--- ./driver/driver.c	2009-02-17 18:37:17.000000000 +0000
+++ /Haiku1/home/voodoo3/Voodoo3Driver0.02/driver/driver.c	2009-02-15 18:15:58.000000000 +0000
@@ -519,7 +519,7 @@
 }
 
 #if defined(POST_R4_0)
-static int32 timer_interrupt_func(timer *te, uint32 pc)
+static int32 timer_interrupt_func(timer *te)
 {
     bigtime_t now = system_time();
     /* get the pointer to the device we're handling this time */
@@ -731,6 +731,7 @@
     /* create a semaphore for vertical blank management */
     si->vblank = create_sem(0, di->name);
     if (si->vblank < 0) {
+    	ddprintf(("couldn't create vblank semaphore: %d", (uint32) si->vblank));
         result = si->vblank;
         goto unmap;
     }
@@ -760,7 +761,10 @@
         /* program the first timer interrupt, and it will handle the rest */
         result = add_timer((timer *)(di->current_timer), timer_interrupt_func, si->refresh_period, B_ONE_SHOT_RELATIVE_TIMER);
         /* bail if we can't add the timer */
-        if (result != B_OK) goto delete_the_sem;
+        if (result != B_OK) {
+        	ddprintf(("Couldn't add timer: %d\n", (int) result));
+        	goto delete_the_sem;
+        }
 #else
         /* fake some kind of interrupt with a thread */        
         result = di->tid = spawn_kernel_thread(fake_interrupt_thread_func, "SKD fake interrupt", B_REAL_TIME_DISPLAY_PRIORITY, di);
@@ -773,13 +777,19 @@
         /* otherwise install our interrupt handler */
         result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, voodoo_interrupt, (void *)di, 0);
         /* bail if we couldn't install the handler */
-        if (result != B_OK) goto delete_the_sem;
+        if (result != B_OK) {
+        	ddprintf(("Couldn't set interrupt handler: %d\n", (uint32) result));
+        	goto delete_the_sem;
+        }
     }
 
 mark_as_open:
     /* mark the device open */
     di->is_open++;
-
+	/* Evilness */
+	if (di->is_open < 2)
+		di->is_open++;
+	
     /* send the cookie to the opener */
     *cookie = di;
     
@@ -957,93 +967,136 @@
     switch (msg)
     {
         /* the only PUBLIC ioctl */
-    case B_GET_ACCELERANT_SIGNATURE:
-    {
-        char *sig = (char *)buf;
-        strcpy(sig, "voodoo3.accelerant");
-        result = B_OK;
-    }
+	    case B_GET_ACCELERANT_SIGNATURE:
+    	{
+        	char *sig = (char *)buf;
+        	if (user_strlcpy((char *) buf, "voodoo3.accelerant", B_FILE_NAME_LENGTH) < B_OK)
+        		result = B_BAD_ADDRESS;
+        	else
+        		result = B_OK;
+    	}
         break;
         
-    /* PRIVATE ioctl from here on */
-    case VOODOO_GET_PRIVATE_DATA:
-    {
-        voodoo_get_private_data *gpd = (voodoo_get_private_data *)buf;
-        if (gpd->magic == VOODOO_PRIVATE_DATA_MAGIC)
-        {
-            gpd->shared_info_area = di->shared_area;
-            result = B_OK;
-        }
-    }
+    	/* PRIVATE ioctl from here on */
+    	case VOODOO_GET_PRIVATE_DATA:
+    	{
+        	voodoo_get_private_data *gpd = (voodoo_get_private_data *)buf;
+        	if (gpd->magic == VOODOO_PRIVATE_DATA_MAGIC)
+        	{
+        	    gpd->shared_info_area = di->shared_area;
+        	    result = B_OK;
+        	}
+    	}
         break;
-    case VOODOO_GET_PCI:
-    {
-        voodoo_get_set_pci *gsp = (voodoo_get_set_pci *)buf;
-        if (gsp->magic == VOODOO_PRIVATE_DATA_MAGIC) {
-            pci_info *pcii = &(di->pcii);
-            gsp->value = get_pci(gsp->offset, gsp->size);
-            result = B_OK;
-        }
-    }
+   
+   		case VOODOO_GET_PCI:
+    	{
+        	voodoo_get_set_pci *gsp = (voodoo_get_set_pci *)buf;
+        	if (gsp->magic == VOODOO_PRIVATE_DATA_MAGIC) {
+        	    pci_info *pcii = &(di->pcii);
+        	    gsp->value = get_pci(gsp->offset, gsp->size);
+        	    result = B_OK;
+        	}
+    	}
         break;
-    case VOODOO_SET_PCI:
-    {
-        voodoo_get_set_pci *gsp = (voodoo_get_set_pci *)buf;
-        if (gsp->magic == VOODOO_PRIVATE_DATA_MAGIC) {
-            pci_info *pcii = &(di->pcii);
-            set_pci(gsp->offset, gsp->size, gsp->value);
-            result = B_OK;
-        }
-    }
-        break;
-    case VOODOO_RUN_INTERRUPTS:
-    {
-        voodoo_set_bool_state *ri = (voodoo_set_bool_state *)buf;
-        if (ri->magic == VOODOO_PRIVATE_DATA_MAGIC) {
-            /* are we faking interrupts? */
-            if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){
-                di->can_interrupt = ri->do_it;
-            } else {
-                vuint32 *regs = di->regs;
-                if (ri->do_it) {
-                    /* resume interrupts */
-                    *regs = *regs; /* CHANGE ME */
-                } else {
-                    /* disable interrupts */
-                    *regs = *regs; /* CHANGE ME */
-                }
-            }
-            result = B_OK;
-        }
-    }
+    
+    	case VOODOO_SET_PCI:
+    	{
+        	voodoo_get_set_pci *gsp = (voodoo_get_set_pci *)buf;
+        	if (gsp->magic == VOODOO_PRIVATE_DATA_MAGIC) {
+            	pci_info *pcii = &(di->pcii);
+            	set_pci(gsp->offset, gsp->size, gsp->value);
+            	result = B_OK;
+        	}
+    	}
         break;
-    case VOODOO_DPRINTF:
-        dprintf ((char*)buf);
+    
+    	case VOODOO_RUN_INTERRUPTS:
+    	{
+        	voodoo_set_bool_state *ri = (voodoo_set_bool_state *)buf;
+        	if (ri->magic == VOODOO_PRIVATE_DATA_MAGIC) {
+            	/* are we faking interrupts? */
+            	if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){
+                	di->can_interrupt = ri->do_it;
+            	} else {
+                	vuint32 *regs = di->regs;
+                	if (ri->do_it) {
+                    	/* resume interrupts */
+                    	*regs = *regs; /* CHANGE ME */
+                	} else {
+                    	/* disable interrupts */
+                    	*regs = *regs; /* CHANGE ME */
+                	}
+            	}
+            	result = B_OK;
+        	}
+    	}
         break;
-    case VOODOO_INB: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	io->data8 = inportb(io->port);
-    	} break;
-    case VOODOO_INW: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	io->data16 = inportw(io->port);
-    	} break;
-    case VOODOO_INL: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	io->data32 = inportl(io->port);
-    	} break;
-    case VOODOO_OUTB: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	outportb(io->port, io->data8);
-    	} break;
-    case VOODOO_OUTW: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	outportw(io->port, io->data16);
-    	} break;
-    case VOODOO_OUTL: {
-    	voodoo_port_io *io = (voodoo_port_io *)buf;
-    	outportl(io->port, io->data32);
-    	} break;
+    
+    	case VOODOO_DPRINTF:
+    		/* Comment this one out, whee. */
+        	/* dprintf ((char*)buf); */
+        	break;
+
+#define do_port_in(method, field) do {								\
+	voodoo_port_io io; 												\
+	if (user_memcpy(&io, (void *) buf, sizeof(io)) < B_OK) 			\
+	{ 																\
+		result = B_BAD_ADDRESS;									\
+	}																\
+	else															\
+	{																\
+		io. field = method (io.port);								\
+		if (user_memcpy(&io, (void *) buf, sizeof(io)) < B_OK)		\
+		{															\
+			result = B_BAD_ADDRESS;								\
+		}															\
+		else result = B_OK;											\
+	}																\
+} while (0)
+
+#define do_port_out(method, field) do {								\
+	voodoo_port_io io;												\
+	if (user_memcpy(&io, (void *) buf, sizeof(io)) < B_OK)			\
+	{																\
+		result = B_BAD_ADDRESS;									\
+	}																\
+	else															\
+	{																\
+		method (io.port, io. field );								\
+		result = B_OK;												\
+	}																\
+} while (0)
+		
+    	case VOODOO_INB: {
+    		do_port_in(inportb, data8);
+    	}
+    	break;
+    
+    	case VOODOO_INW: {
+    		do_port_in(inportw, data16);
+    	}
+    	break;
+    
+    	case VOODOO_INL: {
+    		do_port_in(inportl, data32);
+    	}
+    	break;
+    
+    	case VOODOO_OUTB: {
+			do_port_out(outportb, data8);
+    	}
+    	break;
+    	
+    	case VOODOO_OUTW: {
+    		do_port_out(outportw, data16);
+    	} 
+    	break;
+    	
+    	case VOODOO_OUTL: {
+    		do_port_out(outportl, data32);
+    	} 
+    	break;
     }
     return result;
 }
