extern ulong_t s_ramdiskSize;
 
 
-#define SPEAKER_PORT 0x61
-
-static inline void VM_Out_Byte(ushort_t port, uchar_t value)
-{
-    __asm__ __volatile__ (
-       "outb %b0, %w1"
-       :
-       : "a" (value), "Nd" (port)
-    );
-}
-
-/*
- * Read a byte from an I/O port.
- */
-static inline uchar_t VM_In_Byte(ushort_t port)
-{
-    uchar_t value;
-
-    __asm__ __volatile__ (
-       "inb %w1, %b0"
-       : "=a" (value)
-       : "Nd" (port)
-    );
-
-    return value;
-}
-
-
-
-
-int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
-
-  if (length != 1) {
-    return 0;
-  }
-
-  *(uchar_t*)dst = VM_In_Byte(port);    
-  return 1;
-}
-
-
-
-int IO_Write(ushort_t port, void * src, uint_t length, void * priv_data) {
-
-  if (length != 1) {
-    return 0;
-  }
-
-  VM_Out_Byte(port, *(uchar_t *)src);    
-
-  return 1;
-}
-
-
-int IO_Read_to_Serial(ushort_t port, void * dst, uint_t length, void * priv_data) {
-  PrintBoth("Input from Guest on port %d (0x%x) Length=%d\n", port, port, length);
-  
-  return 0;
-}
-
-
-char * bochs_debug_buf = NULL;
-int bochs_debug_offset = 0;
-
-char * bochs_info_buf = NULL;
-int bochs_info_offset = 0;
-
-
-int IO_BOCHS_debug(ushort_t port, void * src, uint_t length, void * priv_data) {
-  if (!bochs_debug_buf) {
-    bochs_debug_buf = (char*)Malloc(1024);
-  }
-
-  bochs_debug_buf[bochs_debug_offset++] = *(char*)src;
-
-  if ((*(char*)src == 0xa) ||  (bochs_debug_offset == 1023)) {
-    SerialPrint("BOCHSDEBUG>%s", bochs_debug_buf);
-    memset(bochs_debug_buf, 0, 1024);
-    bochs_debug_offset = 0;
-  }
-
-  return length;
-}
-
-int IO_BOCHS_info(ushort_t port, void * src, uint_t length, void * priv_data) {
-  if (!bochs_info_buf) {
-    bochs_info_buf = (char*)Malloc(1024);
-  }
-
-  bochs_info_buf[bochs_info_offset++] = *(char*)src;
-
-  if ((*(char*)src == 0xa) ||  (bochs_info_offset == 1023)) {
-    SerialPrint("BOCHSINFO>%s", bochs_info_buf);
-    memset(bochs_info_buf, 0, 1024);
-    bochs_info_offset = 0;
-  }
-
-  return length;
-}
-
-
-int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, void * priv_data) {
- SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
-  switch (length) {
-
-  case 1:
-    SerialPrint(">0x%.2x\n", *(char*)src);
-    break;
-  case 2:
-    SerialPrint(">0x%.4x\n", *(ushort_t*)src);
-    break;
-  case 4:
-    SerialPrint(">0x%.8x\n", *(uint_t*)src);
-    break;
-  default:
-    break;
-  }
-
-  //  SerialMemDump(src, length);
-  return length;
-}
-
-
-
-void BuzzVM()
-{
-  int x;
-  int j;
-  unsigned char init;
-
-#if 0  
-  __asm__ __volatile__ (
-    "popf"
-    );
-    
-#endif
-    
-  PrintBoth("Starting To Buzz\n");
-
-  init=VM_In_Byte(SPEAKER_PORT);
-
-  while (1) {
-    VM_Out_Byte(SPEAKER_PORT, init|0x2);
-    for (j=0;j<1000000;j++) { 
-      x+=j;
-    }
-    VM_Out_Byte(SPEAKER_PORT, init);
-    for (j=0;j<1000000;j++) { 
-      x+=j;
-    }
-  }
-}
-
-
-/*
-int passthrough_mem_read(void * guest_addr, void * dst, uint_t length, void * priv_data) {
-  memcpy(dst, (void*)guest_addr, length);
-  return length;
-}
-
-int passthrough_mem_write(void * guest_addr, void * src, uint_t length, void * priv_data) {
-  memcpy((void*)guest_addr, src, length);
-  return length;
-}
-*/
-
-
-/* We need a configuration mechanism, so we can wrap this completely inside the VMM code, 
- * with no pollution into the HOST OS
- */
-
 int RunVMM(struct Boot_Info * bootInfo) {
   struct vmm_os_hooks os_hooks;
   struct vmm_ctrl_ops vmm_ops;
 
 
 
-
   vm_info = (vmm_ops).allocate_guest();
 
   Init_Stubs(vm_info);
 
   PrintBoth("Configured guest\n");
 
-
-  //v3_hook_io_port(&vm_info, 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
-  
-  //v3_hook_io_port(vm_info, 0x61, &IO_Read, &IO_Write, NULL);
-  //v3_hook_io_port(vm_info, 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
-  //v3_hook_io_port(vm_info, 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
-  //v3_hook_io_port(vm_info, 0x402, &IO_Read, &IO_BOCHS_info, NULL);
-  //v3_hook_io_port(vm_info, 0x403, &IO_Read, &IO_BOCHS_debug, NULL);
-  
-
   (vmm_ops).init_guest(vm_info);
   PrintBoth("Starting Guest\n");
   //Clear_Screen();
 
 
 
 
-DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c ramdisk.c cdrom.c
+DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c ramdisk.c cdrom.c bochs_debug.c
 
 DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
 
 
--- /dev/null
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_BOCHS_DEBUG_H__
+#define __DEVICES_BOCHS_DEBUG_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vm_dev.h>
+
+struct vm_device * create_bochs_debug();
+
+
+#endif // ! __V3VEE__
+
+#endif
 
--- /dev/null
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#include <devices/bochs_debug.h>
+#include <palacios/vmm.h>
+
+#define BUF_SIZE 1024
+
+#define BOCHS_PORT1 0x400
+#define BOCHS_PORT2 0x401
+#define BOCHS_INFO_PORT 0x402
+#define BOCHS_DEBUG_PORT 0x403
+
+
+
+struct debug_state {
+  char debug_buf[BUF_SIZE];
+  uint_t debug_offset;
+
+  char info_buf[BUF_SIZE];
+  uint_t info_offset;
+};
+
+static int handle_info_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+  struct debug_state * state = (struct debug_state *)dev->private_data;
+
+  state->info_buf[state->info_offset++] = *(char*)src;
+
+  if ((*(char*)src == 0xa) ||  (state->info_offset == (BUF_SIZE - 1))) {
+    PrintDebug("BOCHSINFO>%s", state->info_buf);
+    memset(state->info_buf, 0, BUF_SIZE);
+    state->info_offset = 0;
+  }
+
+  return length;
+}
+
+
+static int handle_debug_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+  struct debug_state * state = (struct debug_state *)dev->private_data;
+
+  state->debug_buf[state->debug_offset++] = *(char*)src;
+
+  if ((*(char*)src == 0xa) ||  (state->debug_offset == (BUF_SIZE - 1))) {
+    PrintDebug("BOCHSDEBUG>%s", state->debug_buf);
+    memset(state->debug_buf, 0, BUF_SIZE);
+    state->debug_offset = 0;
+  }
+
+  return length;
+}
+
+
+static int handle_gen_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+
+  switch (length) {
+  case 1:
+    PrintDebug(">0x%.2x\n", *(uchar_t*)src);
+    break;
+  case 2:
+    PrintDebug(">0x%.4x\n", *(ushort_t*)src);
+    break;
+  case 4:
+    PrintDebug(">0x%.8x\n", *(uint_t*)src);
+    break;
+  default:
+    PrintError("Invalid length in handle_gen_write\n");
+    return -1;
+    break;
+  }
+
+  return length;
+}
+
+
+static int debug_init(struct vm_device * dev) {
+  struct debug_state * state = (struct debug_state *)dev->private_data;
+
+  state->debug_offset = 0;
+  state->info_offset = 0;
+  memset(state->debug_buf, 0, BUF_SIZE);
+  memset(state->info_buf, 0, BUF_SIZE);
+
+
+  dev_hook_io(dev, BOCHS_PORT1,  NULL, &handle_gen_write);
+  dev_hook_io(dev, BOCHS_PORT2, NULL, &handle_gen_write);
+  dev_hook_io(dev, BOCHS_INFO_PORT, NULL, &handle_info_write);
+  dev_hook_io(dev, BOCHS_DEBUG_PORT, NULL, &handle_debug_write);
+  
+  return 0;
+}
+
+static int debug_deinit(struct vm_device * dev) {
+  dev_unhook_io(dev, BOCHS_PORT1);
+  dev_unhook_io(dev, BOCHS_PORT2);
+  dev_unhook_io(dev, BOCHS_INFO_PORT);
+  dev_unhook_io(dev, BOCHS_DEBUG_PORT);
+
+  return 0;
+};
+
+
+
+
+static struct vm_device_ops dev_ops = {
+  .init = debug_init,
+  .deinit = debug_deinit,
+  .reset = NULL,
+  .start = NULL,
+  .stop = NULL,
+};
+
+
+struct vm_device * create_bochs_debug() {
+  struct debug_state * state = NULL;
+
+  state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
+
+  V3_ASSERT(state != NULL);
+
+  PrintDebug("Creating Bochs Debug Device\n");
+  struct vm_device * device = create_device("BOCHS Debug", &dev_ops, state);
+
+
+
+  return device;
+}
 
   char buffer[SERIAL_BUF_LEN];
 };
 
-int queue_data(struct serial_buffer * buf, char data) {
+static int queue_data(struct serial_buffer * buf, char data) {
   uint_t next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
 
   if (next_loc == buf->tail) {
   return 0;
 }
 
-int dequeue_data(struct serial_buffer * buf, char * data) {
+static int dequeue_data(struct serial_buffer * buf, char * data) {
   uint_t next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
 
   if (buf->head == buf->tail) {
 };
 
 
-int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
   char * val = (char *)src;
   PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src);
 
 
 
-int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
   char * val = (char *)dst;
   PrintDebug("Read from Data Port 0x%x\n", port);
 
 
 
-int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) {
+static int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) {
   
 
   return -1;
 }
 
 
-int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
   char * val = (char *)src;
   PrintDebug("Write to Control Port (val=%x)\n", *(char *)src);
 
 
 
-int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
   char * val = (char *)dst;
   PrintDebug("Read from Control Port\n");
 }
 
 
-int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
   PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src);
 
   return -1;
 }
 
-int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
   char * val = (char *)dst;
   PrintDebug("Read from Status Port 0x%x\n", port);
   return 0;
 }
 
-int serial_init(struct vm_device * dev) {
+static int serial_init(struct vm_device * dev) {
   struct serial_state * state = (struct serial_state *)dev->private_data;
 
 
 }
 
 
-int serial_deinit(struct vm_device * dev) {
+static int serial_deinit(struct vm_device * dev) {
 
 
   dev_unhook_io(dev, COM1_DATA_PORT);
 
 #include <devices/generic.h>
 #include <devices/ramdisk.h>
 #include <devices/cdrom.h>
+#include <devices/bochs_debug.h>
 
 
 #include <palacios/vmm_host_events.h>
 }
 
 
-/*static int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
-
-  struct guest_info * info = priv_data;
-  ulong_t tsc_spread = 0;
-  ullong_t exit_tsc = 0;
-
-  
-  *(ulong_t *)(&exit_tsc) = info->vm_regs.rbx;
-  *(ulong_t *)((&exit_tsc) + 4) = info->vm_regs.rcx; 
-  tsc_spread = info->exit_tsc - exit_tsc;
-  
-  PrintError("IOREAD tsc diff = %lu\n",tsc_spread); 
-  info->rip += 3;
-
-
-  return 1;
-}
-*/
-
-
-
 
 int config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
 
     struct vm_device * pic = create_pic();
     struct vm_device * keyboard = create_keyboard();
     struct vm_device * pit = create_pit(); 
+    struct vm_device * bochs_debug = create_bochs_debug();
 
     //struct vm_device * serial = create_serial();
     struct vm_device * generic = NULL;
     v3_attach_device(info, pit);
     v3_attach_device(info, keyboard);
     // v3_attach_device(info, serial);
+    v3_attach_device(info, bochs_debug);
 
     if (use_ramdisk) {
       v3_attach_device(info, ramdisk);