#define PCI_MEM32_BASE(bar_val) (bar_val & 0xfffffff0)
 
 struct pci_device {
+
     union {
        uint8_t config_space[256];
 
        } __attribute__((packed));
     } __attribute__((packed));
 
-
-
     struct v3_pci_bar bar[6];
 
-    uint_t bus_num;
     struct rb_node dev_tree_node;
 
-    int dev_num;
+    uint_t bus_num;
+
+    union {
+       uint8_t devfn;
+       struct {
+           uint8_t fn_num       : 3;
+           uint8_t dev_num      : 5;
+       } __attribute__((packed));
+    } __attribute__((packed));
+
     char name[64];
 
     struct vm_device * vm_dev;  //the corresponding virtual device
     int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled);
     int (*ext_rom_update)(struct pci_device *pci_dev);
 
-
     int ext_rom_update_flag;
     int bar_update_flag;
 
 struct pci_device * 
 v3_pci_register_device(struct vm_device * pci,
                       pci_device_type_t dev_type, 
-                      uint_t bus_num,
-                      const char * name,
+                      int bus_num,
                       int dev_num,
+                      int fn_num,
+                      const char * name,
                       struct v3_pci_bar * bars,
                       int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
                       int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
 
--- /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) 2009, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author:  Lei Xia <lxia@northwestern.edu>
+ *             Chang Seok Bae <jhuell@gmail.com>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_SOUTHBRIDGE_H__
+#define __DEVICES_SOUTHBRIDGE_H__
+
+
+#ifdef __V3VEE__
+
+
+typedef enum {V3_SB_INVALID, V3_SB_PIIX3, V3_SB_PIIX4, V3_SB_CMD646} v3_southbridge_type_t;
+
+struct v3_southbridge {
+    struct vm_device * pci_bus;
+    struct pci_device * southbridge_pci;
+
+    v3_southbridge_type_t type;
+};
+
+
+#endif // ! __V3VEE__
+
+#endif
 
 
 #include <palacios/vmm.h>
 #include <devices/i440fx.h>
+#include <devices/pci.h>
 
 struct i440_state {
-    int foo;
+    struct vm_device * pci;
 };
 
 
 }
 
 
-static int i440_init(struct vm_device * dev) {
-    // struct i440_state * state = (struct i440_state *)(dev->private_data);
-
-   
-    v3_dev_hook_io(dev, 0x00b2, 
-                  &io_read, &io_write);
-    v3_dev_hook_io(dev, 0x00b3, 
-                  &io_read, &io_write);
 
+static int i440_init(struct vm_device * dev) {
+    struct i440_state * state = (struct i440_state *)(dev->private_data);
+    struct pci_device * pci_dev = NULL;
+    struct v3_pci_bar bars[6];
+    int i;
 
-    v3_dev_hook_io(dev, 0x0cf8, 
-                  &io_read, &io_write);
+    for (i = 0; i < 4; i++) {
+       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++) {
+       bars[i].type = PCI_BAR_NONE;
+    }    
 
+    pci_dev = v3_pci_register_device(state->pci, PCI_STD_DEVICE, 0, 0, 0, "i440FX", bars,
+                                    NULL, NULL, NULL, dev);
 
-    v3_dev_hook_io(dev, 0x0cf9, 
-                  &io_read, &io_write);
+    if (!pci_dev) {
+       return -1;
+    }
 
+    pci_dev->config_header.vendor_id = 0x8086;
+    pci_dev->config_header.device_id = 0x1237;
+    pci_dev->config_header.revision = 0x0002;
+    pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
+    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
 
+    pci_dev->config_space[0x72] = 0x02; // SMRAM (?)
 
     return 0;
 }
 
 
 struct vm_device * v3_create_i440fx(struct vm_device * pci) {
-
     struct i440_state * state = NULL;
 
-
     state = (struct i440_state *)V3_Malloc(sizeof(struct i440_state));
+
+    state->pci = pci;
        
     struct vm_device * i440_dev = v3_create_device("i440FX", &dev_ops, state);
 
     return i440_dev;
-
 }
 
 #include <palacios/vm_guest_mem.h>
 #include <devices/ide.h>
 #include <devices/pci.h>
+#include <devices/southbridge.h>
 #include "ide-types.h"
 #include "atapi-types.h"
 
 
     int irq; // this is temporary until we add PCI support
 
-    struct pci_device * pci_dev;
-
     // Control Registers
     struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
 
 
 struct ide_internal {
     struct ide_channel channels[2];
-    struct vm_device * pci;
-    struct vm_device * southbridge;
-    struct pci_device * busmaster_pci;
+
+    struct v3_southbridge * southbridge;
+    struct vm_device * pci_bus;
+
+    struct pci_device * ide_pci;
 };
 
 
 }
 
 
-/* 
- * This is an ugly ugly ugly way to differentiate between the first and second DMA channels 
- */
-
-static int write_dma_port(ushort_t port_offset, void * src, uint_t length, struct vm_device * dev, struct ide_channel * channel);
-static int read_dma_port(ushort_t port_offset, void * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel);
-
-
-static int write_pri_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Writing PRI DMA Port %x (%s) (val=%x)\n", port, dma_port_to_str(port & 0x7), *(uint32_t *)src);
-    return write_dma_port(port & 0x7, src, length, dev, &(ide->channels[0]));
-}
-
-static int write_sec_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Writing SEC DMA Port %x (%s) (val=%x)\n", port, dma_port_to_str(port & 0x7), *(uint32_t *)src);
-    return write_dma_port(port & 0x7, src, length, dev, &(ide->channels[1]));
-}
-
-
-static int read_pri_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Reading PRI DMA Port %x (%s)\n", port, dma_port_to_str(port & 0x7));
-    return read_dma_port(port & 0x7, dst, length, dev, &(ide->channels[0]));
-}
-
-static int read_sec_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
-    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    PrintDebug("IDE: Reading SEC DMA Port %x (%s)\n", port, dma_port_to_str(port & 0x7));
-    return read_dma_port(port & 0x7, dst, length, dev, &(ide->channels[1]));
-}
-
 
 #define DMA_CMD_PORT      0x00
 #define DMA_STATUS_PORT   0x02
 #define DMA_PRD_PORT2     0x06
 #define DMA_PRD_PORT3     0x07
 
+#define DMA_CHANNEL_FLAG  0x08
 
-static int write_dma_port(ushort_t port_offset, void * src, uint_t length, 
-                         struct vm_device * dev, struct ide_channel * channel) {
+static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->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]);
 
     switch (port_offset) {
        case DMA_CMD_PORT:
 }
 
 
-static int read_dma_port(ushort_t port_offset, void * dst, uint_t length, 
-                        struct vm_device * dev, struct ide_channel * channel) {
+static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->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]);
 
     switch (port_offset) {
        case DMA_CMD_PORT:
 
 static int init_ide_state(struct vm_device * dev) {
     struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
-    int i, j;
-
+    int i;
 
     /* 
-       Check if the PIIX 3 actually represents both IDE channels in a single PCI entry */
+     * Check if the PIIX 3 actually represents both IDE channels in a single PCI entry 
+     */
 
     for (i = 0; i < 1; i++) {
        init_channel(&(ide->channels[i]));
 
        // JRL: this is a terrible hack...
        ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
-
-
-       if (ide->pci) {
-           struct v3_pci_bar bars[6];
-           struct pci_device * pci_dev = NULL;
-
-           for (j = 0; j < 6; j++) {
-               bars[j].type = PCI_BAR_NONE;
-           }
-
-
-           bars[4].type = PCI_BAR_IO;
-           bars[4].default_base_port = PRI_DEFAULT_DMA_PORT + (i * 0x8);
-           bars[4].num_ports = 8;
-           
-           if (i == 0) {
-               bars[4].io_read = read_pri_dma_port;
-               bars[4].io_write = write_pri_dma_port;
-           } else {
-               bars[4].io_read = read_sec_dma_port;
-               bars[4].io_write = write_sec_dma_port;
-           }
-
-           pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
-                                            pci_config_update, NULL, NULL, dev);
-
-           if (pci_dev == NULL) {
-               PrintError("Failed to register IDE BUS %d with PCI\n", i); 
-               return -1;
-           }
-
-           ide->channels[i].pci_dev = pci_dev;
-
-           /* This is for CMD646 devices 
-              pci_dev->config_header.vendor_id = 0x1095;
-              pci_dev->config_header.device_id = 0x0646;
-              pci_dev->config_header.revision = 0x8f07;
-           */
-           pci_dev->config_header.vendor_id = 0x8086;
-           pci_dev->config_header.device_id = 0x7010;
-           pci_dev->config_header.revision = 0x8000;
-           
-           pci_dev->config_header.subclass = 0x01;
-           pci_dev->config_header.class = 0x01;
-           
-           
-           pci_dev->config_header.command = 0;
-           pci_dev->config_header.status = 0x0280;
-           
-           //      pci_dev->config_header.intr_line = PRI_DEFAULT_IRQ + i;
-           //      pci_dev->config_header.intr_pin = 1;
-       }
-       
-
     }
 
+
     return 0;
 }
 
 
 
 static int init_ide(struct vm_device * dev) {
-    //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
 
     PrintDebug("IDE: Initializing IDE\n");
 
     v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
                   &read_port_std, &write_port_std);
 
+
+
+
+    if (ide->pci_bus) {
+       struct v3_pci_bar bars[6];
+       struct v3_southbridge * southbridge = (struct v3_southbridge *)(ide->southbridge);
+       struct pci_device * sb_pci = (struct pci_device *)(southbridge->southbridge_pci);
+       struct pci_device * pci_dev = NULL;
+       int i;
+
+       for (i = 0; i < 6; i++) {
+           bars[i].type = PCI_BAR_NONE;
+       }
+
+       bars[4].type = PCI_BAR_IO;
+       bars[4].default_base_port = PRI_DEFAULT_DMA_PORT;
+       bars[4].num_ports = 16;
+
+       bars[4].io_read = read_dma_port;
+       bars[4].io_write = write_dma_port;
+       
+       pci_dev = v3_pci_register_device(ide->pci_bus, PCI_STD_DEVICE, 0, sb_pci->dev_num, 1, 
+                                        "PIIX3_IDE", bars,
+                                        pci_config_update, NULL, NULL, dev);
+
+       if (pci_dev == NULL) {
+           PrintError("Failed to register IDE BUS %d with PCI\n", i); 
+           return -1;
+       }
+
+       /* This is for CMD646 devices 
+          pci_dev->config_header.vendor_id = 0x1095;
+          pci_dev->config_header.device_id = 0x0646;
+          pci_dev->config_header.revision = 0x8f07;
+       */
+
+       pci_dev->config_header.vendor_id = 0x8086;
+       pci_dev->config_header.device_id = 0x7010;
+       pci_dev->config_header.revision = 0x8000;
+
+       pci_dev->config_header.subclass = 0x01;
+       pci_dev->config_header.class = 0x01;
+
+       pci_dev->config_header.command = 0;
+       pci_dev->config_header.status = 0x0280;
+    }
+
     return 0;
 }
 
 };
 
 
-struct vm_device *  v3_create_ide(struct vm_device * pci, struct vm_device * southbridge) {
+struct vm_device *  v3_create_ide(struct vm_device * pci_bus, struct vm_device * southbridge_dev) {
     struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
     struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
 
-    ide->pci = pci;
-    ide->southbridge = southbridge;
+    ide->pci_bus = pci_bus;
+    ide->southbridge = (struct v3_southbridge *)(southbridge_dev->private_data);
 
     PrintDebug("IDE: Creating IDE bus x 2\n");
 
 
     parent = *p;
     tmp_dev = rb_entry(parent, struct pci_device, dev_tree_node);
 
-    if (dev->dev_num < tmp_dev->dev_num) {
+    if (dev->devfn < tmp_dev->devfn) {
       p = &(*p)->rb_left;
-    } else if (dev->dev_num > tmp_dev->dev_num) {
+    } else if (dev->devfn > tmp_dev->devfn) {
       p = &(*p)->rb_right;
     } else {
       return tmp_dev;
 }
 
 
-static struct pci_device * get_device(struct pci_bus * bus, int dev_num) {
+static struct pci_device * get_device(struct pci_bus * bus, uint8_t dev_num, uint8_t fn_num) {
     struct rb_node * n = bus->devices.rb_node;
     struct pci_device * dev = NULL;
+    uint8_t devfn = ((dev_num & 0x1f) << 3) | (fn_num & 0x7);
 
     while (n) {
        dev = rb_entry(n, struct pci_device, dev_tree_node);
        
-       if (dev_num < dev->dev_num) {
+       if (devfn < dev->devfn) {
            n = n->rb_left;
-       } else if (dev_num > dev->dev_num) {
+       } else if (devfn > dev->devfn) {
            n = n->rb_right;
        } else {
            return dev;
               reg_num, reg_num, 
               pci_state->addr_reg.val);
 
-    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
+    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
     
     if (pci_dev == NULL) {
        for (i = 0; i < length; i++) {
                return 1;
  
        }
+    } else if (header_type == 0x80) {
+       switch (reg_num) {
+           case 0x00:
+           case 0x01:
+           case 0x02:
+           case 0x03:
+           case 0x08:
+           case 0x09:
+           case 0x0a:
+           case 0x0b:
+           case 0x0e:
+           case 0x3d:
+               return 0;
+                           
+           default:
+               return 1;
+ 
+       }
     } else {
        // PCI to PCI Bridge = 0x01
        // CardBus Bridge = 0x02
               *(uint32_t *)src, length);
 
 
-    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
+    pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
     
     if (pci_dev == NULL) {
        PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
 
     for (i = 0; i < length; i++) {
        uint_t cur_reg = reg_num + i;
+       int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
+       
+       if (writable == -1) {
+           PrintError("Invalid PCI configuration space\n");
+           return -1;
+       }
 
-       if (is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg)) {
+       if (writable) {
            pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
 
            if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
 
 
 
-
-static int init_i440fx(struct vm_device * dev) {
-    struct pci_device * pci_dev = NULL;
-    struct v3_pci_bar bars[6];
-    int i;
-    
-    for (i = 0; i < 6; i++) {
-       bars[i].type = PCI_BAR_NONE;
-    }    
-
-    pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "i440FX", 0, bars,
-                                    NULL, NULL, NULL, NULL);
-    
-    if (!pci_dev) {
-       return -1;
-    }
-    
-    pci_dev->config_header.vendor_id = 0x8086;
-    pci_dev->config_header.device_id = 0x1237;
-    pci_dev->config_header.revision = 0x0002;
-    pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
-    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
-
-    pci_dev->bus_num = 0;
-    return 0;
-}
-
-
-
-
 static void init_pci_busses(struct pci_internal * pci_state) {
     int i;
 
     pci_state->addr_reg.val = 0; 
 
     init_pci_busses(pci_state);
-
-    if (init_i440fx(dev) == -1) {
-       PrintError("Could not intialize i440fx\n");
-       return -1;
-    }
     
     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
     
 // if dev_num == -1, auto assign 
 struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           pci_device_type_t dev_type, 
-                                          uint_t bus_num,
-                                          const char * name,
+                                          int bus_num,
                                           int dev_num,
+                                          int fn_num,
+                                          const char * name,
                                           struct v3_pci_bar * bars,
                                           int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
                                           int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
        }
     }
     
-    if (get_device(bus, dev_num) != NULL) {
+    if (get_device(bus, dev_num, fn_num) != NULL) {
        PrintError("PCI Device already registered at slot %d on bus %d\n", 
                   dev_num, bus->bus_num);
        return NULL;
     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
 
     if (pci_dev == NULL) {
+       PrintError("Could not allocate pci device\n");
        return NULL;
     }
 
     memset(pci_dev, 0, sizeof(struct pci_device));
-    
+
     
     switch (dev_type) {
        case PCI_STD_DEVICE:
            pci_dev->config_header.header_type = 0x00;
            break;
+       case PCI_MULTIFUNCTION:
+           pci_dev->config_header.header_type = 0x80;
+           break;
        default:
            PrintError("Unhandled PCI Device Type: %d\n", dev_type);
            return NULL;
 
     pci_dev->bus_num = bus_num;
     pci_dev->dev_num = dev_num;
+    pci_dev->fn_num = fn_num;
 
     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
     pci_dev->vm_dev = dev;
     pci_dev->ext_rom_update = ext_rom_update;
 
 
-
     //copy bars
-    for (i = 0; i < 6; i ++){
+    for (i = 0; i < 6; i ++) {
        pci_dev->bar[i].type = bars[i].type;
 
        if (pci_dev->bar[i].type == PCI_BAR_IO) {
 
 #include <devices/piix3.h>
 #include <palacios/vmm.h>
 #include <devices/pci.h>
+#include <devices/southbridge.h>
+
+
+
+static int reset_piix3(struct vm_device * dev) {
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+    struct pci_device * pci_dev = piix3->southbridge_pci;
+
+    pci_dev->config_header.command = 0x0007; // master, memory and I/O
+    pci_dev->config_header.status = 0x0200;
+
+    pci_dev->config_space[0x4c] = 0x4d;
+    pci_dev->config_space[0x4e] = 0x03;
+    pci_dev->config_space[0x4f] = 0x00;
+    pci_dev->config_space[0x60] = 0x80;
+    pci_dev->config_space[0x69] = 0x02;
+    pci_dev->config_space[0x70] = 0x80;
+    pci_dev->config_space[0x76] = 0x0c;
+    pci_dev->config_space[0x77] = 0x0c;
+    pci_dev->config_space[0x78] = 0x02;
+    pci_dev->config_space[0x79] = 0x00;
+    pci_dev->config_space[0x80] = 0x00;
+    pci_dev->config_space[0x82] = 0x00;
+    pci_dev->config_space[0xa0] = 0x08;
+    pci_dev->config_space[0xa2] = 0x00;
+    pci_dev->config_space[0xa3] = 0x00;
+    pci_dev->config_space[0xa4] = 0x00;
+    pci_dev->config_space[0xa5] = 0x00;
+    pci_dev->config_space[0xa6] = 0x00;
+    pci_dev->config_space[0xa7] = 0x00;
+    pci_dev->config_space[0xa8] = 0x0f;
+    pci_dev->config_space[0xaa] = 0x00;
+    pci_dev->config_space[0xab] = 0x00;
+    pci_dev->config_space[0xac] = 0x00;
+    pci_dev->config_space[0xae] = 0x00;
 
+    return 0;
+}
 
-struct piix3_state {
-    uint8_t pci_dev_num;
 
-    struct vm_device * pci;
+static int init_piix3(struct vm_device * dev) {
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
+    struct pci_device * pci_dev = NULL;
+    struct v3_pci_bar bars[6];
+    int i;
 
-};
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
+    }
 
+    pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
+                                    0, -1, 0, 
+                                    "PIIX3", bars, 
+                                    NULL, NULL, NULL, dev);
+    if (!pci_dev) {
+       PrintError("Could not register PCI Device for PIIX3\n");
+       return -1;
+    }
 
-static int init_piix3(struct vm_device * dev) {
+    pci_dev->config_header.vendor_id = 0x8086;
+    pci_dev->config_header.device_id = 0x7000; // PIIX4 is 0x7001
+    pci_dev->config_header.subclass = 0x01; //  SubClass: host2pci
+    pci_dev->config_header.class = 0x06;    // Class: PCI bridge
+
+    piix3->southbridge_pci = pci_dev;
+
+    reset_piix3(dev);
 
     return 0;
 }
 static struct vm_device_ops dev_ops = {
     .init = init_piix3,
     .deinit = deinit_piix3,
-    .reset = NULL,
+    .reset = reset_piix3,
     .start = NULL,
     .stop = NULL,
 };
 
 
 struct vm_device * v3_create_piix3(struct vm_device * pci) {
-    struct piix3_state * piix3 = (struct piix3_state *)V3_Malloc(sizeof(struct piix3_state));
+    struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
     struct vm_device * dev = NULL;
 
-    piix3->pci = pci;
+    piix3->pci_bus = pci;
+    piix3->type = V3_SB_PIIX3;
     
     dev = v3_create_device("PIIX3", &dev_ops, piix3);
 
 
     v3_attach_device(info, para_net);
 
     if (config_ptr->enable_pci == 1) {
+       PrintDebug("Attaching PCI\n");
        v3_attach_device(info, pci);
+       PrintDebug("Attaching Northbridge\n");
        v3_attach_device(info, northbridge);
+       PrintDebug("Attaching Southbridge\n");
        v3_attach_device(info, southbridge);
     }
 
+    PrintDebug("Attaching IDE\n");
     v3_attach_device(info, ide);