-int v3_dev_hook_io(struct vm_device   *dev,
+int v3_dev_hook_io(struct vm_device   * dev,
                   ushort_t            port,
-                  int (*read)(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev),
-                  int (*write)(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev));
+                  int (*read)(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data),
+                  int (*write)(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data));
 
 int v3_dev_unhook_io(struct vm_device   *dev,
                     ushort_t            port);
 
 
 
 static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct pit * state = (struct pit *)dev->private_data;
+    struct pit * state = (struct pit *)priv_data;
     char * val = (char *)dst;
 
     if (length != 1) {
 
 
 static int pit_write_channel(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct pit * state = (struct pit *)dev->private_data;
+    struct pit * state = (struct pit *)priv_data;
     char val = *(char *)src;
 
     if (length != 1) {
 
 
 static int pit_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct pit * state = (struct pit *)dev->private_data;
+    struct pit * state = (struct pit *)priv_data;
     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
 
     PrintDebug("8254 PIT: Write to PIT Command port\n");
     if (state->timer) {
        v3_remove_timer(info, state->timer);
     }
-
-    v3_unhook_io_port(dev->vm, CHANNEL0_PORT);
-    v3_unhook_io_port(dev->vm, CHANNEL1_PORT);
-    v3_unhook_io_port(dev->vm, CHANNEL2_PORT);
-    v3_unhook_io_port(dev->vm, COMMAND_PORT);
-    v3_unhook_io_port(dev->vm, SPEAKER_PORT);
-    
+ 
     V3_Free(state);
     return 0;
 }
        return -1;
     }
 
-    ret |= v3_hook_io_port(vm, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel, dev);
-    ret |= v3_hook_io_port(vm, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel, dev);
-    ret |= v3_hook_io_port(vm, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel, dev);
-    ret |= v3_hook_io_port(vm, COMMAND_PORT, NULL, &pit_write_command, dev);
-    ret |= v3_hook_io_port(vm, SPEAKER_PORT, &pit_read_channel, &pit_write_channel, dev);
+    ret |= v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
+    ret |= v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
+    ret |= v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
+    ret |= v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
+    ret |= v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
 
     if (ret != 0) {
        PrintError("8254 PIT: Failed to hook IO ports\n");
 
 };
 
 
-static int read_master_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int read_master_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
 
     if (length != 1) {
        PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
     return 1;
 }
 
-static int read_master_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int read_master_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
 
     if (length != 1) {
        PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
   
 }
 
-static int read_slave_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int read_slave_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
 
     if (length != 1) {
        PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
     return 1;
 }
 
-static int read_slave_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int read_slave_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
 
     if (length != 1) {
        PrintError("8259 PIC: Invalid Read length  (rd_Slave2)\n");
 }
 
 
-static int write_master_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int write_master_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     uchar_t cw = *(uchar_t *)src;
 
     PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
     return 1;
 }
 
-static int write_master_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int write_master_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     uchar_t cw = *(uchar_t *)src;    
 
     PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
     return 1;
 }
 
-static int write_slave_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int write_slave_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     uchar_t cw = *(uchar_t *)src;
 
     PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
     return 1;
 }
 
-static int write_slave_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int write_slave_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     uchar_t cw = *(uchar_t *)src;    
 
     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
 
 
 
-static int read_elcr_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int read_elcr_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     
     if (length != 1) {
        PrintError("ELCR read of invalid length %d\n", length);
 }
 
 
-static int write_elcr_port(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+static int write_elcr_port(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pic_internal * state = (struct pic_internal *)priv_data;
     
     if (length != 1) {
        PrintError("ELCR read of invalid length %d\n", length);
 
 }
 
 
-static int ata_read(struct vm_device * dev, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
+static int ata_read(struct ide_internal * ide, struct ide_channel * channel, uint8_t * dst, uint_t sect_cnt) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     if (drive->hd_state.accessed == 0) {
 }
 
 
-static int ata_write(struct vm_device * dev, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
+static int ata_write(struct ide_internal * ide, struct ide_channel * channel, uint8_t * src, uint_t sect_cnt) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     PrintDebug("Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
 
 
 
-static int ata_get_lba(struct vm_device * dev, struct ide_channel * channel, uint64_t * lba) {
+static int ata_get_lba(struct ide_internal * ide, struct ide_channel * channel, uint64_t * lba) {
     struct ide_drive * drive = get_selected_drive(channel);
     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
 
 // 28 bit LBA
-static int ata_read_sectors(struct vm_device * dev, struct ide_channel * channel) {
+static int ata_read_sectors(struct ide_internal * ide,  struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
     uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
-    if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) {
-       ide_abort_command(dev, channel);
+    if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
+       ide_abort_command(ide, channel);
        return 0;
     }
 
     
-    if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
+    if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
        PrintError("Could not read disk sector\n");
        return -1;
     }
     drive->irq_flags.rel = 0;
 
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 
     PrintDebug("Returning from read sectors\n");
 
 
 
 // 48 bit LBA
-static int ata_read_sectors_ext(struct vm_device * dev, struct ide_channel * channel) {
+static int ata_read_sectors_ext(struct ide_internal * ide, struct ide_channel * channel) {
     //struct ide_drive * drive = get_selected_drive(channel);
     // The if the sector count == 0 then read 256 sectors (cast up to handle that value)
     //uint32_t sector_count = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
  * however the device can change that value 
  * 
  */
-static int atapi_update_req_len(struct vm_device * dev, struct ide_channel * channel, uint_t xfer_len) {
+static int atapi_update_req_len(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     //   PrintDebug("Updating request length (pre=%d)\n", drive->req_len);
 
 
 // This is for simple commands that don't need to sanity check the req_len
-static void atapi_setup_cmd_resp(struct vm_device * dev, struct ide_channel * channel, uint_t xfer_len) {
+static void atapi_setup_cmd_resp(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     drive->transfer_length = xfer_len;
     channel->status.data_req = 1;
     channel->status.error = 0;
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 }
 
-static void atapi_cmd_error(struct vm_device * dev, struct ide_channel * channel, 
+static void atapi_cmd_error(struct ide_internal * ide, struct ide_channel * channel, 
                     atapi_sense_key_t  sense_key, atapi_add_sense_code_t asc) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     drive->irq_flags.c_d = 1;
     drive->irq_flags.rel = 0;
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 }
 
 
-static void atapi_cmd_nop(struct vm_device * dev, struct ide_channel * channel) {
+static void atapi_cmd_nop(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     channel->status.busy = 0;
     drive->irq_flags.c_d = 1;
     drive->irq_flags.rel = 0;
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 }
 
 
 
-static int atapi_read_chunk(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_read_chunk(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     int ret = drive->ops->read(drive->data_buf, drive->current_lba * ATAPI_BLOCK_SIZE, ATAPI_BLOCK_SIZE, 
 }
 
 
-static int atapi_update_data_buf(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_update_data_buf(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);    
     
     switch (drive->cd_state.atapi_cmd) {
            drive->current_lba++;
 
            // read the next block
-           return atapi_read_chunk(dev, channel);
+           return atapi_read_chunk(ide, channel);
 
        default:
            PrintError("Unhandled ATAPI command in update buffer %x\n", drive->cd_state.atapi_cmd);
 }
 
 static int atapi_read10(struct guest_info * core, 
-                       struct vm_device * dev, 
+                       struct ide_internal * ide,
                        struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_read10_cmd * cmd = (struct atapi_read10_cmd *)(drive->data_buf);
      */
     
     if (xfer_len == 0) {
-       atapi_cmd_nop(dev, channel);
+       atapi_cmd_nop(ide, channel);
        return 0;
     }
     
        PrintError("IDE: xfer len exceeded capacity (lba=%d) (xfer_len=%d) (ReadEnd=%d) (capacity=%d)\n", 
                   lba, xfer_len, lba + xfer_len, 
                   (uint32_t)drive->ops->get_capacity(drive->private_data));
-       atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
-       ide_raise_irq(dev, channel);
+       atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
+       ide_raise_irq(ide, channel);
        return 0;
     }
        
     if (channel->features.dma) {
 
        if (channel->dma_status.active == 1) {
-           if (dma_read(core, dev, channel) == -1) {
+           if (dma_read(core, ide, channel) == -1) {
                PrintError("Error in DMA read for CD Read10 command\n");
                return -1;
            }
        return 0;
     }
 
-    if (atapi_read_chunk(dev, channel) == -1) {
+    if (atapi_read_chunk(ide, channel) == -1) {
        PrintError("IDE: Could not read initial chunk from CD\n");
        return -1;
     }
     // Length of ATAPI buffer sits in cylinder registers
     // This is weird... The host sets this value to say what it would like to transfer, 
     // if it is larger than the correct size, the device shrinks it to the correct size
-    if (atapi_update_req_len(dev, channel, ATAPI_BLOCK_SIZE) == -1) {
+    if (atapi_update_req_len(ide, channel, ATAPI_BLOCK_SIZE) == -1) {
        PrintError("Could not update initial request length\n");
        return -1;
     }
     
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 
     return 0;
 }
 
 
 
-static void atapi_req_sense(struct vm_device * dev, struct ide_channel * channel) {
+static void atapi_req_sense(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
    
-    atapi_setup_cmd_resp(dev, channel, 18);
+    atapi_setup_cmd_resp(ide, channel, 18);
 }
 
 
 
-static int atapi_get_capacity(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_get_capacity(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
     uint32_t capacity = drive->ops->get_capacity(drive->private_data);
     resp->lba = le_to_be_32(capacity);
     resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
 
-    atapi_setup_cmd_resp(dev, channel, sizeof(struct atapi_rd_capacity_resp));
+    atapi_setup_cmd_resp(ide, channel, sizeof(struct atapi_rd_capacity_resp));
 
     return 0;
 }
 
-static int atapi_get_config(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_get_config(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_config_cmd * cmd = (struct atapi_config_cmd *)(drive->data_buf);
     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
        xfer_len = alloc_len;
     }
     
-    atapi_setup_cmd_resp(dev, channel, xfer_len);
+    atapi_setup_cmd_resp(ide, channel, xfer_len);
     
     return 0;
 }
 
 
-static int atapi_read_toc(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_read_toc(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_rd_toc_cmd * cmd = (struct atapi_rd_toc_cmd *)(drive->data_buf);
     uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
            xfer_len = alloc_len;
        }
 
-       atapi_setup_cmd_resp(dev, channel, xfer_len);
+       atapi_setup_cmd_resp(ide, channel, xfer_len);
     } else {
        PrintError("Unhandled Format (%d)\n", cmd->format);
        return -1;
 }
 
 
-static int atapi_mode_sense_cur_values(struct vm_device * dev, struct ide_channel * channel, 
+static int atapi_mode_sense_cur_values(struct ide_internal * ide, struct ide_channel * channel, 
                                       struct atapi_mode_sense_cmd * sense_cmd) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_mode_sense_hdr * hdr = (struct atapi_mode_sense_hdr *)(drive->data_buf);
        case 0x3f:
        default:
            PrintError("ATAPI: Mode sense Page Code not supported (%x)\n", sense_cmd->page_code);
-           atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
-           ide_raise_irq(dev, channel);
+           atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+           ide_raise_irq(ide, channel);
            return 0;
     }
 
 
     drive->transfer_length = (resp_len > alloc_len) ? alloc_len : resp_len;
     drive->transfer_index = 0;
-    atapi_update_req_len(dev, channel, drive->transfer_length);
+    atapi_update_req_len(ide, channel, drive->transfer_length);
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 
     return 0;
 }
 
 
-static int atapi_mode_sense(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_mode_sense(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_mode_sense_cmd * sense_cmd = (struct atapi_mode_sense_cmd *)(drive->data_buf);
 
     switch (sense_cmd->page_ctrl) {
        case 0x00: // Current values
-           return atapi_mode_sense_cur_values(dev, channel, sense_cmd);
+           return atapi_mode_sense_cur_values(ide, channel, sense_cmd);
        case 0x01: // Changeable values
        case 0x02: // default values
        case 0x03: // saved values
 }
 
 
-static int atapi_inquiry(struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_inquiry(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_inquiry_cmd * inquiry_cmd = (struct atapi_inquiry_cmd *)(drive->data_buf);
     uint16_t alloc_len = be_to_le_16(inquiry_cmd->alloc_len);
        xfer_len = alloc_len;
     }
 
-    atapi_setup_cmd_resp(dev, channel, xfer_len);
+    atapi_setup_cmd_resp(ide, channel, xfer_len);
 
     return 0;
 }
 }
 
 
-static int atapi_handle_packet(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel) {
+static int atapi_handle_packet(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
    struct ide_drive * drive = get_selected_drive(channel);
    uint8_t cmd = drive->data_buf[0];
 
 
    switch (cmd) {
        case 0x00: // test unit ready
-          atapi_cmd_nop(dev, channel);
+          atapi_cmd_nop(ide, channel);
 
           /* if drive not ready: 
              atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
           */
           break;
        case 0x03: // request sense
-          atapi_req_sense(dev, channel);
+          atapi_req_sense(ide, channel);
           break;
 
        case 0x1e: // lock door
-          atapi_cmd_nop(dev, channel);
+          atapi_cmd_nop(ide, channel);
           break;
 
        case 0x28: // read(10)
-          if (atapi_read10(core, dev, channel) == -1) {
+          if (atapi_read10(core, ide, channel) == -1) {
               PrintError("IDE: Error in ATAPI read (%x)\n", cmd);
               return -1;
           }
           break;
 
        case 0x5a: // mode sense
-          if (atapi_mode_sense(dev, channel) == -1) {
+          if (atapi_mode_sense(ide, channel) == -1) {
               PrintError("IDE: Error in ATAPI mode sense (%x)\n", cmd);
               return -1;
           }
 
 
        case 0x25: // read cdrom capacity
-          if (atapi_get_capacity(dev, channel) == -1) {
+          if (atapi_get_capacity(ide, channel) == -1) {
               PrintError("IDE: Error getting CDROM capacity (%x)\n", cmd);
               return -1;
           }
 
 
        case 0x43: // read TOC
-          if (atapi_read_toc(dev, channel) == -1) {
+          if (atapi_read_toc(ide, channel) == -1) {
               PrintError("IDE: Error getting CDROM TOC (%x)\n", cmd);
               return -1;
           }
           break;
 
        case 0x46: // get configuration
-          if (atapi_get_config(dev, channel) == -1) {
+          if (atapi_get_config(ide, channel) == -1) {
               PrintError("IDE: Error getting CDROM Configuration (%x)\n", cmd);
               return -1;
           }
        case 0x51: // read disk info
           // no-op to keep the Linux CD-ROM driver happy
           PrintDebug("Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
-          atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
-          ide_raise_irq(dev, channel);
+          atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+          ide_raise_irq(ide, channel);
           break;
 
        case 0x12: // inquiry
-          if (atapi_inquiry(dev, channel) == -1) {
+          if (atapi_inquiry(ide, channel) == -1) {
               PrintError("IDE: Error in ATAPI inquiry (%x)\n", cmd);
               return -1;
           }
 
        default:
           PrintError("Unhandled ATAPI command %x\n", cmd);
-          atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
-          ide_raise_irq(dev, channel);
+          atapi_cmd_error(ide, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+          ide_raise_irq(ide, channel);
           return -1;
    }
    
 
 };
 
 static int handle_info_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = priv_data;
-    struct debug_state * state = (struct debug_state *)dev->private_data;
+    struct debug_state * state = (struct debug_state *)priv_data;
 
     state->info_buf[state->info_offset++] = *(char*)src;
 
 
 
 static int handle_debug_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = priv_data;
-    struct debug_state * state = (struct debug_state *)dev->private_data;
+    struct debug_state * state = (struct debug_state *)priv_data;
 
     state->debug_buf[state->debug_offset++] = *(char*)src;
 
 
 
 static int handle_console_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = priv_data;
-    struct debug_state * state = (struct debug_state *)dev->private_data;
+    struct debug_state * state = (struct debug_state *)priv_data;
 
     state->cons_buf[state->cons_offset++] = *(char *)src;
 
 
 
 static int handle_gen_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data)  {
-    //struct vm_device * dev = priv_data;
     
     switch (length) {
        case 1:
 static int debug_free(struct vm_device * dev) {
     struct debug_state * state = dev->private_data;
 
-    v3_unhook_io_port(dev->vm, BOCHS_PORT1);
-    v3_unhook_io_port(dev->vm, BOCHS_PORT2);
-    v3_unhook_io_port(dev->vm, BOCHS_INFO_PORT);
-    v3_unhook_io_port(dev->vm, BOCHS_DEBUG_PORT);
-
     V3_Free(state);
 
     return 0;
     memset(state->cons_buf, 0, BUF_SIZE);
 
 
-    ret |= v3_hook_io_port(vm, BOCHS_PORT1,  NULL, &handle_gen_write, dev);
-    ret |= v3_hook_io_port(vm, BOCHS_PORT2, NULL, &handle_gen_write, dev);
-    ret |= v3_hook_io_port(vm, BOCHS_INFO_PORT, NULL, &handle_info_write, dev);
-    ret |= v3_hook_io_port(vm, BOCHS_DEBUG_PORT, NULL, &handle_debug_write, dev);
-    ret |= v3_hook_io_port(vm, BOCHS_CONSOLE_PORT, NULL, &handle_console_write, dev);
+    ret |= v3_dev_hook_io(dev, BOCHS_PORT1,  NULL, &handle_gen_write);
+    ret |= v3_dev_hook_io(dev, BOCHS_PORT2, NULL, &handle_gen_write);
+    ret |= v3_dev_hook_io(dev, BOCHS_INFO_PORT, NULL, &handle_info_write);
+    ret |= v3_dev_hook_io(dev, BOCHS_DEBUG_PORT, NULL, &handle_debug_write);
+    ret |= v3_dev_hook_io(dev, BOCHS_CONSOLE_PORT, NULL, &handle_console_write);
     
     if (ret != 0) {
        PrintError("Could not hook Bochs Debug IO Ports\n");
 
 }
 
 static int video_read_port(struct guest_info * core, uint16_t port, void * dest, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    struct video_internal * video_state = priv_data;
 
 
     PrintDebug("Video: Read port 0x%x\n", port);
 
 
 static int video_write_port(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    struct video_internal * video_state = priv_data;
 
 
     PrintDebug("Video: write port 0x%x...\n", port);
 
 
 static int crtc_data_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    struct video_internal * video_state = priv_data;
     uint8_t val = *(uint8_t *)src;
     uint_t index = video_state->crtc_index_reg;
 
 
 
 static int crtc_index_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    struct video_internal * video_state = priv_data;
     
     if (length > 2) {
        PrintError("Invalid write length for crtc index register port: %d (0x%x)\n",
     }
 
     if (length == 2) {
-       if (crtc_data_write(core, port + 1, src + 1, length - 1, dev) != (length - 1)) {
+       if (crtc_data_write(core, port + 1, src + 1, length - 1, video_state) != (length - 1)) {
            PrintError("could not handle implicit crtc data write\n");
            return -1;
        }
 
 static int free_device(struct vm_device * dev) {
     struct video_internal * video_state = (struct video_internal *)dev->private_data;
-    struct v3_vm_info * vm = dev->vm;
 
     if (video_state->framebuf_pa) {
        V3_FreePages((void *)(video_state->framebuf_pa), (FRAMEBUF_SIZE / 4096));
 
     v3_unhook_mem(dev->vm, V3_MEM_CORE_ANY, START_ADDR);
 
-    v3_unhook_io_port(vm, 0x3b0);
-    v3_unhook_io_port(vm, 0x3b1);
-    v3_unhook_io_port(vm, 0x3b2);
-    v3_unhook_io_port(vm, 0x3b3);
-    v3_unhook_io_port(vm, 0x3b4);
-    v3_unhook_io_port(vm, 0x3b5);
-    v3_unhook_io_port(vm, 0x3b6);
-    v3_unhook_io_port(vm, 0x3b7);
-    v3_unhook_io_port(vm, 0x3b8);
-    v3_unhook_io_port(vm, 0x3b9);
-    v3_unhook_io_port(vm, 0x3ba);
-    v3_unhook_io_port(vm, 0x3bb);
-    v3_unhook_io_port(vm, 0x3c0);
-    v3_unhook_io_port(vm, 0x3c1);
-    v3_unhook_io_port(vm, 0x3c2);
-    v3_unhook_io_port(vm, 0x3c3);
-    v3_unhook_io_port(vm, 0x3c4);
-    v3_unhook_io_port(vm, 0x3c5);
-    v3_unhook_io_port(vm, 0x3c6);
-    v3_unhook_io_port(vm, 0x3c7);
-    v3_unhook_io_port(vm, 0x3c8);
-    v3_unhook_io_port(vm, 0x3c9);
-    v3_unhook_io_port(vm, 0x3ca);
-    v3_unhook_io_port(vm, 0x3cb);
-    v3_unhook_io_port(vm, 0x3cc);
-    v3_unhook_io_port(vm, 0x3cd);
-    v3_unhook_io_port(vm, 0x3ce);
-    v3_unhook_io_port(vm, 0x3cf);
-    v3_unhook_io_port(vm, 0x3d0);
-    v3_unhook_io_port(vm, 0x3d1);
-    v3_unhook_io_port(vm, 0x3d2);
-    v3_unhook_io_port(vm, 0x3d3);
-    v3_unhook_io_port(vm, 0x3d4);
-    v3_unhook_io_port(vm, 0x3d5);
-    v3_unhook_io_port(vm, 0x3d6);
-    v3_unhook_io_port(vm, 0x3d7);
-    v3_unhook_io_port(vm, 0x3d8);
-    v3_unhook_io_port(vm, 0x3d9);
-    v3_unhook_io_port(vm, 0x3da);
-    v3_unhook_io_port(vm, 0x3db);
-    v3_unhook_io_port(vm, 0x3dc);
-    v3_unhook_io_port(vm, 0x3dd);
-    v3_unhook_io_port(vm, 0x3de);
-    v3_unhook_io_port(vm, 0x3df);
 
     V3_Free(video_state);
 
     }
 
 
-    v3_hook_io_port(vm, 0x3b0, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b1, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b2, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b3, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b4, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b5, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b6, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b7, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b8, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3b9, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3ba, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3bb, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c0, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c1, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c2, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c3, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c4, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c5, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c6, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c7, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c8, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3c9, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3ca, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3cb, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3cc, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3cd, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3ce, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3cf, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d0, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d1, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d2, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d3, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d4, &video_read_port, &crtc_index_write, dev);
-    v3_hook_io_port(vm, 0x3d5, &video_read_port, &crtc_data_write, dev);
-    v3_hook_io_port(vm, 0x3d6, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d7, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d8, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3d9, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3da, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3db, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3dc, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3dd, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3de, &video_read_port, &video_write_port, dev);
-    v3_hook_io_port(vm, 0x3df, &video_read_port, &video_write_port, dev);
+    v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d4, &video_read_port, &crtc_index_write);
+    v3_dev_hook_io(dev, 0x3d5, &video_read_port, &crtc_data_write);
+    v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3da, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
 
 
     return 0;
 
              GENERIC_PRINT_AND_IGNORE} generic_mode_t;
 
 struct generic_internal {
-    struct list_head port_list;
-    uint_t num_port_ranges;
-
 };
 
 
 
 static int generic_free(struct vm_device * dev) {
     struct generic_internal * state = (struct generic_internal *)(dev->private_data);
-    struct port_range * tmp;
-    struct port_range * cur;
 
     PrintDebug("generic: deinit_device\n");
 
-    list_for_each_entry_safe(cur, tmp, &(state->port_list), range_link) {
-       uint_t i;
-
-       PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
-                  cur->start, cur->end);
-       
-       for (i = cur->start; i <= cur->end; i++) {
-           if (v3_unhook_io_port(dev->vm, i)) {
-               PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", i);
-           }
-       }
-
-       list_del(&(cur->range_link));
-       state->num_port_ranges--;
-       V3_Free(cur);
-    }
-
     V3_Free(state);
     return 0;
 }
 
 
 static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, generic_mode_t mode) {
-    struct generic_internal * state = (struct generic_internal *)(dev->private_data);
-    struct port_range * range = (struct port_range *)V3_Malloc(sizeof(struct port_range));
     uint_t i = 0;
 
-    range->start = start;
-    range->end = end;
-    range->mode = mode;
-      
     PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %s\n", 
               start, end, 
               (mode == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
     
     for (i = start; i <= end; i++) { 
        if (mode == GENERIC_PRINT_AND_PASSTHROUGH) { 
-           if (v3_hook_io_port(dev->vm, i, 
+           if (v3_dev_hook_io(dev, i, 
                                &generic_read_port_passthrough, 
-                               &generic_write_port_passthrough, dev) == -1) { 
+                               &generic_write_port_passthrough) == -1) { 
                PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
                return -1;
            }
        } else if (mode == GENERIC_PRINT_AND_IGNORE) { 
-           if (v3_hook_io_port(dev->vm, i, 
+           if (v3_dev_hook_io(dev, i, 
                                &generic_read_port_ignore, 
-                               &generic_write_port_ignore, dev) == -1) { 
+                               &generic_write_port_ignore) == -1) { 
                PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
                return -1;
            }
        } 
     }
-
-    list_add(&(range->range_link), &(state->port_list));
-    state->num_port_ranges++;
     
     return 0;
 }
     }
     
     memset(state, 0, sizeof(struct generic_internal));
-
-    INIT_LIST_HEAD(&(state->port_list));
-    state->num_port_ranges = 0;
     
     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
 
 
 
 
 static int io_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
-    //    struct vm_device * dev = priv_data;
     PrintError("Unhandled read on port %x\n", port);
     return -1;
 }
 
 static int io_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
-    //    struct vm_device * dev = priv_data;
     PrintError("Unhandled write on port %x\n", port);
     return -1;
 }
 
 static int i440_free(struct vm_device * dev) {
     struct i440_state * state = dev->private_data;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-       v3_unhook_io_port(dev->vm, 0x0cf8 + i);
-       v3_unhook_io_port(dev->vm, 0x0cfc + i);
-    }
 
     // unregister from PCI
 
     }
 
     for (i = 0; i < 4; i++) {
-       v3_hook_io_port(vm, 0x0cf8 + i, &io_read, &io_write, dev);
-       v3_hook_io_port(vm, 0x0cfc + i, &io_read, &io_write, dev);
+       v3_dev_hook_io(dev, 0x0cf8 + i, &io_read, &io_write);
+       v3_dev_hook_io(dev, 0x0cfc + i, &io_read, &io_write);
     }
 
     for (i = 0; i < 6; i++) {
 
     struct vm_device * pci_bus;
 
     struct pci_device * ide_pci;
+
+    struct v3_vm_info * vm;
 };
 
 
 
 
 /* Drive Commands */
-static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
+static void ide_raise_irq(struct ide_internal * ide, struct ide_channel * channel) {
     if (channel->ctrl_reg.irq_disable == 0) {
        //        PrintError("Raising IDE Interrupt %d\n", channel->irq);
         channel->dma_status.int_gen = 1;
-        v3_raise_irq(dev->vm, channel->irq);
+        v3_raise_irq(ide->vm, channel->irq);
     }
 }
 
 }
 
 
-static void ide_abort_command(struct vm_device * dev, struct ide_channel * channel) {
+static void ide_abort_command(struct ide_internal * ide, struct ide_channel * channel) {
     channel->status.val = 0x41; // Error + ready
     channel->error_reg.val = 0x04; // No idea...
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 }
 
 
-static int dma_read(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel);
-static int dma_write(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel);
+static int dma_read(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel);
+static int dma_write(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel);
 
 
 /* ATAPI functions */
 #endif
 
 /* IO Operations */
-static int dma_read(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel) {
+static int dma_read(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     // This is at top level scope to do the EOT test at the end
     struct ide_dma_prd prd_entry = {};
     // Read a sector/block at a time until the prd entry is full.
 
 #ifdef CONFIG_DEBUG_IDE
-    print_prd_table(dev, channel);
+    print_prd_table(ide, channel);
 #endif
 
     PrintDebug("DMA read for %d bytes\n", bytes_left);
                bytes_to_write = (prd_bytes_left > HD_SECTOR_SIZE) ? HD_SECTOR_SIZE : prd_bytes_left;
 
 
-               if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
+               if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
                    PrintError("Failed to read next disk sector\n");
                    return -1;
                }
                if (atapi_cmd_is_data_op(drive->cd_state.atapi_cmd)) {
                    bytes_to_write = (prd_bytes_left > ATAPI_BLOCK_SIZE) ? ATAPI_BLOCK_SIZE : prd_bytes_left;
 
-                   if (atapi_read_chunk(dev, channel) == -1) {
+                   if (atapi_read_chunk(ide, channel) == -1) {
                        PrintError("Failed to read next disk sector\n");
                        return -1;
                    }
        channel->dma_status.err = 0;
     }
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 
     return 0;
 }
 
 
-static int dma_write(struct guest_info * core, struct vm_device * dev, struct ide_channel * channel) {
+static int dma_write(struct guest_info * core, struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     // This is at top level scope to do the EOT test at the end
     struct ide_dma_prd prd_entry = {};
            PrintDebug("\t DMA ret=%d (prd_bytes_left=%d) (bytes_left=%d)\n", ret, prd_bytes_left, bytes_left);
 
 
-           if (ata_write(dev, channel, drive->data_buf, 1) == -1) {
+           if (ata_write(ide, channel, drive->data_buf, 1) == -1) {
                PrintError("Failed to write data to disk\n");
                return -1;
            }
        channel->dma_status.err = 0;
     }
 
-    ide_raise_irq(dev, channel);
+    ide_raise_irq(ide, channel);
 
     return 0;
 }
 #define DMA_CHANNEL_FLAG  0x08
 
 static int write_dma_port(struct guest_info * core, ushort_t port, void * src, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_internal * ide = (struct ide_internal *)private_data;
     uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
     uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
     struct ide_channel * channel = &(ide->channels[channel_flag]);
 
                if (channel->dma_cmd.read == 1) {
                    // DMA Read
-                   if (dma_read(core, dev, channel) == -1) {
+                   if (dma_read(core, ide, channel) == -1) {
                        PrintError("Failed DMA Read\n");
                        return -1;
                    }
                } else {
                    // DMA write
-                   if (dma_write(core, dev, channel) == -1) {
+                   if (dma_write(core, ide, channel) == -1) {
                        PrintError("Failed DMA Write\n");
                        return -1;
                    }
 
 
 static int read_dma_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_internal * ide = (struct ide_internal *)private_data;
     uint16_t port_offset = port & (DMA_CHANNEL_FLAG - 1);
     uint_t channel_flag = (port & DMA_CHANNEL_FLAG) >> 3;
     struct ide_channel * channel = &(ide->channels[channel_flag]);
 
 
 
-static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int write_cmd_port(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct ide_internal * ide = priv_data;
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
 
                drive_reset(drive);
 
                // JRL: Should we abort here?
-               ide_abort_command(dev, channel);
+               ide_abort_command(ide, channel);
            } else {
                
                atapi_identify_device(drive);
                channel->error_reg.val = 0;
                channel->status.val = 0x58; // ready, data_req, seek_complete
            
-               ide_raise_irq(dev, channel);
+               ide_raise_irq(ide, channel);
            }
            break;
        case 0xec: // Identify Device
                drive_reset(drive);
 
                // JRL: Should we abort here?
-               ide_abort_command(dev, channel);
+               ide_abort_command(ide, channel);
            } else {
                ata_identify_device(drive);
 
                channel->error_reg.val = 0;
                channel->status.val = 0x58;
 
-               ide_raise_irq(dev, channel);
+               ide_raise_irq(ide, channel);
            }
            break;
 
        case 0xa0: // ATAPI Command Packet
            if (drive->drive_type != BLOCK_CDROM) {
-               ide_abort_command(dev, channel);
+               ide_abort_command(ide, channel);
            }
            
            drive->sector_count = 1;
        case 0x21: // Read Sectors without Retry
            drive->hd_state.cur_sector_num = 1;
 
-           if (ata_read_sectors(dev, channel) == -1) {
+           if (ata_read_sectors(ide, channel) == -1) {
                PrintError("Error reading sectors\n");
                return -1;
            }
        case 0x24: // Read Sectors Extended
            drive->hd_state.cur_sector_num = 1;
 
-           if (ata_read_sectors_ext(dev, channel) == -1) {
+           if (ata_read_sectors_ext(ide, channel) == -1) {
                PrintError("Error reading extended sectors\n");
                return -1;
            }
        case 0xc9: { // Read DMA
            uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
-           if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) {
-               ide_abort_command(dev, channel);
+           if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
+               ide_abort_command(ide, channel);
                return 0;
            }
            
 
            if (channel->dma_status.active == 1) {
                // DMA Read
-               if (dma_read(core, dev, channel) == -1) {
+               if (dma_read(core, ide, channel) == -1) {
                    PrintError("Failed DMA Read\n");
                    return -1;
                }
        case 0xca: { // Write DMA
            uint32_t sect_cnt = (drive->sector_count == 0) ? 256 : drive->sector_count;
 
-           if (ata_get_lba(dev, channel, &(drive->current_lba)) == -1) {
-               ide_abort_command(dev, channel);
+           if (ata_get_lba(ide, channel, &(drive->current_lba)) == -1) {
+               ide_abort_command(ide, channel);
                return 0;
            }
 
 
            if (channel->dma_status.active == 1) {
                // DMA Write
-               if (dma_write(core, dev, channel) == -1) {
+               if (dma_write(core, ide, channel) == -1) {
                    PrintError("Failed DMA Write\n");
                    return -1;
                }
        case 0x99: // Sleep Now 2
            channel->status.val = 0;
            channel->status.ready = 1;
-           ide_raise_irq(dev, channel);
+           ide_raise_irq(ide, channel);
            break;
 
        case 0xef: // Set Features
            channel->status.ready = 1;
            channel->status.seek_complete = 1;
            
-           ide_raise_irq(dev, channel);
+           ide_raise_irq(ide, channel);
            break;
 
        case 0x91:  // Initialize Drive Parameters
            channel->status.error = 0;
            channel->status.ready = 1;
            channel->status.seek_complete = 1;
-           ide_raise_irq(dev, channel);
+           ide_raise_irq(ide, channel);
            break;
        case 0xc6: { // Set multiple mode (IDE Block mode) 
            // This makes the drive transfer multiple sectors before generating an interrupt
            uint32_t tmp_sect_num = drive->sector_num; // GCC SUCKS
 
            if (tmp_sect_num > MAX_MULT_SECTORS) {
-               ide_abort_command(dev, channel);
+               ide_abort_command(ide, channel);
                break;
            }
 
            channel->status.ready = 1;
            channel->status.error = 0;
 
-           ide_raise_irq(dev, channel);
+           ide_raise_irq(ide, channel);
 
            break;
        }
 }
 
 
-static int write_data_port(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int write_data_port(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct ide_internal * ide = priv_data;
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
 
                return -1;
                
            case 0xa0: // ATAPI packet command
-               if (atapi_handle_packet(core, dev, channel) == -1) {
+               if (atapi_handle_packet(core, ide, channel) == -1) {
                    PrintError("Error handling ATAPI packet\n");
                    return -1;
                }
 }
 
 
-static int read_hd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+static int read_hd_data(uint8_t * dst, uint_t length, struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     int data_offset = drive->transfer_index % HD_SECTOR_SIZE;
 
     if ((data_offset == 0) && (drive->transfer_index > 0)) {
        drive->current_lba++;
 
-       if (ata_read(dev, channel, drive->data_buf, 1) == -1) {
+       if (ata_read(ide, channel, drive->data_buf, 1) == -1) {
            PrintError("Could not read next disk sector\n");
            return -1;
        }
        drive->irq_flags.io_dir = 1;
        channel->status.busy = 0;
 
-       ide_raise_irq(dev, channel);
+       ide_raise_irq(ide, channel);
     }
 
 
 
 
 
-static int read_cd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+static int read_cd_data(uint8_t * dst, uint_t length, struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     int data_offset = drive->transfer_index % ATAPI_BLOCK_SIZE;
     int req_offset = drive->transfer_index % drive->req_len;
 
     
     if ((data_offset == 0) && (drive->transfer_index > 0)) {
-       if (atapi_update_data_buf(dev, channel) == -1) {
+       if (atapi_update_data_buf(ide, channel) == -1) {
            PrintError("Could not update CDROM data buffer\n");
            return -1;
        }
            drive->irq_flags.c_d = 0;
 
            // Update the request length in the cylinder regs
-           if (atapi_update_req_len(dev, channel, drive->transfer_length - drive->transfer_index) == -1) {
+           if (atapi_update_req_len(ide, channel, drive->transfer_length - drive->transfer_index) == -1) {
                PrintError("Could not update request length after completed increment\n");
                return -1;
            }
        drive->irq_flags.io_dir = 1;
        channel->status.busy = 0;
 
-       ide_raise_irq(dev, channel);
+       ide_raise_irq(ide, channel);
     }
 
     return length;
 }
 
 
-static int read_drive_id( uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+static int read_drive_id( uint8_t * dst, uint_t length, struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
 
     channel->status.busy = 0;
 }
 
 
-static int ide_read_data_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int ide_read_data_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct ide_internal * ide = priv_data;
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
 
 
     if ((channel->cmd_reg == 0xec) ||
        (channel->cmd_reg == 0xa1)) {
-       return read_drive_id((uint8_t *)dst, length, dev, channel);
+       return read_drive_id((uint8_t *)dst, length, ide, channel);
     }
 
     if (drive->drive_type == BLOCK_CDROM) {
-       if (read_cd_data((uint8_t *)dst, length, dev, channel) == -1) {
+       if (read_cd_data((uint8_t *)dst, length, ide, channel) == -1) {
            PrintError("IDE: Could not read CD Data\n");
            return -1;
        }
     } else if (drive->drive_type == BLOCK_DISK) {
-       if (read_hd_data((uint8_t *)dst, length, dev, channel) == -1) {
+       if (read_hd_data((uint8_t *)dst, length, ide, channel) == -1) {
            PrintError("IDE: Could not read HD Data\n");
            return -1;
        }
     return length;
 }
 
-static int write_port_std(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int write_port_std(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct ide_internal * ide = priv_data;
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
            
 }
 
 
-static int read_port_std(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int read_port_std(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct ide_internal * ide = priv_data;
     struct ide_channel * channel = get_selected_channel(ide, port);
     struct ide_drive * drive = get_selected_drive(channel);
     
     return 0;
 }
 
-static int init_ide_state(struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+static int init_ide_state(struct ide_internal * ide) {
     int i;
 
     /* 
 
     memset(ide, 0, sizeof(struct ide_internal));
 
+    ide->vm = vm;
 
     ide->pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
 
        return -1;
     }
 
-    if (init_ide_state(dev) == -1) {
+    if (init_ide_state(ide) == -1) {
        PrintError("Failed to initialize IDE state\n");
        v3_detach_device(dev);
        return -1;
 
     struct queue kbd_queue;
     struct queue mouse_queue;
 
+    struct v3_vm_info * vm;
+
     v3_lock_t kb_lock;
 };
 
 
-static int update_kb_irq(struct vm_device * dev) {
-    struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+static int update_kb_irq(struct keyboard_internal * state) {
     int irq_num = 0;
 
 
        state->status.out_buf_full = 1;
        
        if (state->cmd.irq_en == 1) { 
-           v3_raise_irq(dev->vm, irq_num);
+           v3_raise_irq(state->vm, irq_num);
        }
     }
 
  * If we keep reading an empty queue we return the last queue entry
  */
 
-static int push_to_output_queue(struct vm_device * dev, uint8_t value, uint8_t cmd, uint8_t mouse) {
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+static int push_to_output_queue(struct keyboard_internal * state, uint8_t value, uint8_t cmd, uint8_t mouse) {
     struct queue * q = NULL;
 
 
     q->count++;
 
 
-    update_kb_irq(dev);
+    update_kb_irq(state);
 
     return 0;
 }
 
 
 
-static int pull_from_output_queue(struct vm_device * dev, uint8_t * value) {
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+static int pull_from_output_queue(struct keyboard_internal * state, uint8_t * value) {
     struct queue * q = NULL;
 
     if (state->kbd_queue.count > 0) {
     PrintDebug("Read from Queue: %x\n", *value);
     PrintDebug("QStart=%d, QEnd=%d\n", q->start, q->end);
 
-    update_kb_irq(dev);
+    update_kb_irq(state);
 
     return 0;
 }
 static int key_event_handler(struct v3_vm_info * vm, 
                             struct v3_keyboard_event * evt, 
                             void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+    struct keyboard_internal * state = (struct keyboard_internal *)private_data;
 
     PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code);
 
     if ( (state->status.enabled == 1)      // onboard is enabled
         && (state->cmd.disable == 0) )  {   // keyboard is enabled
     
-       push_to_output_queue(dev, evt->scan_code, DATA, KEYBOARD);
+       push_to_output_queue(state, evt->scan_code, DATA, KEYBOARD);
     }
 
     v3_unlock_irqrestore(state->kb_lock, irq_state);
 static int mouse_event_handler(struct v3_vm_info * vm, 
                               struct v3_mouse_event * evt, 
                               void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+    struct keyboard_internal * kbd = (struct keyboard_internal *)private_data;
     int ret = 0;
 
     PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n",
               evt->data[0], evt->data[1], evt->data[2]);
   
-    addr_t irq_state = v3_lock_irqsave(state->kb_lock);
+    addr_t irq_state = v3_lock_irqsave(kbd->kb_lock);
 
-    switch (state->mouse_state) { 
+    switch (kbd->mouse_state) { 
        case STREAM:
 
-           if (state->cmd.mouse_disable == 0) {
-               push_to_output_queue(dev, evt->data[0], DATA, MOUSE);
-               push_to_output_queue(dev, evt->data[1], DATA, MOUSE);
-               push_to_output_queue(dev, evt->data[2], DATA, MOUSE);
+           if (kbd->cmd.mouse_disable == 0) {
+               push_to_output_queue(kbd, evt->data[0], DATA, MOUSE);
+               push_to_output_queue(kbd, evt->data[1], DATA, MOUSE);
+               push_to_output_queue(kbd, evt->data[2], DATA, MOUSE);
            }
            break;
        default:
     }
 
 
-    v3_unlock_irqrestore(state->kb_lock, irq_state);
+    v3_unlock_irqrestore(kbd->kb_lock, irq_state);
 
     return ret;
 }
 
 
-static int keyboard_reset_device(struct vm_device * dev) {
-    struct keyboard_internal * data = (struct keyboard_internal *)(dev->private_data);
+static int keyboard_reset_device(struct keyboard_internal * kbd) {
   
-    memset(data, 0, sizeof(struct keyboard_internal));
+    memset(kbd, 0, sizeof(struct keyboard_internal));
 
-    data->state = NORMAL;
-    data->mouse_state = STREAM;
+    kbd->state = NORMAL;
+    kbd->mouse_state = STREAM;
 
 
     // PS2, keyboard+mouse enabled, generic translation    
-    data->cmd.val = 0;
+    kbd->cmd.val = 0;
 
-    data->cmd.irq_en = 1;
-    data->cmd.mouse_irq_en = 1;
-    data->cmd.self_test_ok = 1;
+    kbd->cmd.irq_en = 1;
+    kbd->cmd.mouse_irq_en = 1;
+    kbd->cmd.self_test_ok = 1;
     /** **/
 
 
     // buffers empty, no errors
-    data->status.val = 0; 
+    kbd->status.val = 0; 
 
-    data->status.self_test_ok = 1; // self-tests passed
-    data->status.enabled = 1;// keyboard ready
+    kbd->status.self_test_ok = 1; // self-tests passed
+    kbd->status.enabled = 1;// keyboard ready
     /** **/
 
     
-    data->output_byte = 0;  //  ?
+    kbd->output_byte = 0;  //  ?
 
-    data->input_byte = INPUT_RAM;  // we have some
+    kbd->input_byte = INPUT_RAM;  // we have some
     // also display=color, jumper 0, keyboard enabled 
 
     PrintDebug("keyboard: reset device\n");
 
 
 
-static int keyboard_start_device(struct vm_device * dev) {
-    PrintDebug("keyboard: start device\n");
-    return 0;
-}
-
-
-static int keyboard_stop_device(struct vm_device * dev) {
-    PrintDebug("keyboard: stop device\n");
-    return 0;
-}
 
 
 
-static int mouse_write_output(struct vm_device * dev, uint8_t data) {
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
 
-    switch (state->mouse_state) { 
+static int mouse_write_output(struct keyboard_internal * kbd, uint8_t data) {
+    switch (kbd->mouse_state) { 
        case NORMAL:
            switch (data) {
 
                case 0xff: //reset
-                   if (state->mouse_enabled == 0) {
-                       push_to_output_queue(dev, 0xfe, DATA, MOUSE) ;   // no mouse!
+                   if (kbd->mouse_enabled == 0) {
+                       push_to_output_queue(kbd, 0xfe, DATA, MOUSE) ;   // no mouse!
                    } else {
-                       push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
-                       push_to_output_queue(dev, 0xaa, DATA, MOUSE) ; 
-                       push_to_output_queue(dev, 0x00, DATA, MOUSE) ; 
+                       push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
+                       push_to_output_queue(kbd, 0xaa, DATA, MOUSE) ; 
+                       push_to_output_queue(kbd, 0x00, DATA, MOUSE) ; 
                    }
                    break;
 
 /*             case 0xfe: //resend */
-/*                 PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;  */
+/*                 PushToOutputQueue(kbd, 0xfa, OVERWRITE, DATA, MOUSE) ;  */
 /*                 PrintDebug(" mouse resend begins "); */
-/*                 state->mouse_done_after_ack = 0; */
-/*                 state->mouse_needs_ack = 0; */
-/*                 state->mouse_state = STREAM1; */
+/*                 kbd->mouse_done_after_ack = 0; */
+/*                 kbd->mouse_needs_ack = 0; */
+/*                 kbd->mouse_state = STREAM1; */
 /*                 return 0;  // not done */
 /*                 break; */
       
                case 0xf6: // set defaults
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse set defaults ");
 
                    break;
       
                case 0xf5: // disable data reporting 
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse disable data reporting ");
                    break;
       
                case 0xf4: // enable data reporting 
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse enable data reporting ");
                    break;
       
                case 0xf3: // set sample rate
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
-                   state->mouse_state = SAMPLE;
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
+                   kbd->mouse_state = SAMPLE;
                    PrintDebug(" mouse set sample rate begins ");
                    break;
       
                case 0xf2: // get device id
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
-                   push_to_output_queue(dev, 0x0,  DATA, MOUSE); 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, 0x0,  DATA, MOUSE); 
                    PrintDebug(" mouse get device id begins ");
                    break;
       
                case 0xf0: // set remote mode
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse set remote mode  ");
                    break;
 
                case 0xee: // set wrap mode
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintError(" mouse set wrap mode (ignored)  ");
                    break;
 
                case 0xec: // reset wrap mode
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintError(" mouse reset wrap mode (ignored)  ");
                    break;
 
                case 0xeb: // read data
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintError(" mouse switch to wrap mode (ignored)  ");
                    break;
       
                case 0xea: // set stream mode
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse set stream mode  ");
                    break;
 
                case 0xe9: // status request
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
-                   push_to_output_queue(dev, 0x00, DATA, MOUSE); 
-                   push_to_output_queue(dev, 0x00, DATA, MOUSE);
-                   push_to_output_queue(dev, 0x00, DATA, MOUSE); 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, 0x00, DATA, MOUSE); 
+                   push_to_output_queue(kbd, 0x00, DATA, MOUSE);
+                   push_to_output_queue(kbd, 0x00, DATA, MOUSE); 
                    PrintDebug(" mouse status request begins  ");
                    break;
 
                case 0xe8: // set resolution
-                   push_to_output_queue(dev, MOUSE_ACK,  DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK,  DATA, MOUSE) ; 
                    PrintDebug(" mouse set resolution begins  ");
-                   state->mouse_state = SET_RES;
+                   kbd->mouse_state = SET_RES;
                    break;
 
                case 0xe7: // set scaling 2:1
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse set scaling 2:1 ");
                    break;
 
                case 0xe6: // set scaling 1:1
-                   push_to_output_queue(dev, MOUSE_ACK, DATA, MOUSE) ; 
+                   push_to_output_queue(kbd, MOUSE_ACK, DATA, MOUSE) ; 
                    PrintDebug(" mouse set scaling 1:1 ");
                    break;
       
                default:
-                   PrintDebug(" receiving unknown mouse command (0x%x) in acceptable state ", data);
+                   PrintDebug(" receiving unknown mouse command (0x%x) in acceptable kbd ", data);
                    break;
            }
 
        case SAMPLE:
        case SET_RES:
        default:
-           PrintDebug(" receiving mouse output in unhandled state (0x%x) ", state->mouse_state);
+           PrintDebug(" receiving mouse output in unhandled kbd (0x%x) ", kbd->mouse_state);
            return -1;
     }
 
 
 
 #if KEYBOARD_DEBUG_80H
-static int keyboard_write_delay(ushort_t port, void * src,  uint_t length, struct vm_device * dev) {
+static int keyboard_write_delay(ushort_t port, void * src,  uint_t length, void * priv_data) {
 
     if (length == 1) { 
        PrintDebug("keyboard: write of 0x%x to 80h\n", *((uint8_t*)src));
     }
 }
 
-static int keyboard_read_delay(struct guest_info * core, ushort_t port, void * dest, uint_t length, struct vm_device * dev) {
+static int keyboard_read_delay(struct guest_info * core, ushort_t port, void * dest, uint_t length, void * priv_data) {
 
     if (length == 1) { 
        *(uint8_t *)dest = v3_inb(port);
 
 
 
-static int keyboard_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+static int keyboard_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct keyboard_internal * kbd = priv_data;
     uint8_t cmd = *(uint8_t *)src;
 
     // Should always be single byte write
     }
 
 
-    addr_t irq_state = v3_lock_irqsave(state->kb_lock);
+    addr_t irq_state = v3_lock_irqsave(kbd->kb_lock);
 
-    if (state->state != NORMAL) { 
+    if (kbd->state != NORMAL) { 
        PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n");
     }
   
 
     switch (cmd) { 
        case 0x20:  // READ COMMAND BYTE (returned in 60h)
-           push_to_output_queue(dev, state->cmd.val, COMMAND, KEYBOARD);
-           PrintDebug("keyboard: command byte 0x%x returned\n", state->cmd.val);
+           push_to_output_queue(kbd, kbd->cmd.val, COMMAND, KEYBOARD);
+           PrintDebug("keyboard: command byte 0x%x returned\n", kbd->cmd.val);
            break;
 
        case 0x60:  // WRITE COMMAND BYTE (read from 60h)
-           state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
+           kbd->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
            PrintDebug("keyboard: prepare to write command byte\n");
            break;
 
            // case 0x90-9f - write to output port  (?)
 
        case 0xa1: // Get version number
-           push_to_output_queue(dev, 0x00, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0x00, COMMAND, KEYBOARD);
            PrintDebug("keyboard: version number 0x0 returned\n");
            break;
 
        case 0xa4:  // is password installed?  send result to 0x60
            // we don't support passwords
-           push_to_output_queue(dev, 0xf1, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0xf1, COMMAND, KEYBOARD);
            PrintDebug("keyboard: password not installed\n");
            break;
 
        case 0xa5:  // new password will arrive on 0x60
-           state->state = TRANSMIT_PASSWD;
+           kbd->state = TRANSMIT_PASSWD;
            PrintDebug("keyboard: pepare to transmit password\n");
            break;
 
            break;
 
        case 0xa7:  // disable mouse
-           state->cmd.mouse_disable = 1;
+           kbd->cmd.mouse_disable = 1;
            PrintDebug("keyboard: mouse disabled\n");
            break;
 
        case 0xa8:  // enable mouse
-           state->cmd.mouse_disable = 0;
+           kbd->cmd.mouse_disable = 0;
            PrintDebug("keyboard: mouse enabled\n");
            break;
 
        case 0xa9:  // mouse interface test  (always succeeds)
-           push_to_output_queue(dev, 0x00, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0x00, COMMAND, KEYBOARD);
            PrintDebug("keyboard: mouse interface test succeeded\n");
            break;
 
        case 0xaa:  // controller self test (always succeeds)
-           push_to_output_queue(dev, 0x55, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0x55, COMMAND, KEYBOARD);
            PrintDebug("keyboard: controller self test succeeded\n");
            break;
 
        case 0xab:  // keyboard interface test (always succeeds)
-           push_to_output_queue(dev, 0, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0, COMMAND, KEYBOARD);
            PrintDebug("keyboard: keyboard interface test succeeded\n");
            break;
 
        case 0xad:  // disable keyboard
-           state->cmd.disable = 1;
+           kbd->cmd.disable = 1;
            PrintDebug("keyboard: keyboard disabled\n");
            break;
 
        case 0xae:  // enable keyboard
-           state->cmd.disable = 0;
+           kbd->cmd.disable = 0;
            PrintDebug("keyboard: keyboard enabled\n");
            break;
 
        case 0xaf:  // get version
-           push_to_output_queue(dev, 0x00, COMMAND, KEYBOARD);
+           push_to_output_queue(kbd, 0x00, COMMAND, KEYBOARD);
            PrintDebug("keyboard: version 0 returned \n");
            break;
 
        case 0xd0: // return microcontroller output on 60h
-           push_to_output_queue(dev, state->output_byte, COMMAND, KEYBOARD);
-           PrintDebug("keyboard: output byte 0x%x returned\n", state->output_byte);
+           push_to_output_queue(kbd, kbd->output_byte, COMMAND, KEYBOARD);
+           PrintDebug("keyboard: output byte 0x%x returned\n", kbd->output_byte);
            break;
 
        case 0xd1: // request to write next byte on 60h to the microcontroller output port
-           state->state = WRITING_OUTPUT_PORT;
+           kbd->state = WRITING_OUTPUT_PORT;
            PrintDebug("keyboard: prepare to write output byte\n");
            break;
 
        case 0xd2:  //  write keyboard buffer (inject key)
-           state->state = INJECTING_KEY;
+           kbd->state = INJECTING_KEY;
            PrintDebug("keyboard: prepare to inject key\n");
            break;
 
        case 0xd3: //  write mouse buffer (inject mouse)
-           state->state = INJECTING_MOUSE;
+           kbd->state = INJECTING_MOUSE;
            PrintDebug("keyboard: prepare to inject mouse\n");
            break;
 
        case 0xd4: // write mouse device (command to mouse?)
-           state->state = IN_MOUSE;
+           kbd->state = IN_MOUSE;
            PrintDebug("keyboard: prepare to inject mouse command\n");
            break;
 
        case 0xc0: //  read input port 
-           push_to_output_queue(dev, state->input_byte, COMMAND, KEYBOARD);
-           PrintDebug("keyboard: input byte 0x%x returned\n", state->input_byte);
+           push_to_output_queue(kbd, kbd->input_byte, COMMAND, KEYBOARD);
+           PrintDebug("keyboard: input byte 0x%x returned\n", kbd->input_byte);
            break;
 
        case 0xc1:  //copy input port lsn to status msn
-           state->status.val &= 0x0f;
-           state->status.val |= (state->input_byte & 0xf) << 4;
+           kbd->status.val &= 0x0f;
+           kbd->status.val |= (kbd->input_byte & 0xf) << 4;
            PrintDebug("keyboard: copied input byte low 4 bits to status reg hi 4 bits\n");
            break;
 
        case 0xc2: // copy input port msn to status msn
-           state->status.val &= 0x0f;
-           state->status.val |= (state->input_byte & 0xf0);
+           kbd->status.val &= 0x0f;
+           kbd->status.val |= (kbd->input_byte & 0xf0);
            PrintDebug("keyboard: copied input byte hi 4 bits to status reg hi 4 bits\n");
            break;
     
        case 0xe0: // read test port
-           push_to_output_queue(dev, state->output_byte >> 6, COMMAND, KEYBOARD);
-           PrintDebug("keyboard: read 0x%x from test port\n", state->output_byte >> 6);
+           push_to_output_queue(kbd, kbd->output_byte >> 6, COMMAND, KEYBOARD);
+           PrintDebug("keyboard: read 0x%x from test port\n", kbd->output_byte >> 6);
            break;
 
    
            break;
     }
 
-    v3_unlock_irqrestore(state->kb_lock, irq_state);
+    v3_unlock_irqrestore(kbd->kb_lock, irq_state);
 
     return length;
 }
 
-static int keyboard_read_status(struct guest_info * core, ushort_t port, void * dest, uint_t length, struct vm_device * dev) {
-    struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+static int keyboard_read_status(struct guest_info * core, ushort_t port, void * dest, uint_t length, void * priv_data) {
+    struct keyboard_internal * kbd = priv_data;
 
     if (length != 1) { 
        PrintError("keyboard: >1 byte read for status (64h)\n");
 
     PrintDebug("keyboard: read status (64h): ");
 
-    addr_t irq_state = v3_lock_irqsave(state->kb_lock);
+    addr_t irq_state = v3_lock_irqsave(kbd->kb_lock);
 
-    *(uint8_t *)dest = state->status.val;
+    *(uint8_t *)dest = kbd->status.val;
 
-    v3_unlock_irqrestore(state->kb_lock, irq_state);
+    v3_unlock_irqrestore(kbd->kb_lock, irq_state);
     
     PrintDebug("0x%x\n", *(uint8_t *)dest);
     
     return length;
 }
 
-static int keyboard_write_output(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+static int keyboard_write_output(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct keyboard_internal * kbd = priv_data;
     int ret = length;
 
     if (length != 1) { 
   
     PrintDebug("keyboard: output 0x%x on 60h\n", data);
 
-    addr_t irq_state = v3_lock_irqsave(state->kb_lock);
+    addr_t irq_state = v3_lock_irqsave(kbd->kb_lock);
 
-    switch (state->state) {
+    switch (kbd->state) {
        case WRITING_CMD_BYTE:
-           state->cmd.val = data;
-           state->state = NORMAL;
-           PrintDebug("keyboard: wrote new command byte 0x%x\n", state->cmd.val);
+           kbd->cmd.val = data;
+           kbd->state = NORMAL;
+           PrintDebug("keyboard: wrote new command byte 0x%x\n", kbd->cmd.val);
            break;
 
        case WRITING_OUTPUT_PORT:
-           state->output_byte = data;
-           state->state = NORMAL;
-           PrintDebug("keyboard: wrote new output byte 0x%x\n", state->output_byte);
+           kbd->output_byte = data;
+           kbd->state = NORMAL;
+           PrintDebug("keyboard: wrote new output byte 0x%x\n", kbd->output_byte);
            break;
 
        case INJECTING_KEY:
-           push_to_output_queue(dev, data, COMMAND, KEYBOARD);  // probably should be a call to deliver_key_to_vmm()
-           state->state = NORMAL;
+           push_to_output_queue(kbd, data, COMMAND, KEYBOARD);  // probably should be a call to deliver_key_to_vmm()
+           kbd->state = NORMAL;
            PrintDebug("keyboard: injected key 0x%x\n", data);
            break;
 
        case INJECTING_MOUSE:
-           push_to_output_queue(dev, data, DATA, MOUSE);
+           push_to_output_queue(kbd, data, DATA, MOUSE);
            //      PrintDebug("keyboard: ignoring injected mouse event 0x%x\n", data);
            PrintDebug("keyboard: injected mouse event 0x%x\n", data);
-           state->state = NORMAL;
+           kbd->state = NORMAL;
            break;
 
        case IN_MOUSE:
            PrintDebug("keyboard: mouse action: ");
-           if (mouse_write_output(dev, data)) { 
-               state->state = NORMAL;
+           if (mouse_write_output(kbd, data)) { 
+               kbd->state = NORMAL;
            }
            PrintDebug("\n");
            break;
                PrintDebug("keyboard: ignoring password character 0x%x\n",data);
            } else {
                // end of password
-               state->state = NORMAL;
+               kbd->state = NORMAL;
                PrintDebug("keyboard: done with password\n");
            }
            break;
 
        case SET_LEDS:
            PrintDebug("Keyboard: LEDs being set...\n");
-           push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
-           state->state = NORMAL;
+           push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+           kbd->state = NORMAL;
            break;
 
        case SET_RATE:
            PrintDebug("Keyboard: Rate being set...\n");
-           push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
-           state->state = NORMAL;
+           push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+           kbd->state = NORMAL;
            break;
 
        default:
            // command is being sent to keyboard controller
            switch (data) { 
                case 0xff: // reset
-                   push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD); // ack
-                   push_to_output_queue(dev, 0xaa, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD); // ack
+                   push_to_output_queue(kbd, 0xaa, COMMAND, KEYBOARD);
                    PrintDebug("keyboard: reset complete and acked\n");
                    break;
 
                case 0xf5: // disable scanning
                case 0xf4: // enable scanning
                    // ack
-                   push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
                    // should do something here... PAD
                    PrintDebug("keyboard: %s scanning done and acked\n", (data == 0xf5) ? "disable" : "enable");
                    break;
 
                case 0xf3:
-                   push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
-                   state->state = SET_RATE;
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+                   kbd->state = SET_RATE;
                    break;
 
                case 0xf2: // get keyboard ID
-                   push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
-                   push_to_output_queue(dev, 0xab, COMMAND, KEYBOARD);
-                   push_to_output_queue(dev, 0x83, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0xab, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0x83, COMMAND, KEYBOARD);
                    PrintDebug("Keyboard: Requesting Keyboard ID\n");
                    break;
 
                case 0xed: // enable keyboard LEDs
-                   push_to_output_queue(dev, 0xfa, COMMAND, KEYBOARD);
-                   state->state = SET_LEDS;
+                   push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD);
+                   kbd->state = SET_LEDS;
                    break;
 
                case 0xee: // echo, used by FreeBSD to probe controller
-                   push_to_output_queue(dev, 0xee, COMMAND, KEYBOARD);
+                   push_to_output_queue(kbd, 0xee, COMMAND, KEYBOARD);
                    break;
 
                case 0xfe: // resend
 
                default:
                    PrintError("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
-                   state->status.out_buf_full = 1;
+                   kbd->status.out_buf_full = 1;
                    ret = -1;
                    break;
            }
        }
     }
   
-    v3_unlock_irqrestore(state->kb_lock, irq_state);
+    v3_unlock_irqrestore(kbd->kb_lock, irq_state);
 
     return ret;
 }
 
-static int keyboard_read_input(struct guest_info * core, ushort_t port, void * dest, uint_t length, struct vm_device * dev) {
-    struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+static int keyboard_read_input(struct guest_info * core, ushort_t port, void * dest, uint_t length, void * priv_data) {
+    struct keyboard_internal * kbd = priv_data;
 
     if (length != 1) {
        PrintError("keyboard: unknown size read from input (60h)\n");
        return -1;
     }
     
-    addr_t irq_state = v3_lock_irqsave(state->kb_lock);
+    addr_t irq_state = v3_lock_irqsave(kbd->kb_lock);
 
-    pull_from_output_queue(dev, (uint8_t *)dest);
+    pull_from_output_queue(kbd, (uint8_t *)dest);
       
-    v3_unlock_irqrestore(state->kb_lock, irq_state);
+    v3_unlock_irqrestore(kbd->kb_lock, irq_state);
 
     PrintDebug("keyboard: read from input (60h): 0x%x\n", *(uint8_t *)dest);
 
 
 
 static int keyboard_free(struct vm_device * dev) {
-
-    v3_dev_unhook_io(dev, KEYBOARD_60H);
-    v3_dev_unhook_io(dev, KEYBOARD_64H);
-#if KEYBOARD_DEBUG_80H
-    v3_dev_unhook_io(dev, KEYBOARD_DELAY_80H);
-#endif
-    keyboard_reset_device(dev);
+    
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = { 
     .free = keyboard_free,
-    .reset = keyboard_reset_device,
-    .start = keyboard_start_device,
-    .stop = keyboard_stop_device,
+
 };
 
 
 
 
 static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
-    struct keyboard_internal * keyboard_state = NULL;
+    struct keyboard_internal * kbd = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
 
     PrintDebug("keyboard: init_device\n");
 
-    keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
+    kbd = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
+
+    memset(kbd, 0, sizeof(struct keyboard_internal));
 
-    memset(keyboard_state, 0, sizeof(struct keyboard_internal));
+    kbd->vm = vm;
 
-    keyboard_state->mouse_queue.start = 0;
-    keyboard_state->mouse_queue.end = 0;
-    keyboard_state->mouse_queue.count = 0;
+    kbd->mouse_queue.start = 0;
+    kbd->mouse_queue.end = 0;
+    kbd->mouse_queue.count = 0;
 
-    keyboard_state->kbd_queue.start = 0;
-    keyboard_state->kbd_queue.end = 0;
-    keyboard_state->kbd_queue.count = 0;
+    kbd->kbd_queue.start = 0;
+    kbd->kbd_queue.end = 0;
+    kbd->kbd_queue.count = 0;
 
-    keyboard_state->mouse_enabled = 0;
+    kbd->mouse_enabled = 0;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, keyboard_state);
+    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, kbd);
 
     if (v3_attach_device(vm, dev) == -1) {
        PrintError("Could not attach device %s\n", dev_id);
        return -1;
     }
 
-
-    keyboard_reset_device(dev);
+    keyboard_reset_device(kbd);
 
 
-    v3_lock_init(&(keyboard_state->kb_lock));
+    v3_lock_init(&(kbd->kb_lock));
 
 
     // hook ports
 
 
     struct vm_device * ide;
 
+    struct v3_vm_info * vm;
+
     v3_lock_t nvram_lock;
 
     uint_t        us;   //microseconds - for clock update - zeroed every second
 }
 
 
-static void update_time( struct vm_device * dev, uint_t period_us) {
-    struct nvram_internal * data = (struct nvram_internal *) (dev->private_data);
+static void update_time(struct nvram_internal * data, uint_t period_us) {
     struct rtc_stata * stata = (struct rtc_stata *) &((data->mem_state[NVRAM_REG_STAT_A]));
     struct rtc_statb * statb = (struct rtc_statb *) &((data->mem_state[NVRAM_REG_STAT_B]));
     struct rtc_statc * statc = (struct rtc_statc *) &((data->mem_state[NVRAM_REG_STAT_C]));
     // Interrupt associated VM, if needed
     if (statc->irq) { 
        PrintDebug("nvram: injecting interrupt\n");
-       v3_raise_irq(dev->vm, NVRAM_RTC_IRQ);
+       v3_raise_irq(data->vm, NVRAM_RTC_IRQ);
     }
 }
 
                              struct v3_timer_event * evt, 
                              void * priv_data) {
 
-    struct vm_device * dev = (struct vm_device *)priv_data;
 
-    if (dev) {
-       struct nvram_internal * data = (struct nvram_internal *) (dev->private_data);
-       
+    struct nvram_internal * data = priv_data;
+
+    if (data) {
        addr_t irq_state = v3_lock_irqsave(data->nvram_lock);
-       update_time(dev, evt->period_us);
+       update_time(data, evt->period_us);
        v3_unlock_irqrestore(data->nvram_lock, irq_state);
     }
   
     }
 }
 
-static int init_nvram_state(struct v3_vm_info * vm, struct vm_device * dev) {
+static int init_nvram_state(struct v3_vm_info * vm, struct nvram_internal * nvram) {
 
-    struct nvram_internal * nvram = (struct nvram_internal *)dev->private_data;
-  
     memset(nvram->mem_state, 0, NVRAM_REG_MAX);
     memset(nvram->reg_map, 0, NVRAM_REG_MAX / 8);
 
 
 
 
-static int nvram_reset_device(struct vm_device * dev) {
-
-    return 0;
-}
-
-
-
-
-
-static int nvram_start_device(struct vm_device * dev) {
-    PrintDebug("nvram: start device\n");
-    return 0;
-}
-
-
-static int nvram_stop_device(struct vm_device * dev) {
-    PrintDebug("nvram: stop device\n");
-    return 0;
-}
-
-
 
 
 static int nvram_write_reg_port(struct guest_info * core, ushort_t port,
-                               void * src, uint_t length, struct vm_device * dev) {
+                               void * src, uint_t length, void * priv_data) {
 
-    struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+    struct nvram_internal * data = priv_data;
     
     memcpy(&(data->thereg), src, 1);
     PrintDebug("Writing To NVRAM reg: 0x%x\n", data->thereg);
 }
 
 static int nvram_read_data_port(struct guest_info * core, ushort_t port,
-                               void * dst, uint_t length, struct vm_device * dev) {
+                               void * dst, uint_t length, void * priv_data) {
 
-    struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+    struct nvram_internal * data = priv_data;
 
     addr_t irq_state = v3_lock_irqsave(data->nvram_lock);
 
 
 
 static int nvram_write_data_port(struct guest_info * core, ushort_t port,
-                                void * src, uint_t length, struct vm_device * dev) {
+                                void * src, uint_t length, void * priv_data) {
 
-    struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+    struct nvram_internal * data = priv_data;
 
     addr_t irq_state = v3_lock_irqsave(data->nvram_lock);
 
 
 
 static int nvram_free(struct vm_device * dev) {
-    v3_dev_unhook_io(dev, NVRAM_REG_PORT);
-    v3_dev_unhook_io(dev, NVRAM_DATA_PORT);
-
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {  
     .free = nvram_free,
-    .reset = nvram_reset_device,
-    .start = nvram_start_device,
-    .stop = nvram_stop_device,
 };
 
 
     PrintDebug("nvram: internal at %p\n", (void *)nvram_state);
 
     nvram_state->ide = ide;
+    nvram_state->vm = vm;
 
     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, nvram_state);
 
        return -1;
     }
 
-    init_nvram_state(vm, dev);
+    init_nvram_state(vm, nvram_state);
 
     // hook ports
     v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
     v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
   
-    v3_hook_host_event(vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev);
+    v3_hook_host_event(vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), nvram_state);
 
     return 0;
 }
 
 };
 
 
-static int handle_gen_write(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct debug_state * state = (struct debug_state *)dev->private_data;
+static int handle_gen_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct debug_state * state = priv_data;
 
     state->debug_buf[state->debug_offset++] = *(char*)src;
 
 }
 
 static int handle_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct debug_state * state = (struct debug_state *)dev->private_data;
+    struct debug_state * state = (struct debug_state *)priv_data;
 
     int msg_len = info->vm_regs.rcx;
     addr_t msg_gpa = info->vm_regs.rbx;
 
 
 static int debug_free(struct vm_device * dev) {
-    v3_dev_unhook_io(dev, DEBUG_PORT1);
-
 
     return 0;
 };
 
 static struct v3_device_ops dev_ops = {
     .free = debug_free,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
 };
 
 
     }
 
     v3_dev_hook_io(dev, DEBUG_PORT1,  NULL, &handle_gen_write);
-    v3_register_hypercall(vm, OS_DEBUG_HCALL, handle_hcall, dev);
+    v3_register_hypercall(vm, OS_DEBUG_HCALL, handle_hcall, state);
 
     state->debug_offset = 0;
     memset(state->debug_buf, 0, BUF_SIZE);
 
 
 
 
-static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
+static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pci_internal * pci_state = priv_data;
     int reg_offset = port & 0x3;
     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
 
 }
 
 
-static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
+static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pci_internal * pci_state = priv_data;
     int reg_offset = port & 0x3; 
     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
 
 }
 
 
-static int data_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
-    struct pci_internal * pci_state =  (struct pci_internal *)(vmdev->private_data);
+static int data_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
+    struct pci_internal * pci_state =  priv_data;
     struct pci_device * pci_dev = NULL;
     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
     int i;
 }
 
 
-static int data_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
-    struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
+static int data_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
+    struct pci_internal * pci_state = priv_data;
     struct pci_device * pci_dev = NULL;
     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
     int i;
 
 
 
-static int pci_reset_device(struct vm_device * dev) {
-    PrintDebug("pci: reset device\n");    
-    return 0;
-}
-
-
-static int pci_start_device(struct vm_device * dev) {
-    PrintDebug("pci: start device\n");
-    return 0;
-}
-
-
-static int pci_stop_device(struct vm_device * dev) {
-    PrintDebug("pci: stop device\n");  
-    return 0;
-}
-
-
-
 static int pci_free(struct vm_device * dev) {
-    int i = 0;
-    
-    for (i = 0; i < 4; i++){
-       v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i);
-       v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i);
-    }
     
     return 0;
 }
 
 static struct v3_device_ops dev_ops = {
     .free = pci_free,
-    .reset = pci_reset_device,
-    .start = pci_start_device,
-    .stop = pci_stop_device,
+
 };
 
 
 
 }
 
 static int write_data_port(struct guest_info * core, uint16_t port, 
-                          void * src, uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                          void * src, uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t * val = (uint8_t *)src;
     struct serial_port * com_port = NULL;
 
 
 
 static int read_data_port(struct guest_info * core, uint16_t port, 
-                         void * dst, uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                         void * dst, uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t * val = (uint8_t *)dst;
     struct serial_port * com_port = NULL;
 
 
 
 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src, 
-                          uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                          uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t val = *(uint8_t *)src;
     struct serial_port * com_port = NULL;
 
 
 
 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst, 
-                         uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                         uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t * val = (uint8_t *)dst;
     struct serial_port * com_port = NULL;
 
 
 
 static int write_status_port(struct guest_info * core, uint16_t port, void * src, 
-                            uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                            uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t val = *(uint8_t *)src;
     struct serial_port * com_port = NULL;
 
 }
 
 static int read_status_port(struct guest_info * core, uint16_t port, void * dst, 
-                           uint_t length, struct vm_device * dev) {
-    struct serial_state * state = (struct serial_state *)dev->private_data;
+                           uint_t length, void * priv_data) {
+    struct serial_state * state = priv_data;
     uint8_t * val = (uint8_t *)dst;
     struct serial_port * com_port = NULL;
 
 }
 
 static int serial_deinit(struct vm_device * dev) {
-
-
-    v3_dev_unhook_io(dev, COM1_DATA_PORT);
-    v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
-    v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
-
-    v3_dev_unhook_io(dev, COM2_DATA_PORT);
-    v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
-    v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
-
-    v3_dev_unhook_io(dev, COM3_DATA_PORT);
-    v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
-    v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
-
-    v3_dev_unhook_io(dev, COM4_DATA_PORT);
-    v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
-    v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
-    v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
-    v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
-
     return 0;
 }
 
     //.init = serial_init,
     .free = serial_deinit,
     .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
 };
 
 
 
     return 0;
 }
 
-/*
-int v3_init_core_dev_mgr(struct v3_vm_info * vm) {
-    struct v3_core_dev_mgr * mgr = &(vm->core_dev_mgr);
-
-    INIT_LIST_HEAD(&(mgr->dev_list));
-    mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
-
-    return 0;
-}
-
-int v3_core_dev_mgr_deinit(struct v3_vm_info * vm) {
-    struct vm_device * dev;
-    struct v3_core_dev_mgr * mgr = &(vm->core_dev_mgr);
-    struct vm_device * tmp;
-
-    list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
-       v3_detach_device(dev);
-    }
-
-    // TODO: Clear hash tables 
-
-}
-*/
 
 
 int v3_create_device(struct v3_vm_info * vm, const char * dev_name, v3_cfg_tree_t * cfg) {
 /* The remaining functions are called by the devices themselves */
 /****************************************************************/
 
+struct dev_io_hook {
+    uint16_t port;
+
+    struct list_head node;
+
+};
+
 /* IO HOOKS */
 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
-                  int (*read)(struct guest_info * core, uint16_t port, void * dst, uint_t length, struct vm_device * dev),
-                  int (*write)(struct guest_info * core, uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
-    return v3_hook_io_port(dev->vm, port, 
-                          (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))read, 
-                          (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))write, 
-                          (void *)dev);
+                  int (*read)(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data),
+                  int (*write)(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data)) {
+    struct dev_io_hook * io_hook = NULL;
+    int ret = 0;
+    
+   ret = v3_hook_io_port(dev->vm, port, 
+                        (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))read, 
+                        (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))write, 
+                        (void *)dev->private_data);
+
+   if (ret == -1) {
+       return -1;
+   }
+
+   io_hook = V3_Malloc(sizeof(struct dev_io_hook));
+
+   if (io_hook == NULL) {
+       PrintError("Could not allocate io hook dev state\n");
+       return -1;
+   }
+
+   io_hook->port = port;
+   list_add(&(io_hook->node), &(dev->io_hooks));
+
+   return 0;
 }
 
 
 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
-    return v3_unhook_io_port(dev->vm, port);
+    struct dev_io_hook * io_hook = NULL;
+    struct dev_io_hook * tmp;
+
+    list_for_each_entry_safe(io_hook, tmp, &(dev->io_hooks), node) {
+       if (io_hook->port == port) {
+
+           list_del(&(io_hook->node));
+           V3_Free(io_hook);
+           
+           return v3_unhook_io_port(dev->vm, port);        
+       }
+    }
+
+    return -1;
 }
 
 
 
     dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
 
+    INIT_LIST_HEAD(&(dev->io_hooks));
+
     strncpy(dev->name, name, 32);
     dev->ops = ops;
     dev->private_data = private_data;