changeset 18690:f31c0f34db76

Fixes suggested by Ivo, and failure under non-root operation improved. Original patch by Mark Sanderson < mmp AH kiora P ath P cx > (reworked a bit to try to meet out commit policy).
author gpoirier
date Tue, 13 Jun 2006 07:57:06 +0000
parents 4f22d91b6e85
children b08913965b6a
files libvo/vo_s3fb.c
diffstat 1 files changed, 46 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_s3fb.c	Mon Jun 12 23:09:18 2006 +0000
+++ b/libvo/vo_s3fb.c	Tue Jun 13 07:57:06 2006 +0000
@@ -39,6 +39,12 @@
 
 LIBVO_EXTERN(s3fb)
 
+typedef struct vga_type {
+  int cr38, cr39, cr53;
+  unsigned char *mmio;
+} vga_t;
+
+static vga_t *v = NULL;
      static int fd = -1;
      static struct fb_fix_screeninfo fb_finfo;
      static struct fb_var_screeninfo fb_vinfo;
@@ -80,12 +86,7 @@
 #define S3V_MMIO_REGSIZE           0x8000  /* 32KB */
 #define S3_NEWMMIO_VGABASE      (S3_NEWMMIO_REGBASE + 0x8000)
 
-#define OUTREG(mmreg, value) *(unsigned int *)(&v.mmio[mmreg]) = value
-
-typedef struct vga_type {
-  int cr38, cr39, cr53;
-  unsigned char *mmio;
-} vga_t;
+#define OUTREG(mmreg, value) *(unsigned int *)(&v->mmio[mmreg]) = value
 
 int readcrtc(int reg) {
   outb(reg, 0x3d4);
@@ -97,36 +98,52 @@
   outb(value, 0x3d5);   
 }
 
-int enable(vga_t *v) {
+// enable S3 registers
+int enable() {
   int fd;
 
-  // enable registers
-  if (iopl(3) != 0)
-    return 0;
+  if (v)
+    return 1;
+  errno = 0;
+  v = (vga_t *)malloc(sizeof(vga_t));
+  if (v) {
+    if (ioperm(0x3d4, 2, 1) == 0) {
+      fd = open("/dev/mem", O_RDWR);
+      if (fd != -1) {
+        v->mmio = mmap(0, S3_NEWMMIO_REGSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
+                 S3_MEMBASE + S3_NEWMMIO_REGBASE);
+        close(fd);
+        if (v->mmio != MAP_FAILED) {
   v->cr38 = readcrtc(0x38);
   v->cr39 = readcrtc(0x39);
   v->cr53 = readcrtc(0x53);
   writecrtc(0x38, 0x48);
   writecrtc(0x39, 0xa5);
   writecrtc(0x53, 0x08);
-  fd = open("/dev/mem", O_RDWR);
-  v->mmio = mmap(0, S3_NEWMMIO_REGSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
-                 S3_MEMBASE + S3_NEWMMIO_REGBASE);
-  close(fd);
   return 1;
 }
+      }
+      iopl(0);
+    }
+    free(v);
+    v = NULL;
+  }
+}
 
-void disable(vga_t *v) {
+void disable() {
+  if (v) {
   writecrtc(0x53, v->cr53);
   writecrtc(0x39, v->cr39);
   writecrtc(0x38, v->cr38);
-  iopl(0);
+    ioperm(0x3d4, 2, 0);
   munmap(v->mmio, S3_NEWMMIO_REGSIZE);
+    free(v);
+    v = NULL;
+  }
 }
 
 int yuv_on(int format, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int crop, int xres, int yres, int line_length, int offset) {
   int tmp, pitch, start, src_wc, src_hc, bpp;
-  vga_t v;
 
   if (format == 0 || format == 7)
     bpp = 4;
@@ -151,9 +168,6 @@
   // start is the top left viewable scaler input pixel
   start = offset + crop * pitch + crop * bpp;
    
-  if (!enable(&v))
-    return 0;
-   
   OUTREG(COL_CHROMA_KEY_CONTROL_REG, 0x47000000);
   OUTREG(CHROMA_KEY_UPPER_BOUND_REG, 0x0);
   OUTREG(BLEND_CONTROL_REG, 0x00000020);
@@ -192,18 +206,12 @@
    
   writecrtc(0x67, readcrtc(0x67) | 0x4);
 
-  disable(&v);
-   
   return offset;
 }
 
 void yuv_off() {
-  vga_t v;
-
-  enable(&v);
-
   writecrtc(0x67, readcrtc(0x67) & ~0xc);
-  memset(v.mmio + 0x8180, 0, 0x80);
+  memset(v->mmio + 0x8180, 0, 0x80);
   OUTREG(0x81b8, 0x900);
   OUTREG(0x81bc, 0x900);
   OUTREG(0x81c8, 0x900);
@@ -213,7 +221,6 @@
   OUTREG(0x81fc, 0x00010001);
   writecrtc(0x92, 0);
   writecrtc(0x93, 0);
-  disable(&v);
 }
 
 static int preinit(const char *arg)
@@ -271,9 +278,17 @@
     return -1;
   }
 
-  return 0;
+  if (!enable()) {
+    mp_msg(MSGT_VO, MSGL_FATAL, "s3fb: Couldn't map S3 registers: %s\n", strerror(errno));
+    close(fd);
+    fd = -1;
+    return -1;
 }
 
+  return 0; // Success
+}
+
+/* And close our mess */
 static void uninit(void)
 {
   if (inpage0) {
@@ -282,12 +297,13 @@
     inpage0 = NULL;
   }
    
-  /* And close our mess */
   if(smem) {
     munmap(smem, fb_finfo.smem_len);
     smem = NULL;
   }
 
+  disable();
+
   if(fd != -1) {
     close(fd);
     fd = -1;