/* (c) 2008, Peter Dinda <pdinda@northwestern.edu> */
+/* (c) 2008, Jack Lange <jarusl@northwestern.edu> */
 /* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
 
-#ifndef __GENERIC_H
-#define __GENERIC_H
+#ifndef __GENERIC_H__
+#define __GENERIC_H__
 
 #include <palacios/vm_dev.h>
 
 #define GENERIC_PRINT_AND_PASSTHROUGH 0
 #define GENERIC_PRINT_AND_IGNORE      1
 
-// A port range is low..high, inclusive, third value is one of the above
-typedef uint_t generic_port_range_type[3];
-// A memory range is low..high, inclusive, flags
-typedef void *generic_address_range_type[3];
-// An interrupt ory map range is low..high, inclusive, flags
-typedef uint_t generic_irq_range_type[3];
+
+int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type);
+int v3_generic_add_mem_range(struct vm_device * dev, void * start, void * end, uint_t type);
+int v3_generic_add_irq_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type);
 
 // The lists given are null terminated
-struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
-                                generic_address_range_type addess_ranges[],
-                                generic_irq_range_type     irq_ranges[]);  
+struct vm_device * create_generic();  
 
 #endif
 
 #include <devices/generic.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
-
+#include <palacios/vmm_list.h>
 
 
 
 #define MEM_HOOKS  0   // not yet implmented in device model
 #define IRQ_HOOKS  0   // not yet implemented in device model
 
+
 struct generic_internal {
-  generic_port_range_type    * port_ranges;
-  uint_t                     num_port_ranges;
-  generic_address_range_type * address_ranges;
-  uint_t                     num_address_ranges;
-  generic_irq_range_type     * irq_ranges;
-  uint_t                     num_irq_ranges;
+  struct list_head port_range;
+  uint_t num_port_ranges;
+  struct list_head mem_range;
+  uint_t num_mem_ranges;
+  struct list_head irq_range;
+  uint_t num_irq_ranges;
+};
+
+
+struct port_range {
+  uint_t start;
+  uint_t end;
+  uint_t type;
+  struct list_head range_list;
+};
+
+struct mem_range {
+  void * start;
+  void * end;
+  uint_t type;
+  struct list_head range_list;
+};
+
+struct irq_range {
+  uint_t start;
+  uint_t end;
+  uint_t type;
+  struct list_head range_list;
 };
 
 
     PrintDebug("%x", ((uchar_t*)src)[i]);
   }
   
-  PrintDebug(" to port 0x%x ... ", port);
-
-  PrintDebug(" ignored\n");
+  PrintDebug(" to port 0x%x ... ignored\n", port);
  
   return length;
 }
 
 int generic_init_device(struct vm_device * dev) {
   struct generic_internal * state = (struct generic_internal *)(dev->private_data);
-  uint_t i, j;
 
   PrintDebug("generic: init_device\n");
-
-  // Would read state here
-
   generic_reset_device(dev);
 
-  for (i = 0; i < state->num_port_ranges; i++) { 
-
-    PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n", 
-              state->port_ranges[i][0], state->port_ranges[i][1], 
-              (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
 
-    if (PORT_HOOKS) { // This is a runtime conditional on a #define
-      for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
-       if (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) { 
-
-         if (dev_hook_io(dev, j, &generic_read_port_passthrough, &generic_write_port_passthrough)) { 
-           PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
+  if (PORT_HOOKS) { // This is a runtime conditional on a #define
+    struct port_range * tmp;
+
+    list_for_each_entry(tmp, &(state->port_range), range_list) {
+      uint_t i = 0;
+      
+      PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n", 
+                tmp->start, tmp->end, 
+                (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
+      
+      for (i = tmp->start; i <= tmp->end; i++) { 
+       if (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) { 
+         
+         if (dev_hook_io(dev, i, &generic_read_port_passthrough, &generic_write_port_passthrough)) { 
+           PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
          }
-
-       } else if (state->port_ranges[i][2] == GENERIC_PRINT_AND_IGNORE) { 
-
-         if (dev_hook_io(dev, j, &generic_read_port_ignore, &generic_write_port_ignore)) { 
-           PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
+         
+       } else if (tmp->type == GENERIC_PRINT_AND_IGNORE) { 
+         
+         if (dev_hook_io(dev, i, &generic_read_port_ignore, &generic_write_port_ignore)) { 
+           PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
          }
-
        } 
       }
-    } else {
-      PrintDebug("generic: hooking ports not supported\n");
-    }
 
+    }
+  } else {
+    PrintDebug("generic: hooking ports not supported\n");
   }
 
-  for (i = 0; i < state->num_address_ranges; i++) { 
 
-    PrintDebug("generic: hooking addresses 0x%x to 0x%x\n", 
-              state->address_ranges[i][0], state->address_ranges[i][1]); 
 
-    if (MEM_HOOKS) { // This is a runtime conditional on a #define
-      if (dev_hook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
+  if (MEM_HOOKS) { // This is a runtime conditional on a #define
+    struct mem_range * tmp;
+
+    list_for_each_entry(tmp, &(state->mem_range), range_list) {
+
+      PrintDebug("generic: hooking addresses 0x%x to 0x%x\n", 
+                tmp->start, tmp->end); 
+      
+      
+      if (dev_hook_mem(dev, tmp->start, tmp->end)) {
        PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
-                  state->address_ranges[i][0], state->address_ranges[i][1]); 
+                  tmp->start, tmp->end); 
       }
-    } else {
-      PrintDebug("generic: hooking addresses not supported\n");
     }
+  } else {
+    PrintDebug("generic: hooking addresses not supported\n");
   }
 
-  for (i = 0; i < state->num_irq_ranges; i++) { 
 
-    PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
-              state->irq_ranges[i][0], state->irq_ranges[i][1]);
 
-    if (IRQ_HOOKS) { // This is a runtime conditional on a #define
-      for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
-       if (dev_hook_irq(dev, j, &generic_interrupt)) { 
-         PrintDebug("generic: can't hook irq  0x%x (already hooked?)\n", j);
+
+  if (IRQ_HOOKS) { // This is a runtime conditional on a #define
+    struct irq_range * tmp;
+    
+    list_for_each_entry(tmp, &(state->irq_range), range_list) {
+      uint_t i;
+
+      PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
+                tmp->start, tmp->end);
+      
+      for (i = tmp->start; i <= tmp->end; i++) { 
+       if (dev_hook_irq(dev, i, &generic_interrupt)) { 
+         PrintDebug("generic: can't hook irq  0x%x (already hooked?)\n", i);
        }
       }
-    } else {
-      PrintDebug("generic: hooking irqs not supported\n");
-    }
 
+    }
+  } else {
+    PrintDebug("generic: hooking irqs not supported\n");
   }
 
+
+
   return 0;
 }
 
 int generic_deinit_device(struct vm_device * dev) {
-  struct generic_internal *state = (struct generic_internal *)(dev->private_data);
-  uint_t i, j;
+  struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+
 
   PrintDebug("generic: deinit_device\n");
 
 
-  for (i = 0; i < state->num_irq_ranges; i++) { 
+  if (IRQ_HOOKS) { // This is a runtime conditional on a #define
+    struct irq_range * tmp;
+    struct irq_range * cur;
     
-    PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n", 
-              state->irq_ranges[i][0], state->irq_ranges[i][1]);
+    list_for_each_entry_safe(cur, tmp, &(state->irq_range), range_list) {
+      uint_t i;
 
-    if (IRQ_HOOKS) { // This is a runtime conditional on a #define
-      for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
+      PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n", 
+                cur->start, cur->end);
+      
 
-       if (dev_unhook_irq(dev, j)) {
-         PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
+      for (i = cur->start; i <= cur->end; i++) { 
+       if (dev_unhook_irq(dev, i)) {
+         PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n", i);
        }
-
       }
-    } else {
-      PrintDebug("generic: unhooking irqs not supported\n");
+
+      V3_Free(cur);
     }
+  } else {
+    PrintDebug("generic: unhooking irqs not supported\n");
   }
 
-  for (i = 0; i < state->num_address_ranges; i++) { 
 
-    PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
-              state->address_ranges[i][0], state->address_ranges[i][1]); 
+  if (MEM_HOOKS) {
+    struct mem_range * tmp;
+    struct mem_range * cur;
+    
+    list_for_each_entry_safe(cur, tmp, &(state->mem_range), range_list) {
 
-    if (MEM_HOOKS) {
-      if (dev_unhook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
+      PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
+                cur->start, cur->end); 
 
+      if (dev_unhook_mem(dev, cur->start, cur->end)) {
        PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
-                  state->address_ranges[i][0], state->address_ranges[i][1]); 
-
+                  cur->start, cur->end); 
       }
-    } else {
-      PrintDebug("generic: unhooking addresses not supported\n");
+
+      V3_Free(cur);
     }
+  } else {
+    PrintDebug("generic: unhooking addresses not supported\n");
   }
+  
 
-  for (i = 0; i < state->num_port_ranges; i++) { 
-    PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
-              state->port_ranges[i][0], state->port_ranges[i][1]);
-
-    if (PORT_HOOKS) {
-      for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
-       if (dev_unhook_io(dev, j)) {
-         PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", j);
+  if (PORT_HOOKS) {
+    struct port_range * tmp;
+    struct port_range * cur;
+    
+    list_for_each_entry_safe(cur, tmp, &(state->mem_range), range_list) {
+      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 (dev_unhook_io(dev, i)) {
+         PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", i);
        }
       }
-    } else {
-      PrintDebug("generic: unhooking ports not supported\n");
-    }
 
+      V3_Free(cur);
+    }
+  } else {
+    PrintDebug("generic: unhooking ports not supported\n");
   }
 
+
+
   generic_reset_device(dev);
   return 0;
 }
 
 
 
-struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
-                                generic_address_range_type address_ranges[],
-                                generic_irq_range_type     irq_ranges[])
-{
-  struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
-  int i;
-  uint_t num_port_ranges;
-  uint_t num_address_ranges;
-  uint_t num_irq_ranges;
-
-
-  num_port_ranges = 0;
+int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type) {
 
-  if (port_ranges != NULL) { 
-    i = 0;
-
-    while ((port_ranges[i] != NULL) && 
-          ( !( (port_ranges[i][0] == 0) && 
-               (port_ranges[i][1] == 0) && 
-               (port_ranges[i][2] == 0)) ) ) 
-      {
-       num_port_ranges++; 
-       i++; 
-      }
-  }
+  if (PORT_HOOKS) {
+    struct generic_internal * state = (struct generic_internal *)(dev->private_data);
 
-  
-  num_address_ranges = 0;
-
-  if (address_ranges != NULL) { 
-    i = 0;
-
-    while ((address_ranges[i] != NULL)  && 
-          ( !( (address_ranges[i][0] == 0) && 
-               (address_ranges[i][1] == 0) && 
-               (address_ranges[i][2] == 0)) ) ) 
-      { 
-       num_address_ranges++; 
-       i++; 
-      }
+    struct port_range * range = (struct port_range *)V3_Malloc(sizeof(struct port_range));
+    range->start = start;
+    range->end = end;
+    range->type = type;
+    
+    list_add(&(state->port_range), &(range->range_list));
+    state->num_port_ranges++;
+  } else {
+    PrintDebug("generic: hooking IO ports not supported\n");
+    return -1;
   }
 
-  num_irq_ranges = 0;
+  return 0;
+}
 
-  if (irq_ranges != NULL) { 
-    i = 0;
+int v3_generic_add_mem_range(struct vm_device * dev, void * start, void * end, uint_t type) {
 
-    while ((irq_ranges[i] != NULL) && 
-          ( !( (irq_ranges[i][0] == 0) && 
-               (irq_ranges[i][1] == 0) && 
-               (irq_ranges[i][2] == 0)) ) ) 
-      { 
-       num_irq_ranges++; 
-       i++; 
-      }
-  }
+  if (MEM_HOOKS) {
+    struct generic_internal * state = (struct generic_internal *)(dev->private_data);
     
-
-  generic_state->num_port_ranges = num_port_ranges;
-
-  if (num_port_ranges > 0) { 
- 
-   generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_port_ranges);
-   memcpy(generic_state->port_ranges, port_ranges, 
-         (sizeof(generic_port_range_type) * num_port_ranges));
-   
+    struct mem_range * range = (struct mem_range *)V3_Malloc(sizeof(struct mem_range));
+    range->start = start;
+    range->end = end;
+    range->type = type;
+    
+    list_add(&(state->port_range), &(range->range_list));
+    state->num_mem_ranges++;
   } else {
-    generic_state->port_ranges = NULL;
+    PrintDebug("generic: hooking memory not supported\n");
+    return -1;
   }
 
+  return 0;
+}
 
-  generic_state->num_address_ranges = num_address_ranges;
-
-  if (num_address_ranges > 0) { 
 
-    generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_address_ranges);
-    memcpy(generic_state->address_ranges, address_ranges, 
-          (sizeof(generic_address_range_type) * num_address_ranges));
+int v3_generic_add_irq_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type) {
 
+  if (IRQ_HOOKS) {
+    struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+    
+    struct irq_range * range = (struct irq_range *)V3_Malloc(sizeof(struct irq_range));
+    range->start = start;
+    range->end = end;
+    range->type = type;
+    
+    list_add(&(state->port_range), &(range->range_list));
+    state->num_irq_ranges++;
   } else {
-    generic_state->address_ranges = NULL;
+    PrintDebug("generic: hooking IRQs not supported\n");
+    return -1;
   }
 
+  return 0;
+}
 
-  generic_state->num_irq_ranges = num_irq_ranges;
-
-  if (num_irq_ranges > 0) { 
 
-    generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_irq_ranges);
-    memcpy(generic_state->irq_ranges, irq_ranges, 
-          (sizeof(generic_irq_range_type) * num_port_ranges));
 
-  } else {
-    generic_state->irq_ranges = NULL;
-  }
+struct vm_device *create_generic() {
+  struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
+  
+  generic_state->num_port_ranges = 0;
+  generic_state->num_mem_ranges = 0;
+  generic_state->num_irq_ranges = 0;
 
-  struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
+  INIT_LIST_HEAD(&(generic_state->port_range));
+  INIT_LIST_HEAD(&(generic_state->mem_range));
+  INIT_LIST_HEAD(&(generic_state->irq_range));
+    
+  struct vm_device * device = create_device("GENERIC", &dev_ops, generic_state);
 
   return device;
 }
 
 #include <devices/8254.h>
 #include <devices/nvram.h>
 #include <devices/generic.h>
-
-//Zheng 09/29/2008
-#ifdef RAMDISK_BOOT
 #include <devices/ramdisk.h>
-#endif
+
+
+#define USE_GENERIC 1
+#define USE_RAMDISK 0
+
 
 
 static int mem_test_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
   void * region_start;
   int i;
 
-  
+  int use_ramdisk = USE_RAMDISK;
+  int use_generic = USE_GENERIC;
+
+
   v3_init_time(info);
   init_shadow_map(info);
   
 
   
   {
-    
+    struct vm_device * ramdisk = NULL;
     struct vm_device * nvram = create_nvram();
     //struct vm_device * timer = create_timer();
     struct vm_device * pic = create_pic();
     struct vm_device * keyboard = create_keyboard();
     struct vm_device * pit = create_pit(); 
     //struct vm_device * serial = create_serial();
-    
+    struct vm_device * generic = NULL;
     //Zheng 09/29/2008
 
-#ifdef RAMDISK_BOOT
-    struct vm_device * ramdisk = create_ramdisk();
-#endif
+    if (use_ramdisk) {
+      ramdisk = create_ramdisk();
+    }
     
-#define GENERIC 1
     
-#if GENERIC
-    generic_port_range_type range[] = {
-#if 1
+    if (use_generic) {
+      generic = create_generic();
+      
       // Make the DMA controller invisible
-
-      {0x00, 0x07, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channels 0,1,2,3 (address, counter)
-      {0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channels 4,5,6,7 (address, counter)
-      {0x87, 0x87, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 0 page register
-      {0x83, 0x83, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 1 page register
-      {0x81, 0x81, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 2 page register
-      {0x82, 0x82, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 3 page register
-      {0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 4 page register
-      {0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 5 page register
-      {0x89, 0x89, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 6 page register
-      {0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 7 page register
-      {0x08, 0x0f, GENERIC_PRINT_AND_IGNORE},   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
-      {0xd0, 0xde, GENERIC_PRINT_AND_IGNORE},   // DMA 2 misc registers
-#endif
+      v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
+      v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
+      v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
+      v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
+      v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
+      v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
+      v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
+      v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
+      v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
+      v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
+      v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
+      v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
+      
+      
+      
       
-
-#if 1      
       // Make the Serial ports invisible 
+      
+      v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
+      v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
+      
 
-      {0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 1
-      {0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 2
-
-#endif
-
+      
 #ifndef DEBUG_RAMDISK
-
-      {0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 3
-      {0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 4
+      
+      v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
+      v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
 #endif
+      
+      
 
-
-#if 1
       // Make the PCI bus invisible (at least it's configuration)
+      
+      v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
+      v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
 
-      {0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE}, // PCI Config Address
-      {0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE}, // PCI Config Data
-#endif
- 
-
-#ifndef RAMDISK_BOOT
-
-      // Monitor the IDE controllers (very slow)
-
-      {0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
-      {0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
-
-#endif
-
+      
+      
+      if (!use_ramdisk) {
+       // Monitor the IDE controllers (very slow)
+       v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
+       v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
+      }
+      
 #if 1
-      {0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 0
-      {0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 0
+      v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
+      v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
 #endif
       
-
+      
 #if 0
-
+      
       // Make the floppy controllers invisible
-
-      {0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (base,statusa/statusb,DOR)
-      {0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (mainstat/datarate,data)
-      {0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (DIR)
-      {0x370, 0x372, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (base,statusa/statusb,DOR)
-      {0x374, 0x375, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (mainstat/datarate,data)
-      {0x377, 0x377, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (DIR)
+      
+      v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
+      v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
+      v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
+      v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
+      v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
+      v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
       
 #endif
 
 
       // Make the parallel port invisible
       
-      {0x378, 0x37f, GENERIC_PRINT_AND_IGNORE},
+      v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
 
 #endif
 
 
       // Monitor graphics card operations
 
-      {0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH},
-      {0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH},
+      v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
+      v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
       
 #endif
 
 #if 1
       // Make the ISA PNP features invisible
 
-      {0x274, 0x277, GENERIC_PRINT_AND_IGNORE},
-      {0x279, 0x279, GENERIC_PRINT_AND_IGNORE},
-      {0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE},
+      v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
+      v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
+      v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
 #endif
 
 
 #if 1
       // Monitor any network card (realtek ne2000) operations 
-      {0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH},
+      v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
 #endif
 
 
 #if 1
       // Make any Bus master ide controller invisible
       
-      {0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE},
+      v3_generic_add_port_range(generic, 0xc000, 0xc00f, GENERIC_PRINT_AND_IGNORE);
 #endif
-
-
-      //         {0x378, 0x400, GENERIC_PRINT_AND_IGNORE}
       
-      {0,0,0},  // sentinal - must be last
+    }
+      //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
       
-    };
-    
 
-    struct vm_device * generic = create_generic(range, NULL, NULL);
-    
-#endif
+
     
+
     v3_attach_device(info, nvram);
     //v3_attach_device(info, timer);
     v3_attach_device(info, pic);
     v3_attach_device(info, keyboard);
     // v3_attach_device(info, serial);
 
-//Zheng 09/29/2008    
-#ifdef RAMDISK_BOOT
-    v3_attach_device(info, ramdisk);
-#endif
+    if (use_ramdisk) {
+      v3_attach_device(info, ramdisk);
+    }
 
-#if GENERIC
-    // Important that this be attached last!
-    v3_attach_device(info, generic);
-    
-#endif
+    if (use_generic) {
+      // Important that this be attached last!
+      v3_attach_device(info, generic);
+    }
     
     PrintDebugDevMgr(info);
   }
   // no longer needed since we have a keyboard device
   //hook_irq(&vm_info, 1);
   
-#if 1
+#if 0
   // give floppy controller to vm
   v3_hook_irq_for_guest_injection(info, 6);
 #endif
   
-#if 1
-  //primary ide
-  v3_hook_irq_for_guest_injection(info, 14);
-  
-#endif
 
-#ifndef RAMDISK_BOOT
-  // secondary ide
-  v3_hook_irq_for_guest_injection(info, 15);
-#endif
+  if (!use_ramdisk) {
+    //primary ide
+    v3_hook_irq_for_guest_injection(info, 14);
   
+    // secondary ide
+    v3_hook_irq_for_guest_injection(info, 15);    
+  }  
 
   //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);