* redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#include <devices/ethernet.h>
 #include <devices/pci.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 #include <palacios/vmm_io.h>
 #include <palacios/vmm_debug.h>
 #include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_ethernet.h>
+#include <palacios/vmm_sprintf.h>
+
 
 
 #ifndef CONFIG_DEBUG_RTL8139
 #define PrintDebug(fmts, args...)
 #endif
 
-
-
-#define NIC_BASE_ADDR  0xc100
-#define NIC_IRQ                11
-
-#define RTL8139_IDR0    (0x00)         /* ID Registers */
-#define RTL8139_IDR1    (0x01)
-#define RTL8139_IDR2    (0x02)
-#define RTL8139_IDR3    (0x03)
-#define RTL8139_IDR4    (0x04)
-#define RTL8139_IDR5    (0x05)
-
-#define RTL8139_MAR0    (0x08) /* Mulicast Registers*/
-#define RTL8139_MAR1    (0x09)
-#define RTL8139_MAR2    (0x0a)
-#define RTL8139_MAR3    (0x0b)
-#define RTL8139_MAR4    (0x0c)
-#define RTL8139_MAR5    (0x0d)
-#define RTL8139_MAR6    (0x0e)
-#define RTL8139_MAR7    (0x0f)
+#define RTL8139_IDR0    (0x00) /* ID Registers start, len 6*1bytes */
+#define RTL8139_MAR0    (0x08) /* Mulicast Registers start, len 8*1bytes */
 
 #define RTL8139_TSD0    (0x10) /* Tx Status of Descriptors */
 #define RTL8139_TSD1    (0x14)
 #define RTL8139_CONFIG4 (0x5a)
 #define RTL8139_MULINT  (0x5c) /* Multiple Intrpt Select */
 #define RTL8139_RERID   (0x5e) 
-#define RTL8139_TSAD    (0x60) /* Tx Status of All Descriptors */
+#define RTL8139_TXSAD    (0x60)        /* Tx Status of All Descriptors */
 #define RTL8139_BMCR    (0x62) /* Basic Mode Control Register */
 #define RTL8139_BMSR    (0x64) /* Basic Mode Status Register */
 #define RTL8139_ANAR    (0x66) /* Auto-Negotiation Advertisement Register */
 #define RTL8139_TW_PARM (0x7c) /* Twister parameter */
 #define RTL8139_PHY2_PARM   (0x80)
 
-#define RTL8139_CRC0    (0x84) /* Power Management CRC Reg for wakeup frame */
-#define RTL8139_CRC1    (0x85)
-#define RTL8139_CRC2    (0x86)
-#define RTL8139_CRC3    (0x87)
-#define RTL8139_CRC4    (0x88)
-#define RTL8139_CRC5    (0x89)
-#define RTL8139_CRC6    (0x8a)
-#define RTL8139_CRC7    (0x8b)
+#define RTL8139_CRC0    (0x84) /* Power Management CRC Reg for wakeup frame 8*1bytes */
 
 #define RTL8139_Wakeup0        (0x8c)  /* Power Management wakeup frame */
 #define RTL8139_Wakeup1        (0x94)
 
 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
 
-enum TxStatusBits
-{
-    TSD_Own = 0x2000,
-    TSD_Tun = 0x4000,
-    TSD_Tok = 0x8000,
-    TSD_Cdh = 0x10000000,
-    TSD_Owc = 0x20000000,
-    TSD_Tabt = 0x40000000,
-    TSD_Crs = 0x80000000,
+enum TxStatusBits {
+    TSD_Own = 1<<13,
+    TSD_Tun = 1<<14,
+    TSD_Tok = 1<<15,
+    TSD_Cdh = 1<<28,
+    TSD_Owc = 1<<29,
+    TSD_Tabt = 1<<30,
+    TSD_Crs = 1<<31,
 };
 
+/* Transmit Status Register (TSD0-3) Offset: 0x10-0x1F */
+struct tx_status_reg {
+    union {
+       uint16_t val;
+       struct {
+           uint16_t size     : 13;
+           uint8_t own     : 1;
+           uint8_t tun     : 1;
+           uint8_t tok     : 1;        
+           uint8_t er_tx_th   : 6;
+           uint8_t reserved    : 2;
+           uint8_t ncc            : 4;
+           uint8_t cdh : 1;
+           uint8_t owc : 1;
+           uint8_t tabt        : 1;
+           uint8_t crs : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
 enum RxStatusBits {
-    Rx_Multicast = 0x8000,
-    Rx_Physical = 0x4000,
-    Rx_Broadcast = 0x2000,
-    Rx_BadSymbol = 0x0020,
-    Rx_Runt = 0x0010,
-    Rx_TooLong = 0x0008,
-    Rx_CRCErr = 0x0004,
-    Rx_BadAlign = 0x0002,
-    Rx_StatusOK = 0x0001,
+    Rx_Multicast = 1<<15,
+    Rx_Physical = 1<<14,
+    Rx_Broadcast = 1<<13,
+    Rx_BadSymbol = 1<<5,
+    Rx_Runt = 1<<4,
+    Rx_TooLong = 1<<3,
+    Rx_CRCErr = 1<<2,
+    Rx_BadAlign = 1<<1,
+    Rx_OK = 1<<0,
 };
 
 
+/* Receive Status Register in RX Packet Header */
+struct rx_status_reg {
+    union {
+       uint16_t val;
+       struct {
+           uint8_t rx_ok     : 1;
+           uint8_t rx_bad_align     : 1;
+           uint8_t rx_crc_err     : 1;
+           uint8_t rx_too_long     : 1;        
+           uint8_t rx_runt     : 1;
+           uint8_t rx_bad_sym  : 1;
+           uint8_t reserved    : 7;
+           uint8_t rx_brdcast  : 1;
+           uint8_t rx_phys     : 1;
+           uint8_t rx_multi    : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+/* ERSR - Early Rx Status Register Offset: 0x36*/
+struct errx_status_reg{
+    union {
+       uint8_t val;
+       struct {
+           uint8_t er_rx_ok     : 1;
+           uint8_t er_rx_ovw     : 1;
+           uint8_t er_rx_bad_pkt     : 1;
+           uint8_t er_rx_good     : 1; 
+           uint8_t reserved    : 4;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
 /* Transmit Status of All Descriptors (TSAD) Register */
 enum TSAD_bits {
- TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3
- TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2
- TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1
- TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0
- TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3
- TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2
- TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1
- TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0
- TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3
- TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2
- TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1
- TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0
- TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3
- TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2
- TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1
- TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0
+    TSAD_TOK3 = 1<<15, /* TOK bits of Descriptors*/
+    TSAD_TOK2 = 1<<14, 
+    TSAD_TOK1 = 1<<13, 
+    TSAD_TOK0 = 1<<12, 
+    TSAD_TUN3 = 1<<11, /* TUN bits of Descriptors */
+    TSAD_TUN2 = 1<<10, 
+    TSAD_TUN1 = 1<<9, 
+    TSAD_TUN0 = 1<<8,
+    TSAD_TABT3 = 1<<7, /* TABT bits of Descriptors */
+    TSAD_TABT2 = 1<<6,
+    TSAD_TABT1 = 1<<5,
+    TSAD_TABT0 = 1<<4,
+    TSAD_OWN3 = 1<<3, /* OWN bits of Descriptors */
+    TSAD_OWN2 = 1<<2,
+    TSAD_OWN1 = 1<<1, 
+    TSAD_OWN0 = 1<<0,
 };
 
-enum ISRBits
-{
-    ISR_Rok = 0x1,
-    ISR_Rer = 0x2,
-    ISR_Tok = 0x4,
-    ISR_Ter = 0x8,
-    ISR_Rxovw = 0x10,
-    ISR_Pun = 0x20,
-    ISR_Fovw = 0x40,
-    ISR_Lenchg = 0x2000,
-    ISR_Timeout = 0x4000,
-    ISR_Serr = 0x8000,
+
+/* Transmit Status of All Descriptors (TSAD) Register Offset: 0x60-0x61*/
+struct txsad_reg {
+    union {
+       uint16_t val;
+       struct {
+           uint8_t own0     : 1;
+           uint8_t own1     : 1;
+           uint8_t own2     : 1;
+           uint8_t own3     : 1;       
+           uint8_t tabt0       : 1;
+           uint8_t tabt1       : 1;
+           uint8_t tabt2       : 1;
+           uint8_t tabt3       : 1;
+           uint8_t tun0        : 1;
+           uint8_t tun1        : 1;
+           uint8_t tun2        : 1;
+           uint8_t tun3        : 1;
+           uint8_t tok0        : 1;
+           uint8_t tok1        : 1;
+           uint8_t tok2        : 1;
+           uint8_t tok3        : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+enum ISRBits {
+    ISR_Rok = 1<<0,
+    ISR_Rer = 1<<1,
+    ISR_Tok = 1<<2,
+    ISR_Ter = 1<<3,
+    ISR_Rxovw = 1<<4,
+    ISR_Pun = 1<<5,
+    ISR_Fovw = 1<<6,
+    ISR_Lenchg = 1<<13,
+    ISR_Timeout = 1<<14,
+    ISR_Serr = 1<<15,
 };
 
-enum CMDBits
-{
-    CMD_Bufe = 0x1,
-    CMD_Te = 0x4,
-    CMD_Re = 0x8,
-    CMD_Rst = 0x10,
+/* 
+ * Interrupt Status Register (ISR) Offset: ox3e-0x3f
+ * Interrupt Mask Register (IMR 0x3c-0x3d) shares the same structure
+ */
+struct isr_imr_reg {
+    union {
+       uint16_t val;
+       struct {
+           uint8_t rx_ok       :1;
+           uint8_t rx_err     : 1;
+           uint8_t tx_ok        : 1;
+           uint8_t tx_err          : 1;
+           uint8_t rx_ovw          : 1;
+           uint8_t pun_linkchg          : 1;
+           uint8_t rx_fifo_ovw  : 1;
+           uint8_t reservd:     6;
+           uint8_t lenchg  :1;
+           uint8_t timeout   :1;
+           uint8_t syserr  :1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+enum CMDBits {
+    CMD_Bufe = 1<<0,
+    CMD_Te = 1<<2,
+    CMD_Re = 1<<3,
+    CMD_Rst = 1<<4,
 };
 
+
+/* Commmand Register Offset: 0x37 */
+struct cmd_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint8_t cmd_bufe      : 1;
+           uint8_t reservd_1        : 1;
+           uint8_t cmd_te          : 1;
+           uint8_t cmd_re          : 1;
+           uint8_t cmd_rst          : 1;
+           uint8_t reservd_2  : 3;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
 enum CMD9346Bits {
-       CMD9346_Lock = 0x00,
-       CMD9346_Unlock = 0xC0,
+    CMD9346_Lock = 0x00,
+    CMD9346_Unlock = 0xC0,
 };
 
+
+
+/* 93C46 Commmand Register Offset: 0x50 */
+struct cmd9346_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint8_t eedo      : 1;
+           uint8_t eedi        : 1;
+           uint8_t eesk          : 1;
+           uint8_t eecs          : 1;
+           uint8_t reserved    : 2;
+           uint8_t eem  : 2;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
 // Bits in TxConfig.
 enum TXConfig_bits{
 
         /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
-      TxIFGShift = 24,
-      TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */
-      TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */
-      TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */
-      TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */
-
-       TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
-       TxCRC = (1 << 16),      /* DISABLE appending CRC to end of Tx packets */
-       TxClearAbt = (1 << 0),  /* Clear abort (WO) */
-       TxDMAShift = 8,         /* DMA burst value (0-7) is shifted this many bits */
-       TxRetryShift = 4,       /* TXRR value (0-15) is shifted this many bits */
-
-       TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
+    TxIFGShift = 24,
+    TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */
+    TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */
+    TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */
+    TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */
+
+    TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
+    TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
+    TxClearAbt = (1 << 0),     /* Clear abort (WO) */
+    TxDMAShift = 8,            /* DMA burst value (0-7) is shifted this many bits */
+    TxRetryShift = 4,  /* TXRR value (0-15) is shifted this many bits */
+
+    TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
 };
 
+
+/* Transmit Configuration Register (TCR) Offset: 0x40-0x43 */
+struct tx_config_reg {
+    union {
+       uint32_t val;
+       struct {
+           uint8_t clr_abort   :1;
+           uint8_t reserved_1     : 3;
+           uint8_t tx_retry_cnt        : 4;
+           uint8_t max_dma          : 3;
+           uint8_t reserved_2          : 5;
+           uint8_t tx_crc          : 1;
+           uint8_t loop_test  : 2;
+           uint8_t reservd_3:     3;
+           uint8_t hw_verid_b  :2;
+           uint8_t ifg   :2;
+           uint8_t hw_verid_a  :5;
+           uint8_t reservd_4  :1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
 enum CSCRBits {
     CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */
     CSCR_LD  = 1<<9,  /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/
     CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/
 };
 
+
+/* CS Configuration Register (CSCR) Offset: 0x74-0x75 */
+struct cscr_reg {
+    union {
+       uint16_t val;
+       struct {
+           uint8_t pass_scr    :1;
+           uint8_t reserved_1     : 1;
+           uint8_t con_status_en        : 1;
+           uint8_t con_status          : 1;
+           uint8_t reserved_2          : 1;
+           uint8_t f_connect          : 1;
+           uint8_t f_link_100  : 1;
+           uint8_t jben:     1;
+           uint8_t heart_beat  :1;
+           uint8_t ld   :1;
+           uint8_t reservd_3  :5;
+           uint8_t test_fun  :1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
 /* Bits in RxConfig. */
 enum rx_mode_bits {
-       AcceptErr = 0x20,
-       AcceptRunt = 0x10,
-       AcceptBroadcast = 0x08,
-       AcceptMulticast = 0x04,
-       AcceptMyPhys = 0x02,
-       AcceptAllPhys = 0x01,
+    AcceptErr = 0x20,
+    AcceptRunt = 0x10,
+    AcceptBroadcast = 0x08,
+    AcceptMulticast = 0x04,
+    AcceptMyPhys = 0x02,
+    AcceptAllPhys = 0x01,
 };
 
+
+/* Receive Configuration Register (RCR) Offset: 0x44-0x47 */
+struct rx_config_reg {
+    union {
+       uint32_t val;
+       struct {
+           uint8_t all_phy   : 1;
+           uint8_t my_phy      : 1;
+           uint8_t all_multi     : 1;
+           uint8_t all_brdcast        : 1;
+           uint8_t acpt_runt          : 1;
+           uint8_t acpt_err          : 1;
+           uint8_t reserved_1          : 1;
+           uint8_t wrap  : 1;
+           uint8_t max_dma:     3;
+           uint8_t rx_buf_len  :2;
+           uint8_t rx_fifo_thresd   :3;
+           uint8_t rer8  :1;
+           uint8_t mul_er_intr  :1;
+           uint8_t reserved_2          : 6;
+           uint8_t eraly_rx_thresd   :4;
+           uint8_t reserved_3          : 4;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
 #define RTL8139_PCI_REVID_8139      0x10
 
 #define SET_MASKED(input, mask, curr) \
     Chip9346_op_write_disable = 0x00, /* 00 00zzzz */
 };
 
-enum Chip9346Mode
-{
+enum Chip9346Mode {
     Chip9346_none = 0,
     Chip9346_enter_command_mode,
     Chip9346_read_command,
     Chip9346_data_write_all, /* to input register, then filling contents */
 };
 
-struct EEprom9346
-{
+struct EEprom9346 {
     uint16_t contents[EEPROM_9346_SIZE];
     int      mode;
     uint32_t tick;
 
 
 
-struct rtl8139_state
-{      
+struct rtl8139_state { 
     nic_state_t dev_state;
 
     struct v3_vm_info * vm;
     void * backend_data;
 };
 
-
-static void rtl8139_reset(struct vm_device *dev);
-
-static void dump_state(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
-    PrintDebug("====RTL8139: Dumping State Begin==========\n");
-    PrintDebug("Registers\n");
-    int i;
-    uchar_t *reg;
-       reg = (uchar_t *)&nic_state->regs;
-
-    for(i = 0; i < sizeof(struct nic_regs); i++)
-    {
-        PrintDebug("Register[%d] = 0x%2x\n", i, (int)reg[i]);
-    }
-
-    PrintDebug("====RTL8139: Dumping State End==========\n");
-}
-
-static void rtl8139_update_irq(struct rtl8139_state *nic_state)
-{
-    struct pci_device *pdev = nic_state->pci_dev;
-    int irq_line;
-
-    irq_line = pdev->configs[PCI_INTERRUPT_LINE];
+static inline void rtl8139_update_irq(struct rtl8139_state * nic_state) {
     int isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0xffff);
 
-    if(isr & 0xffff)
-    {
-        if (irq_line != 0){
-               v3_raise_irq(dev->vm, irq_line);
-               PrintDebug("VNIC: RaiseIrq %d: isr: 0x%04x imr : 0x%04x\n", irq_line, nic_state->regs.isr, nic_state->regs.imr);
-        } else {
-             PrintError("RTL8139: IRQ_Line: %d\n", irq_line);
-        }
+    if(isr & 0xffff){
+       v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev);
+       nic_state->statistic.interrupts ++;
     }
 }
 
-#if 1
-
-static void prom9346_decode_command(struct EEprom9346 *eeprom, uint8_t command)
-{
+static void prom9346_decode_command(struct EEprom9346 * eeprom, uint8_t command) {
     PrintDebug("RTL8139: eeprom command 0x%02x\n", command);
 
-    switch (command & Chip9346_op_mask)
-    {
+    switch (command & Chip9346_op_mask) {
         case Chip9346_op_read:
-        {
+       {
             eeprom->address = command & EEPROM_9346_ADDR_MASK;
             eeprom->output = eeprom->contents[eeprom->address];
             eeprom->eedo = 0;
         break;
         default:
             eeprom->mode = Chip9346_none;
-            switch (command & Chip9346_op_ext_mask)
-            {
+            switch (command & Chip9346_op_ext_mask) {
                 case Chip9346_op_write_enable:
                     PrintDebug("RTL8139: eeprom write enabled\n");
                     break;
                     PrintDebug("RTL8139: eeprom write disabled\n");
                     break;
             }
-            break;
+        break;
     }
 }
 
-static void prom9346_shift_clock(struct EEprom9346 *eeprom)
-{
+static void prom9346_shift_clock(struct EEprom9346 * eeprom) {
     int bit = eeprom->eedi?1:0;
 
     ++ eeprom->tick;
 
     PrintDebug("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo);
 
-    switch (eeprom->mode)
-    {
+    switch (eeprom->mode) {
         case Chip9346_enter_command_mode:
-            if (bit)
-            {
+            if (bit) {
                 eeprom->mode = Chip9346_read_command;
                 eeprom->tick = 0;
                 eeprom->input = 0;
 
         case Chip9346_read_command:
             eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 8)
-            {
+            if (eeprom->tick == 8) {
                 prom9346_decode_command(eeprom, eeprom->input & 0xff);
             }
             break;
         case Chip9346_data_read:
             eeprom->eedo = (eeprom->output & 0x8000)?1:0;
             eeprom->output <<= 1;
-            if (eeprom->tick == 16)
-            {
+            if (eeprom->tick == 16){
 #if 1
         // the FreeBSD drivers (rl and re) don't explicitly toggle
         // CS between reads (or does setting Cfg9346 to 0 count too?),
 
         case Chip9346_data_write:
             eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 16)
-            {
+            if (eeprom->tick == 16) {
                 PrintDebug("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
                        eeprom->address, eeprom->input);
 
 
         case Chip9346_data_write_all:
             eeprom->input = (eeprom->input << 1) | (bit & 1);
-            if (eeprom->tick == 16)
-            {
+            if (eeprom->tick == 16) {
                 int i;
                 for (i = 0; i < EEPROM_9346_SIZE; i++)
                 {
     }
 }
 
-static int prom9346_get_wire(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static int prom9346_get_wire(struct rtl8139_state * nic_state) {
     struct EEprom9346 *eeprom = &(nic_state->eeprom);
 
-    if (!eeprom->eecs)
+    if (eeprom->eecs == 0)
         return 0;
 
     return eeprom->eedo;
 }
 
-static void prom9346_set_wire(struct vm_device *dev, int eecs, int eesk, int eedi)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static void prom9346_set_wire(struct rtl8139_state * nic_state, 
+                             int eecs, 
+                             int eesk, 
+                             int eedi) {
     struct EEprom9346 *eeprom = &(nic_state->eeprom);
     uint8_t old_eecs = eeprom->eecs;
     uint8_t old_eesk = eeprom->eesk;
     PrintDebug("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
                  eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo);
 
-    if (!old_eecs && eecs)
-    {
+    if (old_eecs == 0 && eecs) {
         /* Synchronize start */
         eeprom->tick = 0;
         eeprom->input = 0;
         PrintDebug("=== eeprom: begin access, enter command mode\n");
     }
 
-    if (!eecs)
-    {
+    if (eecs == 0) {
         PrintDebug("=== eeprom: end access\n");
         return;
     }
 
-    if (!old_eesk && eesk)
-    {
+    if (!old_eesk && eesk) {
         /* SK front rules */
         prom9346_shift_clock(eeprom);
     }
 }
 
-static void rtl8139_9346cr_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
 
+static inline void rtl8139_reset_rxbuf(struct rtl8139_state * nic_state, uint32_t bufsize) {
+    nic_state->rx_bufsize = bufsize;
+    nic_state->regs.capr = 0;
+    nic_state->regs.cbr = 0;
+}
+
+
+static void rtl8139_reset(struct rtl8139_state *nic_state) {
+    struct rtl8139_regs *regs = &(nic_state->regs);
+    int i;
+
+    PrintDebug("Rtl8139: Reset\n");
+
+    /* restore MAC address */
+    memcpy(regs->id, nic_state->mac, ETH_ALEN);
+    memset(regs->mult, 0xff, 8);
+
+    rtl8139_update_irq(nic_state);
+
+    // prepare eeprom
+    nic_state->eeprom.contents[0] = 0x8129;
+       
+    // PCI vendor and device ID
+    nic_state->eeprom.contents[1] = 0x10ec;
+    nic_state->eeprom.contents[2] = 0x8139;
+    //Mac address
+    nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
+    nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
+    nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
+
+    for (i = 0; i < 4; ++i) {
+        regs->tsd[i] = TSD_Own;
+    }
+
+    rtl8139_reset_rxbuf(nic_state, 1024*8);
+
+    /* ACK the reset */
+    regs->tcr = 0;
+
+    regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
+    regs->rerid = RTL8139_PCI_REVID_8139;
+
+    regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd 
+
+    regs->config[0] = 0x0 | (1 << 4); // No boot ROM 
+    regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
+    //regs->config[1] = 0x4; //Only IO mapped registers available
+    regs->config3[0] = 0x1; // fast back-to-back compatible
+    regs->config3[1] = 0x0;
+    regs->config5 = 0x0;
+       
+    regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
+
+    //0x3100 : 100Mbps, full duplex, autonegotiation.  0x2100 : 100Mbps, full duplex
+    regs->bmcr = 0x1000; // autonegotiation
+
+    regs->bmsr  = 0x7809;
+    regs->bmsr |= 0x0020; // autonegotiation completed
+    regs->bmsr |= 0x0004; // link is up
+
+    regs->anar = 0x05e1;     // all modes, full duplex
+    regs->anlpar = 0x05e1;   // all modes, full duplex
+    regs->aner = 0x0001;     // autonegotiation supported
+
+    // reset timer and disable timer interrupt
+    regs->tctr = 0;
+    regs->timer_int = 0;
+}
+
+
+
+static void rtl8139_9346cr_write(struct rtl8139_state * nic_state, uint32_t val) {
     val &= 0xff;
 
     PrintDebug("RTL8139: 9346CR write val=0x%02x\n", val);
         int eecs = (eeprom_val & 0x08)?1:0;
         int eesk = (eeprom_val & 0x04)?1:0;
         int eedi = (eeprom_val & 0x02)?1:0;
-        prom9346_set_wire(dev, eecs, eesk, eedi);
+        prom9346_set_wire(nic_state, eecs, eesk, eedi);
     } else if (opmode == 0x40) {
         /* Reset.  */
         val = 0;
-        rtl8139_reset(dev);
+        rtl8139_reset(nic_state);
     }
 
     nic_state->regs.cmd9346 = val;
 }
 
-static uint32_t rtl8139_9346cr_read(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static uint32_t rtl8139_9346cr_read(struct rtl8139_state * nic_state) {
     uint32_t ret = nic_state->regs.cmd9346;
     uint32_t opmode = ret & 0xc0;
 
-    if (opmode == 0x80)
-    {
+    if (opmode == 0x80) {
         /* eeprom access */
-        int eedo = prom9346_get_wire(dev);
-        if (eedo)
-        {
+        int eedo = prom9346_get_wire(nic_state);
+        if (eedo){
             ret |=  0x01;
-        }
-        else
-        {
+        } else {
             ret &= ~0x01;
         }
     }
     return ret;
 }
 
-#endif
-
-static int rtl8139_receiver_enabled(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
 
+static inline int rtl8139_receiver_enabled(struct rtl8139_state * nic_state) {
     return nic_state->regs.cmd & CMD_Re;
 }
 
-static int rtl8139_rxwrap(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static inline int rtl8139_rxwrap(struct rtl8139_state * nic_state) {
     // wrapping enabled; assume 1.5k more buffer space if size < 64K
     return (nic_state->regs.rcr & (1 << 7));
 }
 
-static void rtl8139_rxbuf_write(struct vm_device *dev, const void *buf, int size)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
+static void rtl8139_rxbuf_write(struct rtl8139_state * nic_state, 
+                               const void * buf, 
+                               int size) {
+    struct rtl8139_regs *regs = &(nic_state->regs);
     int wrap;
     addr_t guestpa, host_rxbuf;
 
     guestpa = (addr_t)regs->rbstart;
-    guest_pa_to_host_va(dev->vm, guestpa, &host_rxbuf);   
+    v3_gpa_to_hva(&(nic_state->vm->cores[0]), guestpa, &host_rxbuf);   
 
     //wrap to the front of rx buffer
-    if (regs->cbr + size > nic_state->rx_bufsize)
-    {
+    if (regs->cbr + size > nic_state->rx_bufsize){
         wrap = MOD2(regs->cbr + size, nic_state->rx_bufsize);
 
-        if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(dev)))
-        {
+        if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(nic_state))){
             PrintDebug("RTL8139: rx packet wrapped in buffer at %d\n", size-wrap);
 
-            if (size > wrap)
-            {
+            if (size > wrap){
                 memcpy((void *)(host_rxbuf + regs->cbr), buf, size-wrap);
             }
 
 #define POLYNOMIAL 0x04c11db6
 
 /* From FreeBSD */
-static int compute_mcast_idx(const uint8_t *ep)
-{
+static inline int compute_mcast_idx(const uint8_t *ep) {
     uint32_t crc;
     int carry, i, j;
     uint8_t b;
             carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
             crc <<= 1;
             b >>= 1;
-            if (carry)
+            if (carry){
                 crc = ((crc ^ POLYNOMIAL) | carry);
+           }
         }
     }
     return (crc >> 26);
 }
-static void vnic_receive(struct vm_device *dev, const uchar_t *pkt, uint_t length)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
-    struct nic_regs *regs = &(nic_state->regs);
+
+
+static int rx_one_pkt(struct rtl8139_state * nic_state, 
+                     uint8_t * pkt, 
+                     uint32_t len){
+    struct rtl8139_regs *regs = &(nic_state->regs);
     uint_t rxbufsize = nic_state->rx_bufsize;
     uint32_t header, val;
     uint8_t bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
     if (regs->rcr & AcceptAllPhys) {
-        PrintDebug("RTL8139: packet received in promiscuous mode\n");
+       PrintDebug("RTL8139: packet received in promiscuous mode\n");
     } else {
-        if (!memcmp(pkt,  bcast_addr, 6)) {
-            if (!(regs->rcr & AcceptBroadcast))
-            {
-                PrintDebug("RTL8139: broadcast packet rejected\n");
-                return;
-            }
-            header |= Rx_Broadcast;
-            PrintDebug("RTL8139: broadcast packet received\n");
-        } else if (pkt[0] & 0x01) {
+       if (!memcmp(pkt,  bcast_addr, 6)) {
+           if (!(regs->rcr & AcceptBroadcast)){
+               PrintDebug("RTL8139: broadcast packet rejected\n");
+               return -1;
+           }
+           header |= Rx_Broadcast;
+           PrintDebug("RTL8139: broadcast packet received\n");
+       } else if (pkt[0] & 0x01) {
             // multicast
-            if (!(regs->rcr & AcceptMulticast))
-            {
+            if (!(regs->rcr & AcceptMulticast)){
                 PrintDebug("RTL8139: multicast packet rejected\n");
-                return;
+                return -1;
             }
 
             int mcast_idx = compute_mcast_idx(pkt);
 
-            if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
-            {
+            if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))){
                 PrintDebug("RTL8139: multicast address mismatch\n");
-                return;
+                return -1;
             }
             header |= Rx_Multicast;
             PrintDebug("RTL8139: multicast packet received\n");
-        } else if (regs->id[0] == pkt[0] &&
-                   regs->id[1] == pkt[1] &&
-                   regs->id[2] == pkt[2] &&
-                   regs->id[3] == pkt[3] &&
-                   regs->id[4] == pkt[4] &&
-                   regs->id[5] == pkt[5]) {
-            if (!(regs->rcr & AcceptMyPhys))
-            {
+        } else if (!compare_ethaddr(regs->id, pkt)){
+            if (!(regs->rcr & AcceptMyPhys)){
                 PrintDebug("RTL8139: rejecting physical address matching packet\n");
-                return;
+                return -1;
             }
 
             header |= Rx_Physical;
             PrintDebug("RTL8139: physical address matching packet received\n");
         } else {
             PrintDebug("RTL8139: unknown packet\n");
-            return;
+            return -1;
         }
     }
 
     if(1){
-        PrintDebug("RTL8139: in ring Rx mode\n");
+       PrintDebug("RTL8139: in ring Rx mode\n");
 
-        int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
+       int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
 
-        if (avail != 0 && length + 8 >= avail)
-        {
+        if (avail != 0 && len + 8 >= avail){
             PrintError("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
-                   rxbufsize, regs->cbr, regs->capr, avail, length + 8);
+                   rxbufsize, regs->cbr, regs->capr, avail, len + 8);
 
             regs->isr |= ISR_Rxovw;
             ++ regs->mpc;
-            rtl8139_update_irq(dev);
-            return;
+            rtl8139_update_irq(nic_state);
+            return -1;
         }
 
-        header |= Rx_StatusOK;
-        header |= ((length << 16) & 0xffff0000);
+        header |= Rx_OK;
+        header |= ((len << 16) & 0xffff0000);
 
-        rtl8139_rxbuf_write(dev, (uint8_t *)&header, 4);
+        rtl8139_rxbuf_write(nic_state, (uint8_t *)&header, 4);
 
-        rtl8139_rxbuf_write(dev, pkt, length);
+        rtl8139_rxbuf_write(nic_state, pkt, len);
 
-        val = V3_Crc32(0, (char *)pkt, length);
+        /* CRC checksum */
+        val = v3_crc32(0, pkt, len);
 
-        rtl8139_rxbuf_write(dev, (uint8_t *)&val, 4);
+        rtl8139_rxbuf_write(nic_state, (uint8_t *)&val, 4);
 
         // correct buffer write pointer 
         regs->cbr = MOD2((regs->cbr + 3) & ~0x3, rxbufsize);
 
     regs->isr |= ISR_Rok;
 
-    nic_state->pkts_rcvd++;
+    nic_state->statistic.rx_pkts ++;
+    nic_state->statistic.rx_bytes += len;
        
-    rtl8139_update_irq(dev);   
+    rtl8139_update_irq(nic_state);   
+
+    return 0;
 }
 
-static int netif_input(uchar_t *pkt, uint_t size)
-{
-    PrintDebug("RTL8139: packet received!\n");
+static int rtl8139_rx(uint8_t * pkt, uint32_t len, void * private_data) {
+    struct rtl8139_state *nic_state = (struct rtl8139_state *)private_data;
 
-    if (!rtl8139_receiver_enabled(current_vnic)){
-               PrintDebug("RTL8139: receiver disabled\n");
-               return 0;
+    if (!rtl8139_receiver_enabled(nic_state)){
+       PrintDebug("RTL8139: receiver disabled\n");
+       nic_state->statistic.rx_dropped ++;
+               
+       return 0;
+    }
+       
+    if(rx_one_pkt(nic_state, pkt, len) >= 0){
+       nic_state->statistic.rx_pkts ++;
+       nic_state->statistic.rx_bytes += len;
+    }else {
+       nic_state->statistic.rx_dropped ++;
     }
-    vnic_receive(current_vnic, pkt, size);
 
     return 0;
 }
 
-static void rtl8139_reset_rxbuf(struct vm_device *dev, uint32_t bufsize)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
-       
-    nic_state->rx_bufsize = bufsize;
-    regs->capr  = 0;
-    regs->cbr = 0;
-}
-
-static void rtl8139_rcr_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static void rtl8139_rcr_write(struct rtl8139_state * nic_state, uint32_t val) {
     PrintDebug("RTL8139: RCR write val=0x%08x\n", val);
 
     val = SET_MASKED(val, 0xf0fc0040, nic_state->regs.rcr);
-
     nic_state->regs.rcr = val;
 
 #if 0
     uchar_t rblen = (regs->rcr >> 11) & 0x3;
-    switch(rblen)
-    {
+    switch(rblen) {
         case 0x0:
             rxbufsize = 1024 * 8 + 16;
             break;
 #endif
 
     // reset buffer size and read/write pointers
-    rtl8139_reset_rxbuf(dev, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
+    rtl8139_reset_rxbuf(nic_state, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
 
     PrintDebug("RTL8139: RCR write reset buffer size to %d\n", nic_state->rx_bufsize);
 }
 
-static void rtl8139_reset(struct rtl8139_state *nic_state)
-{
-    struct rtl8139_regs *regs = &(nic_state->regs);
-    int i;
-
-    PrintDebug("Rtl8139: Reset\n");
-
-    /* restore MAC address */
-    memcpy(regs->id, nic_state->mac, ETH_ALEN);
-    memset(regs->mult, 0xff, 8);
-
-    regs->isr = 0;
-    regs->imr = 0;
-
-    rtl8139_update_irq(nic_state);
-
-    // prepare eeprom
-    nic_state->eeprom.contents[0] = 0x8129;
-       
-    // PCI vendor and device ID
-    nic_state->eeprom.contents[1] = 0x10ec;
-    nic_state->eeprom.contents[2] = 0x8139;
-    //Mac address
-    nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
-    nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
-    nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
-
-    for (i = 0; i < 4; ++i)
-    {
-        regs->tsd[i] = TSD_Own;
-    }
-
-    regs->rbstart = 0;
-
-    rtl8139_reset_rxbuf(nic_state, 1024*8);
-
-    /* ACK the reset */
-    regs->tcr = 0;
-
-    regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
-    regs->rerid = RTL8139_PCI_REVID_8139;
-
-    regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd 
-
-    regs->config[0] = 0x0 | (1 << 4); // No boot ROM 
-    regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
-    //regs->config[1] = 0x4; //Only IO mapped registers available
-    regs->config3[0] = 0x1; // fast back-to-back compatible
-    regs->config3[1] = 0x0;
-    regs->config5 = 0x0;
-       
-    regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
-
-    //0x3100 : 100Mbps, full duplex, autonegotiation.  0x2100 : 100Mbps, full duplex
-    regs->bmcr = 0x1000; // autonegotiation
-
-    regs->bmsr  = 0x7809;
-    regs->bmsr |= 0x0020; // autonegotiation completed
-    regs->bmsr |= 0x0004; // link is up
-
-    regs->anar = 0x05e1;     // all modes, full duplex
-    regs->anlpar = 0x05e1;   // all modes, full duplex
-    regs->aner = 0x0001;     // autonegotiation supported
-
-    // reset timer and disable timer interrupt
-    regs->tctr = 0;
-    regs->timer_int = 0;
-
-    nic_state->pkts_rcvd = 0;
-}
-
-static void init_rtl8139_regs(struct rtl8139_state *nic_state)
-{
-    nic_state->regs.imr = 0x00;
-    nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
-    nic_state->pkts_rcvd = 0;
-
-    int i;
-    for(i = 0; i < 6; i++)
-        nic_state->regs.id[i] = nic_state->mac_addr[i] = mac[i];
-    for(i = 0; i < 8; i++)
-        nic_state->regs.mult[i] = 0xff;
-
-    nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
-    nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
-
-    rtl8139_reset(dev);
-}
-
 
 #if 0
 
 
 #endif
 
-static int rtl8139_transmitter_enabled(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static inline int transmitter_enabled(struct rtl8139_state * nic_state){
     return nic_state->regs.cmd & CMD_Te;
 }
 
-static bool rtl8139_rxbufempty(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
+static int rxbufempty(struct rtl8139_state * nic_state){
+    struct rtl8139_regs *regs = &(nic_state->regs);
     int unread;
 
     unread = MOD2(regs->cbr + nic_state->rx_bufsize - regs->capr, nic_state->rx_bufsize);
    
-    if (unread != 0)
-    {
+    if (unread != 0){
         PrintDebug("RTL8139: receiver buffer data available 0x%04x\n", unread);
-        return false;
+        return 0;
     }
 
     PrintDebug("RTL8139: receiver buffer is empty\n");
 
-    return true;
+    return 1;
 }
 
-static uint32_t rtl8139_cmd_read(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    uint32_t ret = nic_state->regs.cmd;
-
-    if (rtl8139_rxbufempty(dev))
-        ret |= CMD_Bufe;
-
-    PrintDebug("RTL8139: Cmd read val=0x%04x\n", ret);
-
-    return ret;
-}
-
-static void rtl8139_cmd_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static void rtl8139_cmd_write(struct rtl8139_state * nic_state, uint32_t val){
     val &= 0xff;
 
     PrintDebug("RTL8139: Cmd write val=0x%08x\n", val);
 
-    if (val & CMD_Rst)
-    {
+    if (val & CMD_Rst){
         PrintDebug("RTL8139: Cmd reset\n");
-        rtl8139_reset(dev);
+        rtl8139_reset(nic_state);
     }
-    if (val & CMD_Re)
-    {
+    if (val & CMD_Re){
         PrintDebug("RTL8139: Cmd enable receiver\n");
-
-        //s->currCPlusRxDesc = 0;
     }
-    if (val & CMD_Te)
-    {
+    if (val & CMD_Te){
         PrintDebug("RTL8139: Cmd enable transmitter\n");
-
-        //s->currCPlusTxDesc = 0;
     }
 
     val = SET_MASKED(val, 0xe3, nic_state->regs.cmd);
     nic_state->regs.cmd = val;
 }
 
-static int rtl8139_send_packet(struct vm_device *dev, int descriptor)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
+static int tx_one_packet(struct rtl8139_state * nic_state, int descriptor){
+    struct rtl8139_regs *regs = &(nic_state->regs);
     int txsize;
     uint8_t *pkt;
     addr_t pkt_gpa = 0, hostva = 0;
-    int i;
 
-    if (!rtl8139_transmitter_enabled(dev))
-    {
+    if (!transmitter_enabled(nic_state)){
         PrintError("RTL8139: fail to send from descriptor %d: transmitter disabled\n", descriptor);
         return 0;
     }
 
-    if (regs->tsd[descriptor] & TSD_Own)
-    {
+    if (regs->tsd[descriptor] & TSD_Own){
         PrintError("RTL8139: fail to send from descriptor %d: owned by host\n", descriptor);
         return 0;
     }
     pkt_gpa = (addr_t) regs->tsad[descriptor];
 
     PrintDebug("RTL8139: sending %d bytes from guest memory at 0x%08x\n", txsize, regs->tsad[descriptor]);
-
-    guest_pa_to_host_va(dev->vm, (addr_t)pkt_gpa, &hostva);
+       
+    v3_gpa_to_hva(&(nic_state->vm->cores[0]), (addr_t)pkt_gpa, &hostva);
     pkt = (uchar_t *)hostva;
 
-    for(i = 0; i < txsize; i++)
-    {
-        PrintDebug("%x ", pkt[i]);
-    }
-    PrintDebug("\n");
+#ifdef CONFIG_DEBUG_RTL8139
+    v3_hexdump(pkt, txsize, NULL, 0);
+#endif
 
-    if (TxLoopBack == (regs->tcr & TxLoopBack)){ //loopback test
+    if (TxLoopBack == (regs->tcr & TxLoopBack)){ /* loopback test */
         PrintDebug(("RTL8139: transmit loopback mode\n"));
-        vnic_receive(dev, pkt, txsize);
+        rx_one_pkt(nic_state, pkt, txsize);
     } else{       
-           if (V3_SEND_PKT(pkt, txsize) == 0){
-                PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
-           } else {
-               PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
-           }
+        if (nic_state->net_ops->send(pkt, txsize, nic_state->backend_data) == 0){
+           PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
+           nic_state->statistic.tx_pkts ++;
+           nic_state->statistic.tx_bytes += txsize;
+       } else {
+           PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
+           nic_state->statistic.tx_dropped ++;
+       }
     }
 
     regs->tsd[descriptor] |= TSD_Tok;
     regs->tsd[descriptor] |= TSD_Own;
 
     nic_state->regs.isr |= ISR_Tok;
-    rtl8139_update_irq(dev);
+    rtl8139_update_irq(nic_state);
 
     return 0;
 }
 
-//write to transmit status registers
-static void rtl8139_tsd_write(struct vm_device *dev, uint8_t descriptor, uint32_t val)
-{ 
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
-#if 0
-    if (rtl8139_transmitter_enabled(dev))
-    {
-        PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d\n", val, descriptor);
-
-        nic_state->regs.tsd[descriptor] = val;
-
+/*transmit status registers*/
+static void rtl8139_tsd_write(struct rtl8139_state * nic_state, 
+                             uint8_t descriptor, 
+                             uint32_t val){ 
+    if (!transmitter_enabled(nic_state)){
+        PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d, Transmitter not enabled\n", val, descriptor);
+               
         return;
     }
-#endif
 
     PrintDebug("RTL8139: TSD write val=0x%08x descriptor=%d\n", val, descriptor);
 
 
     nic_state->regs.tsd[descriptor] = val;
 
-    rtl8139_send_packet(dev, descriptor);
+    tx_one_packet(nic_state, descriptor);
 }
 
-//transmit status of all descriptors
-static uint16_t rtl8139_tsad_read(struct vm_device *dev)
-{
+/* transmit status of all descriptors */
+static uint16_t rtl8139_txsad_read(struct rtl8139_state * nic_state){
     uint16_t ret = 0;
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
+    struct rtl8139_regs *regs = &(nic_state->regs);
 
-    ret = ((regs->tsd[3] & TSD_Tok)?TSD_Tok:0)
+    ret = ((regs->tsd[3] & TSD_Tok)?TSAD_TOK3:0)
          |((regs->tsd[2] & TSD_Tok)?TSAD_TOK2:0)
          |((regs->tsd[1] & TSD_Tok)?TSAD_TOK1:0)
          |((regs->tsd[0] & TSD_Tok)?TSAD_TOK0:0)
          |((regs->tsd[1] & TSD_Own)?TSAD_OWN1:0)
          |((regs->tsd[0] & TSD_Own)?TSAD_OWN0:0) ;
 
-
-    PrintDebug("RTL8139: tsad read val=0x%04x\n", (int)ret);
+    PrintDebug("RTL8139: txsad read val=0x%04x\n", (int)ret);
 
     return ret;
 }
 
-//interrupt mask register
-static void rtl8139_imr_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-       
-    PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
-
-    /* mask unwriteable bits */
-    val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
-
-    nic_state->regs.imr = val;
-
-    rtl8139_update_irq(dev);
-}
-
-static void rtl8139_isr_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    struct nic_regs *regs = &(nic_state->regs);
+static inline void rtl8139_isr_write(struct rtl8139_state * nic_state, uint32_t val) {
+    struct rtl8139_regs *regs = &(nic_state->regs);
 
     PrintDebug("RTL8139: ISR write val=0x%04x\n", val);
 
-#if 0
-
-    // writing to ISR has no effect
-
-    return;
-
-#else
     uint16_t newisr = regs->isr & ~val;
 
     /* mask unwriteable bits */
 
     /* writing 1 to interrupt status register bit clears it */
     regs->isr = 0;
-    rtl8139_update_irq(dev);
+    rtl8139_update_irq(nic_state);
 
     regs->isr = newisr;
-    rtl8139_update_irq(dev);
-#endif
-}
-
-static uint32_t rtl8139_isr_read(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-    uint32_t ret = (uint32_t)nic_state->regs.isr;
-
-    PrintDebug("RTL8139: ISR read val=0x%04x\n", ret);
-
-#if 0
-    // reading ISR clears all interrupts
-    nic_state->regs.isr = 0;
-
-    rtl8139_update_irq(dev);
-
-#endif
-
-    return ret;
-}
-
-static void rtl8139_capr_write(struct vm_device *dev, uint32_t val)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
-    PrintDebug("RTL8139: CAPR write val=0x%04x\n", val);
-
-    // this value is off by 16
-    nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
-
-    PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
-           nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);
-}
-
-static uint32_t rtl8139_capr_read(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
-    /* this value is off by 16 */
-    uint32_t ret = nic_state->regs.capr - 0x10;
-
-    PrintDebug("RTL8139: CAPR read val=0x%04x\n", ret);
-
-    return ret;
-}
-
-typedef enum {read, write} opr_t; 
-static bool need_hook(int port, opr_t op)
-{
-       if (op == read){ 
-               switch (port) {
-                       case RTL8139_IMR:
-                       case RTL8139_ISR:
-                               return true;
-                       default:
-                               break;
-               }
-       }
-       if (op == write){
-               switch (port) {
-                       case RTL8139_TSD0:
-                       case RTL8139_TSD1:
-                       case RTL8139_TSD2:
-                       case RTL8139_TSD3:
-                       case RTL8139_CR:
-                       case RTL8139_IMR:
-                       case RTL8139_ISR:
-                       case RTL8139_TCR:
-                       case RTL8139_RCR:
-                       case RTL8139_CSCR:
-                       case RTL8139_Config5:
-                               return true;
-                       default:
-                               break;
-               }
-       }
-       
-       return false;
+    rtl8139_update_irq(nic_state);
 }
 
-static int rtl8139_mmio_write(addr_t guest_addr, void * src, uint_t length, void * priv_data)
-{
-    int port;
+static int rtl8139_mmio_write(struct guest_info * core, 
+                             addr_t guest_addr, 
+                             void * src,
+                             uint_t length, 
+                             void * priv_data) {
+    int idx;
     uint32_t val;
-    struct vm_device *dev = (struct vm_device *)priv_data;
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
+    struct rtl8139_state *nic_state = (struct rtl8139_state *)(priv_data);
 
-    port = guest_addr & 0xff;
+    idx = guest_addr & 0xff;
 
     memcpy(&val, src, length);
 
     PrintDebug("rtl8139 mmio write: addr:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
        
-    switch(port) {
-           case RTL8139_IDR0:
-               nic_state->regs.id[0] = val & 0xff;
-               break;
-           case RTL8139_IDR1:
-               nic_state->regs.id[1] = val & 0xff;
-               break;
-           case RTL8139_IDR2:
-               nic_state->regs.id[2] = val & 0xff;
-               break;
-           case RTL8139_IDR3:
-               nic_state->regs.id[3] = val & 0xff;
-               break;
-           case RTL8139_IDR4:
-               nic_state->regs.id[4] = val & 0xff;
-               break;
-           case RTL8139_IDR5:
-               nic_state->regs.id[5] = val & 0xff;
-               break;
-           case RTL8139_MAR0:
-               nic_state->regs.mult[0] = val & 0xff;
-               break;
-           case RTL8139_MAR1:
-               nic_state->regs.mult[1] = val & 0xff;
-               break;
-           case RTL8139_MAR2:
-               nic_state->regs.mult[2] = val & 0xff;
-               break;
-           case RTL8139_MAR3:
-               nic_state->regs.mult[3] = val & 0xff;
-               break;
-           case RTL8139_MAR4:
-               nic_state->regs.mult[4] = val & 0xff;
-               break;
-           case RTL8139_MAR5:
-               nic_state->regs.mult[5] = val & 0xff;
-               break;
-           case RTL8139_MAR6:
-               nic_state->regs.mult[6] = val & 0xff;
-               break;
-           case RTL8139_MAR7:
-               nic_state->regs.mult[7] = val & 0xff;
-               break;
-           case RTL8139_TSD0:
-           case RTL8139_TSD1:
-           case RTL8139_TSD2:
-           case RTL8139_TSD3:
-               rtl8139_tsd_write(dev, (port - RTL8139_TSD0)/4, val);
-               break;
-           case RTL8139_TSAD0:
-           case RTL8139_TSAD1:
-           case RTL8139_TSAD2:
-           case RTL8139_TSAD3:
-               nic_state->regs.tsad[(port - RTL8139_TSAD0)/4] = val;
-               break;
-           case RTL8139_RBSTART:
-               nic_state->regs.rbstart = val;
-               break;
-           case RTL8139_ERBCR:
-               nic_state->regs.erbcr = val & 0xffff;
-               break;
-           case RTL8139_ERSR:
-               //nic_state->regs.ersr = val & 0xff;
-               nic_state->regs.ersr &= (~val) & 0x0c;
-               break;
-           case RTL8139_CR:
-                 rtl8139_cmd_write(dev, val);
-               break;
-           case RTL8139_CAPR:
-               rtl8139_capr_write(dev, val & 0xffff);
-               break;
-           case RTL8139_CBR: //this is read only =====
-               //nic_state->regs.cbr = val & 0xffff;
-               break;
-           case RTL8139_IMR:
-                 rtl8139_imr_write(dev, val);
-               break;
-           case RTL8139_ISR:
-               rtl8139_isr_write(dev, val);
-               break;
-           case RTL8139_TCR:
-               nic_state->regs.tcr = val;
-               break;
-           case RTL8139_RCR:
-               rtl8139_rcr_write(dev, val);
-                break;
-           case RTL8139_TCTR:
-               nic_state->regs.tctr = 0; //write clear current tick
-               break;
-           case RTL8139_MPC:
-               nic_state->regs.mpc = 0; //clear on write
-               break;
-           case RTL8139_9346CR:
-                 rtl8139_9346cr_write(dev, val);
-               break;
-           case RTL8139_CONFIG0:
-               nic_state->regs.config[0] = val & 0xff;
-               break;
-           case RTL8139_CONFIG1:
-               nic_state->regs.config[1] = val & 0xff;
-               break;
-           case RTL8139_TimerInt:
-               nic_state->regs.timer_int = val;
-               break;
-           case RTL8139_MSR:
-               nic_state->regs.msr = val & 0xff;
-               break;
-           case RTL8139_CONFIG3:
-               nic_state->regs.config3[0] = val & 0xff;
-               break;
-           case RTL8139_CONFIG4:
-               nic_state->regs.config3[1] = val & 0xff;
-               break;
-           case RTL8139_MULINT:
-               nic_state->regs.mulint = val & 0xffff;
-               break;
-           case RTL8139_RERID:
-               nic_state->regs.rerid = val & 0xffff;
-               break;
-           case RTL8139_TSAD:
-               nic_state->regs.txsad = val & 0xffff;
-               break;
-           case RTL8139_BMCR:
-               nic_state->regs.bmcr = val & 0xffff;
-               break;
-           case RTL8139_BMSR:
-               nic_state->regs.bmsr = val & 0xffff;
-               break;
-           case RTL8139_ANAR:
-               nic_state->regs.anar = val & 0xffff;
-               break;
-           case RTL8139_ANLPAR:
-               nic_state->regs.anlpar = val & 0xffff;
-               break;
-           case RTL8139_ANER:
-               nic_state->regs.aner = val & 0xffff;
-               break;
-           case RTL8139_DIS:
-               nic_state->regs.dis = val & 0xffff;
-               break;
-           case RTL8139_FCSC:
-               nic_state->regs.fcsc = val & 0xffff;
-               break;
-           case RTL8139_NWAYTR:
-               nic_state->regs.nwaytr = val & 0xffff;
-               break;
-           case RTL8139_REC:
-               nic_state->regs.rec = val & 0xffff;
-               break;
-           case RTL8139_CSCR:
-               nic_state->regs.cscr = val;
-               break;
-           case RTL8139_PHY1_PARM:
-               nic_state->regs.phy1_parm = val;
-               break;
-           case RTL8139_TW_PARM:
-               nic_state->regs.tw_parm = val & 0xffff;
-               break;
-           case RTL8139_PHY2_PARM:
-               nic_state->regs.phy2_parm = val;
-               break;
-           case RTL8139_CRC0:
-               nic_state->regs.crc[0] = val & 0xff;
-               break;
-           case RTL8139_CRC1:
-               nic_state->regs.crc[1] = val & 0xff;
-               break;
-           case RTL8139_CRC2:
-               nic_state->regs.crc[2] = val & 0xff;
-               break;
-           case RTL8139_CRC3:
-               nic_state->regs.crc[3] = val & 0xff;
-               break;
-           case RTL8139_CRC4:
-               nic_state->regs.crc[4] = val & 0xff;
-               break;
-           case RTL8139_CRC5:
-               nic_state->regs.crc[5] = val & 0xff;
-               break;
-           case RTL8139_CRC6:
-               nic_state->regs.crc[6] = val & 0xff;
-               break;
-           case RTL8139_CRC7:
-               nic_state->regs.crc[7] = val & 0xff;
-               break;
-           case RTL8139_Config5:
-               nic_state->regs.config5 = val & 0xff;
-               break;
-           default:
-               PrintDebug("rtl8139 write error: invalid port: 0x%x\n", port);
+    switch(idx) {
+       case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
+           nic_state->regs.id[idx - RTL8139_IDR0] = val & 0xff;
+           break;
+
+       case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
+           nic_state->regs.mult[idx - RTL8139_MAR0] = val & 0xff;
+           break;
+
+       case RTL8139_TSD0:
+       case RTL8139_TSD1:
+       case RTL8139_TSD2:
+       case RTL8139_TSD3:
+           rtl8139_tsd_write(nic_state, (idx - RTL8139_TSD0)/4, val);
+           break;
+               
+       case RTL8139_TSAD0:
+       case RTL8139_TSAD1:
+       case RTL8139_TSAD2:
+       case RTL8139_TSAD3:
+           nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4] = val;
+           break;
+               
+       case RTL8139_RBSTART:
+           nic_state->regs.rbstart = val;
+           break;
+       case RTL8139_ERBCR:
+           nic_state->regs.erbcr = val & 0xffff;
+           break;
+       case RTL8139_ERSR:
+           //nic_state->regs.ersr = val & 0xff;
+           nic_state->regs.ersr &= (~val) & 0x0c;
+           break;
+       case RTL8139_CR:
+           rtl8139_cmd_write(nic_state, val);
+           break;
+       case RTL8139_CAPR:
+       {
+           val &= 0xffff;
+           /* this value is off by 16 */
+           nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
+
+           PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
+           nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);  
+       }
+           break;
+       case RTL8139_CBR: /* read only */
+           //nic_state->regs.cbr = val & 0xffff;
+           break;
+       case RTL8139_IMR:
+       {
+           PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
+
+           /* mask unwriteable bits */
+           val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
+           nic_state->regs.imr = val;
+           rtl8139_update_irq(nic_state);
+       }
+           break;
+       case RTL8139_ISR:
+           rtl8139_isr_write(nic_state, val);
+           break;
+       case RTL8139_TCR:
+           nic_state->regs.tcr = val;
+           break;
+       case RTL8139_RCR:
+           rtl8139_rcr_write(nic_state, val);
+           break;
+       case RTL8139_TCTR:
+           nic_state->regs.tctr = 0; /* write clear current tick */
+           break;
+       case RTL8139_MPC:
+           nic_state->regs.mpc = 0; /* clear on write */
+           break;
+       case RTL8139_9346CR:
+           rtl8139_9346cr_write(nic_state, val);
+           break;
+       case RTL8139_CONFIG0:
+           nic_state->regs.config[0] = val & 0xff;
+           break;
+       case RTL8139_CONFIG1:
+           nic_state->regs.config[1] = val & 0xff;
+           break;
+       case RTL8139_TimerInt:
+           nic_state->regs.timer_int = val;
+           break;
+       case RTL8139_MSR:
+           nic_state->regs.msr = val & 0xff;
+           break;
+       case RTL8139_CONFIG3:
+           nic_state->regs.config3[0] = val & 0xff;
+           break;
+       case RTL8139_CONFIG4:
+           nic_state->regs.config3[1] = val & 0xff;
+           break;
+               
+       case RTL8139_MULINT:
+           nic_state->regs.mulint = val & 0xffff;
+           break;
+       case RTL8139_RERID:
+           nic_state->regs.rerid = val & 0xffff;
+           break;
+       case RTL8139_TXSAD:
+           nic_state->regs.txsad = val & 0xffff;
+           break;
+       case RTL8139_BMCR:
+           nic_state->regs.bmcr = val & 0xffff;
+           break;
+       case RTL8139_BMSR:
+           nic_state->regs.bmsr = val & 0xffff;
+           break;
+       case RTL8139_ANAR:
+           nic_state->regs.anar = val & 0xffff;
+           break;
+       case RTL8139_ANLPAR:
+           nic_state->regs.anlpar = val & 0xffff;
+           break;
+       case RTL8139_ANER:
+           nic_state->regs.aner = val & 0xffff;
+           break;
+       case RTL8139_DIS:
+           nic_state->regs.dis = val & 0xffff;
+           break;
+       case RTL8139_FCSC:
+           nic_state->regs.fcsc = val & 0xffff;
+           break;
+       case RTL8139_NWAYTR:
+           nic_state->regs.nwaytr = val & 0xffff;
+           break;
+       case RTL8139_REC:
+           nic_state->regs.rec = val & 0xffff;
+           break;
+
+       case RTL8139_CSCR:
+           nic_state->regs.cscr = val;
+           break;
+       case RTL8139_PHY1_PARM:
+           nic_state->regs.phy1_parm = val;
+           break;
+       case RTL8139_TW_PARM:
+           nic_state->regs.tw_parm = val & 0xffff;
+           break;
+       case RTL8139_PHY2_PARM:
+           nic_state->regs.phy2_parm = val;
+           break;
+       case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
+           nic_state->regs.crc[idx - RTL8139_CRC0] = val & 0xff;
+           break;
+
+       case RTL8139_Config5:
+           nic_state->regs.config5 = val & 0xff;
+           break;
+       default:
+           PrintDebug("rtl8139 write error: invalid port: 0x%x\n", idx);
        }
-
-       
-#if TEST_PERFORMANCE
-    if (need_hook(port, read))
-               io_hooked ++;
-    if (( ++io_total) % 50 == 0)
-        PrintError("RTL8139: Total IO: %d, Hooked: %d, INT: %d\n", io_total, io_hooked, int_total);
-#endif
         
     return length;
 }
 
-static int rtl8139_mmio_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data)
-{
-    ulong_t port;
+static int rtl8139_mmio_read(struct guest_info * core, 
+                            addr_t guest_addr, 
+                            void * dst, 
+                            uint_t length, 
+                            void * priv_data) {
+    uint16_t idx;
     uint32_t val;
-    struct vm_device *dev = (struct vm_device *)priv_data;
-    struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
-    port = guest_addr & 0xff;
-
-    switch(port) {
-           case RTL8139_IDR0:
-               val = nic_state->regs.id[0];
-               break;
-           case RTL8139_IDR1:
-               val = nic_state->regs.id[1];
-               break;
-           case RTL8139_IDR2:
-               val = nic_state->regs.id[2];
-               break;
-           case RTL8139_IDR3:
-               val = nic_state->regs.id[3];
-               break;
-           case RTL8139_IDR4:
-               val = nic_state->regs.id[4];
-               break;
-           case RTL8139_IDR5:
-               val = nic_state->regs.id[5];
-               break;
-           case RTL8139_MAR0:
-               val = nic_state->regs.mult[0];
-               break;
-           case RTL8139_MAR1:
-               val = nic_state->regs.mult[1];
-               break;
-           case RTL8139_MAR2:
-               val = nic_state->regs.mult[2];
-               break;
-           case RTL8139_MAR3:
-               val = nic_state->regs.mult[3];
-               break;
-           case RTL8139_MAR4:
-               val = nic_state->regs.mult[4];
-               break;
-           case RTL8139_MAR5:
-               val = nic_state->regs.mult[5];
-               break;
-           case RTL8139_MAR6:
-               val = nic_state->regs.mult[6];
-               break;
-           case RTL8139_MAR7:
-               val = nic_state->regs.mult[7];
-               break;
-           case RTL8139_TSD0:
-               val = nic_state->regs.tsd[0];
-               break;
-           case RTL8139_TSD1:
-               val = nic_state->regs.tsd[1];
-               break;
-           case RTL8139_TSD2:
-               val = nic_state->regs.tsd[2];
-               break;
-           case RTL8139_TSD3:
-               val = nic_state->regs.tsd[3];
-               break;
-           case RTL8139_TSAD0:
-               val = nic_state->regs.tsad[0];
-               break;
-           case RTL8139_TSAD1:
-               val = nic_state->regs.tsad[1];
-               break;
-           case RTL8139_TSAD2:
-               val = nic_state->regs.tsad[2];
-               break;
-           case RTL8139_TSAD3:
-               val = nic_state->regs.tsad[3];
-               break;
-           case RTL8139_RBSTART:
-               val = nic_state->regs.rbstart;
-               break;
-           case RTL8139_ERBCR:
-               val = nic_state->regs.erbcr;
-               break;
-           case RTL8139_ERSR:
-               val = nic_state->regs.ersr;
-               break;
-           case RTL8139_CR:
-               val = rtl8139_cmd_read(dev);
-               break;
-           case RTL8139_CAPR:
-               val = rtl8139_capr_read(dev);
-               break;
-           case RTL8139_CBR:
-               val = nic_state->regs.cbr;
-               break;
-           case RTL8139_IMR:
-               val = nic_state->regs.imr;
-               break;
-           case RTL8139_ISR:
-               val = rtl8139_isr_read(dev);
-               break;
-           case RTL8139_TCR:
-               val = nic_state->regs.tcr;
-               break;
-           case RTL8139_RCR:
-               val = nic_state->regs.rcr;
-               break;
-           case RTL8139_TCTR:
-               val = nic_state->regs.tctr;
-               break;
-           case RTL8139_MPC:
-               val = nic_state->regs.mpc;
-               break;
-           case RTL8139_9346CR:
-               val = rtl8139_9346cr_read(dev);
-               break;
-           case RTL8139_CONFIG0:
-               val = nic_state->regs.config[0];
-               break;
-           case RTL8139_CONFIG1:
-               val = nic_state->regs.config[1];
-               break;
-           case RTL8139_TimerInt:
-               val = nic_state->regs.timer_int;
-               break;
-           case RTL8139_MSR:
-               val = nic_state->regs.msr;
-               break;
-           case RTL8139_CONFIG3:
-               val = nic_state->regs.config3[0];
-               break;
-           case RTL8139_CONFIG4:
-               val = nic_state->regs.config3[1];
-               break;
-           case RTL8139_MULINT:
-               val = nic_state->regs.mulint;
-               break;
-           case RTL8139_RERID:
-               val = nic_state->regs.rerid;
-               break;
-           case RTL8139_TSAD: 
-               val = rtl8139_tsad_read(dev);
-               break;
-           case RTL8139_BMCR:
-               val = nic_state->regs.bmcr;
-               break;
-           case RTL8139_BMSR:
-               val = nic_state->regs.bmsr;
-               break;
-           case RTL8139_ANAR:
-               val = nic_state->regs.anar;
-               break;
-           case RTL8139_ANLPAR:
-               val = nic_state->regs.anlpar;
-               break;
-           case RTL8139_ANER:
-               val = nic_state->regs.aner;
-               break;
-           case RTL8139_DIS:
-               val = nic_state->regs.dis;
-               break;
-           case RTL8139_FCSC:
-               val = nic_state->regs.fcsc;
-               break;
-           case RTL8139_NWAYTR:
-               val = nic_state->regs.nwaytr;
-               break;
-           case RTL8139_REC:
-               val = nic_state->regs.rec;
-               break;
-           case RTL8139_CSCR:
-               val = nic_state->regs.cscr;
-               break;
-           case RTL8139_PHY1_PARM:
-               val = nic_state->regs.phy1_parm;
-               break;
-           case RTL8139_TW_PARM:
-               val = nic_state->regs.tw_parm;
-               break;
-           case RTL8139_PHY2_PARM:
-               val = nic_state->regs.phy2_parm;
-               break;
-           case RTL8139_CRC0:
-               val = nic_state->regs.crc[0];
-               break;
-           case RTL8139_CRC1:
-               val = nic_state->regs.crc[1];
-               break;
-           case RTL8139_CRC2:
-               val = nic_state->regs.crc[2];
-               break;
-           case RTL8139_CRC3:
-               val = nic_state->regs.crc[3];
-               break;
-           case RTL8139_CRC4:
-               val = nic_state->regs.crc[4];
-               break;
-           case RTL8139_CRC5:
-               val = nic_state->regs.crc[5];
-               break;
-           case RTL8139_CRC6:
-               val = nic_state->regs.crc[6];
-               break;
-           case RTL8139_CRC7:
-               val = nic_state->regs.crc[7];
-               break;
-           case RTL8139_Config5:
-               val = nic_state->regs.config5;
-               break;
-           default:
-                val = 0x0;
-                break;
+    struct rtl8139_state *nic_state = (struct rtl8139_state *)priv_data;
+
+    idx = guest_addr & 0xff;
+
+    switch(idx) {
+       case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
+           val = nic_state->regs.id[idx - RTL8139_IDR0];
+           break;
+               
+       case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
+           val = nic_state->regs.mult[idx - RTL8139_MAR0];
+           break;
+
+       case RTL8139_TSD0:
+       case RTL8139_TSD1:
+       case RTL8139_TSD2:
+       case RTL8139_TSD3:
+           val = nic_state->regs.tsd[(idx - RTL8139_TSD0)/4];
+           break;
+
+       case RTL8139_TSAD0:
+       case RTL8139_TSAD1:
+       case RTL8139_TSAD2:
+       case RTL8139_TSAD3:
+           val = nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4];
+           break;
+
+       case RTL8139_RBSTART:
+           val = nic_state->regs.rbstart;
+           break;
+       case RTL8139_ERBCR:
+           val = nic_state->regs.erbcr;
+           break;
+       case RTL8139_ERSR:
+           val = nic_state->regs.ersr;
+           break;
+       case RTL8139_CR:
+       {
+           val = nic_state->regs.cmd;
+           if (rxbufempty(nic_state)){
+               val |= CMD_Bufe;
+           }
+       }
+           break;
+       case RTL8139_CAPR:
+           /* this value is off by 16 -- don't know why - Lei*/
+           val = nic_state->regs.capr - 0x10;
+           break;
+       case RTL8139_CBR:
+           val = nic_state->regs.cbr;
+           break;
+       case RTL8139_IMR:
+           val = nic_state->regs.imr;
+           break;
+       case RTL8139_ISR:
+           val = (uint32_t)nic_state->regs.isr;
+           break;
+       case RTL8139_TCR:
+           val = nic_state->regs.tcr;
+           break;
+       case RTL8139_RCR:
+           val = nic_state->regs.rcr;
+           break;
+       case RTL8139_TCTR:
+           val = nic_state->regs.tctr;
+           break;
+       case RTL8139_MPC:
+           val = nic_state->regs.mpc;
+           break;
+       case RTL8139_9346CR:
+           val = rtl8139_9346cr_read(nic_state);
+           break;
+       case RTL8139_CONFIG0:
+           val = nic_state->regs.config[0];
+           break;
+       case RTL8139_CONFIG1:
+           val = nic_state->regs.config[1];
+           break;
+       case RTL8139_TimerInt:
+           val = nic_state->regs.timer_int;
+           break;
+       case RTL8139_MSR:
+           val = nic_state->regs.msr;
+           break;
+       case RTL8139_CONFIG3:
+           val = nic_state->regs.config3[0];
+           break;
+       case RTL8139_CONFIG4:
+           val = nic_state->regs.config3[1];
+           break;
+       case RTL8139_MULINT:
+           val = nic_state->regs.mulint;
+           break;
+       case RTL8139_RERID:
+           val = nic_state->regs.rerid;
+           break;
+       case RTL8139_TXSAD: 
+           val = rtl8139_txsad_read(nic_state);
+           break;
+       case RTL8139_BMCR:
+           val = nic_state->regs.bmcr;
+           break;
+       case RTL8139_BMSR:
+           val = nic_state->regs.bmsr;
+           break;
+       case RTL8139_ANAR:
+           val = nic_state->regs.anar;
+           break;
+       case RTL8139_ANLPAR:
+           val = nic_state->regs.anlpar;
+           break;
+       case RTL8139_ANER:
+           val = nic_state->regs.aner;
+           break;
+       case RTL8139_DIS:
+           val = nic_state->regs.dis;
+           break;
+       case RTL8139_FCSC:
+           val = nic_state->regs.fcsc;
+           break;
+       case RTL8139_NWAYTR:
+           val = nic_state->regs.nwaytr;
+           break;
+       case RTL8139_REC:
+           val = nic_state->regs.rec;
+           break;
+       case RTL8139_CSCR:
+           val = nic_state->regs.cscr;
+           break;
+       case RTL8139_PHY1_PARM:
+           val = nic_state->regs.phy1_parm;
+           break;
+       case RTL8139_TW_PARM:
+           val = nic_state->regs.tw_parm;
+           break;
+       case RTL8139_PHY2_PARM:
+           val = nic_state->regs.phy2_parm;
+           break;
+       case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
+           val = nic_state->regs.crc[idx - RTL8139_CRC0];
+           break;
+       case RTL8139_Config5:
+           val = nic_state->regs.config5;
+           break;
+       default:
+           val = 0x0;
+           break;
     }
 
     memcpy(dst, &val, length);
        
     PrintDebug("rtl8139 mmio read: port:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
 
-#if TEST_PERFORMANCE
-    if (need_hook(port, read))
-               io_hooked ++;
-    if (( ++io_total) % 50 == 0)
-        PrintError("RTL8139: Total IO: %d, Hooked: %d, INT: %d\n", io_total, io_hooked, int_total);
-#endif
-
     return length;
 }
 
 
-static int rtl8139_ioport_write(struct guest_info * core, uint16_t port, void *src, uint_t length, void * private_data)
-{
-    PrintDebug("rtl8139 pio write: port:0x%x (%u bytes)\n", port, length);
-       
-    rtl8139_mmio_write((addr_t)port, src, length, private_data);
-       
-    return length;
+static int rtl8139_ioport_write(struct guest_info * core,
+                               uint16_t port, 
+                               void *src, 
+                               uint_t length, 
+                               void * private_data) {
+    return rtl8139_mmio_write(core, (addr_t)port, 
+                             src, length, private_data);
 }
 
-static int rtl8139_ioport_read(uint16_t port, void *dst, uint_t length, struct vm_device *dev)
-{
-    PrintDebug("rtl8139 pio read: port:0x%x (%u bytes)\n", port, length);
-
-    rtl8139_mmio_read((addr_t)port, dst, length, (void *)dev);
-    
-    return length;
+static int rtl8139_ioport_read(struct guest_info * core, 
+                              uint16_t port, 
+                              void *dst, 
+                              uint_t length, 
+                              void * private_data) {
+    return rtl8139_mmio_read(core, (addr_t)port, 
+                            dst, length, private_data);
 }
 
-static int rtl8139_reset_device(struct vm_device *dev)
-{
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
-    struct nic_regs *regs = &(nic_state->regs);
-    regs->cmd |= CMD_Rst;
-    init_rtl8139(dev);
-    regs->cmd &= ~CMD_Rst;
+
+static int rtl8139_init_state(struct rtl8139_state *nic_state) {
+    PrintDebug("rtl8139: init_state\n");
+       
+    nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
+
+    nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
+    nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
+
+    rtl8139_reset(nic_state);
+
     return 0;
 }
 
-static int rtl8139_start_device(struct vm_device *dev)
-{
-    PrintDebug("rtl8139: start device\n");
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
-    struct nic_regs *regs = &(nic_state->regs);
-    regs->cmd |= CMD_Re | CMD_Te;
+
+#if 0
+static inline int rtl8139_reset_device(struct rtl8139_state * nic_state) {
+    nic_state->regs.cmd |= CMD_Rst;
+    rtl8139_init_state(nic_state);
+    nic_state->regs.cmd &= ~CMD_Rst;
+       
     return 0;
 }
 
-static int rtl8139_stop_device(struct vm_device *dev)
-{
-    PrintDebug("rtl8139: stop device\n");
-    struct nic_context *nic_state = (struct nic_context *)dev->private_data;
-    struct nic_regs *regs = &(nic_state->regs);
-    regs->cmd &= ~(CMD_Re | CMD_Te);
+static inline int rtl8139_start_device(struct rtl8139_state * nic_state) {
+    nic_state->regs.cmd |= CMD_Re | CMD_Te;
+       
     return 0;
 }
 
-static void init_phy_network()
-{
-    V3_REGISTER_PKT_DELIVERY(&netif_input);
+static int rtl8139_stop_device(struct rtl8139_state * nic_state) {
+    PrintDebug("rtl8139: stop device\n");
+
+    nic_state->regs.cmd &= ~(CMD_Re | CMD_Te);
+       
+    return 0;
 }
 
-static int rtl8139_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data)
-{
+static int rtl8139_hook_iospace(struct rtl8139_state * nic_state, 
+                               addr_t base_addr, 
+                               int size, 
+                               int type, 
+                               void *data) {
     int i;
 
-    if (base_addr <= 0)
-    {
+    if (base_addr <= 0){
        PrintError("In RTL8139: Fail to Hook IO Space, base address 0x%x\n", (int) base_addr);
        return -1;
     }
 
-    if (type == PCI_ADDRESS_SPACE_IO){
+    if (type == PCI_BAR_IO){
        PrintDebug("In RTL8139: Hook IO ports starting from %x, size %d\n", (int) base_addr, size);
 
-       for (i = 0; i < 0xff; i++)
-       {       
-           v3_dev_hook_io(vmdev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
+       for (i = 0; i < 0xff; i++){     
+           v3_dev_hook_io(nic_state->dev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
        }
-    } else if (type == PCI_ADDRESS_SPACE_MEM) {
+    } else if (type == PCI_BAR_MEM32) {
        PrintDebug("In RTL8139: Hook memory space starting from %x, size %d\n", (int) base_addr, size);
        
        //hook memory mapped I/O        
-       v3_hook_full_mem(vmdev->vm, base_addr, base_addr + 0xff,
-                                     &rtl8139_mmio_read, &rtl8139_mmio_write, vmdev);
+       v3_hook_full_mem(nic_state->vm, nic_state->vm->cores[0].cpu_id, base_addr, base_addr + 0xff,
+                                     &rtl8139_mmio_read, &rtl8139_mmio_write, nic_state);
     } else {
        PrintError("In RTL8139: unknown memory type: start %x, size %d\n", (int) base_addr, size);
     }
        
     return 0;
 }
+#endif
 
-static int rtl8139_unhook_iospace()
-{
-
-    return 0;
-}
-
-
-static struct pci_device * rtl8139_pci_init(struct vm_device *vmdev, struct pci_bus *bus, int devfn)
-{
-    uchar_t *pci_conf;
-    struct pci_device *pdev;
+static int register_dev(struct rtl8139_state * nic_state)  {
+    int i;
 
-    pdev = v3_pci_register_device(vmdev, bus, "REALTEK8139", devfn, NULL, NULL);
+    if (nic_state->pci_bus == NULL) {
+       PrintError("RTL8139: Not attached to any PCI bus\n");
 
-    if (pdev == NULL)
-    {
-        PrintError("NIC: Register to PCI bus failed\n");
-        return NULL;
+       return -1;
     }
 
-    pci_conf = pdev->configs;
-       
-    pci_conf[0x00] = 0xec;
-    pci_conf[0x01] = 0x10;
-    pci_conf[0x02] = 0x39;
-    pci_conf[0x03] = 0x81;
-    pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
-    pci_conf[0x08] = RTL8139_PCI_REVID_8139; /* PCI revision ID; >=0x20 is for 8139C+ */
-    pci_conf[0x0a] = 0x00; // ethernet network controller
-    pci_conf[0x0b] = 0x02;
-    pci_conf[0x0e] = 0x00; // header_type
-    pci_conf[0x3d] = 1; // interrupt pin 0
-    pci_conf[0x3c] = 12;
-    pci_conf[0x34] = 0xdc;
-
-    pdev->vmdev = vmdev;
-       
-    v3_pci_register_io_region(pdev, 0, 0x100, PCI_ADDRESS_SPACE_IO, &rtl8139_hook_iospace);
-    v3_pci_register_io_region(pdev, 1, 0x100, PCI_ADDRESS_SPACE_MEM, &rtl8139_hook_iospace);
-    
-    return pdev;
-}
+    struct v3_pci_bar bars[6];
+    struct pci_device * pci_dev = NULL;
 
-static int rtl8139_init_state(struct rtl8139_state *nic_state)
-{
-    PrintDebug("rtl8139: init_state\n");
-       
-    init_phy_network();
-    init_rtl8139(dev);
-    current_vnic = dev;
-    bus = v3_get_pcibus(dev->vm, 0);
-
-    if (bus != NULL) 
-    {
-           PrintDebug("Find PCI bus in guest, attach nic to the bus %p\n", bus);
-           pdev = rtl8139_pci_init(dev, bus, -1);
-           if (pdev == NULL)
-                   PrintError("Failure to attach nic to the bus %p\n", bus);
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
     }
 
-    nic_state->pci_dev = pdev;
-
-    //rtl8139_hook_iospace(dev, 0x2000, 0x100, 1, NULL);
-
-    return 0;
-}
+    bars[0].type = PCI_BAR_IO;
+    bars[0].default_base_port = 0xc100;
+    bars[0].num_ports = 0x100;
 
-static int rtl8139_deinit_device(struct vm_device *dev)
-{
-       
-    rtl8139_unhook_iospace(); 
+    bars[0].io_read = rtl8139_ioport_read;
+    bars[0].io_write = rtl8139_ioport_write;
+    bars[0].private_data = nic_state;
 
-    return 0;
-}
-
-static struct vm_device_ops dev_ops =
-{
-    .init = rtl8139_init_device,
-    .deinit = rtl8139_deinit_device,
-    .reset = rtl8139_reset_device,
-    .start = rtl8139_start_device,
-    .stop = rtl8139_stop_device,
-};
-
-struct vm_device *v3_create_rtl8139()
-{
-    struct nic_context *nic_state = V3_Malloc(sizeof(struct nic_context));
-    PrintDebug("rtl8139 internal at %p\n", (void *)nic_state);
-    struct vm_device *dev = v3_create_device("RTL8139", &dev_ops, nic_state);
-    return dev;
-};
-
-
-
-static int register_dev(struct ne2k_state * nic_state) 
-{
-    int i;
-
-    if (nic_state->pci_bus != NULL) {
-       struct v3_pci_bar bars[6];
-       struct pci_device * pci_dev = NULL;
-
-       PrintDebug("NE2000: PCI Enabled\n");
-
-       for (i = 0; i < 6; i++) {
-           bars[i].type = PCI_BAR_NONE;
-       }
-
-       bars[0].type = PCI_BAR_IO;
-       bars[0].default_base_port = NIC_REG_BASE_PORT;
-       bars[0].num_ports = 256;
+/*
+    bars[1].type = PCI_BAR_MEM32;
+    bars[1].default_base_addr = -1;
+    bars[1].num_pages = 1;
 
-       bars[0].io_read = ne2k_pci_read;
-       bars[0].io_write = ne2k_pci_write;
-       bars[0].private_data = nic_state;
+    bars[1].mem_read = rtl8139_mmio_read;
+    bars[1].mem_write = rtl8139_mmio_write;
+    bars[1].private_data = nic_state;
+*/
 
-       pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0, 
-                                        "NE2000", bars,
-                                        pci_config_update, NULL, NULL, nic_state);
+    pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0, 
+                                        "RTL8139", bars,
+                                        NULL, NULL, NULL, nic_state);
 
 
-       if (pci_dev == NULL) {
-           PrintError("NE2000: Could not register PCI Device\n");
-           return -1;
-       }
+    if (pci_dev == NULL) {
+       PrintError("RTL8139: Could not register PCI Device\n");
+       return -1;
+    }
        
-       pci_dev->config_header.vendor_id = 0x10ec;
-       pci_dev->config_header.device_id = 0x8029;
-       pci_dev->config_header.revision = 0x00;
-
-       pci_dev->config_header.subclass = 0x00;
-       pci_dev->config_header.class = 0x02;
-       pci_dev->config_header.header_type = 0x00;
-
-       pci_dev->config_header.intr_line = 11;
-       pci_dev->config_header.intr_pin = 1;
-
-       nic_state->pci_dev = pci_dev;
-    }else {
-       PrintDebug("NE2000: Not attached to PCI\n");
-
-       v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
-
-       for (i = 1; i < 16; i++){       
-           v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
-       }
+    pci_dev->config_header.vendor_id = 0x10ec;
+    pci_dev->config_header.device_id = 0x8139;
+    pci_dev->config_header.command = 0x05;
+       
+    pci_dev->config_header.revision = RTL8139_PCI_REVID_8139;
 
-       v3_dev_hook_io(nic_state->dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
-       v3_dev_hook_io(nic_state->dev, NIC_RESET_PORT, &ne2k_reset_port_read, &ne2k_reset_port_write);
-    }
+    pci_dev->config_header.subclass = 0x00;
+    pci_dev->config_header.class = 0x02;
+    pci_dev->config_header.header_type = 0x00;
 
+    pci_dev->config_header.intr_line = 12;
+    pci_dev->config_header.intr_pin = 1;
+    pci_dev->config_space[0x34] = 0xdc;
 
+    nic_state->pci_dev = pci_dev;
+       
     return 0;
 }
 
                      struct v3_dev_net_ops * ops, 
                      v3_cfg_tree_t * cfg, 
                      void * private_data) {
-    struct ne2k_state * nic_state = (struct ne2k_state *)frontend_data;
+    struct rtl8139_state * nic_state = (struct rtl8139_state *)frontend_data;
 
     rtl8139_init_state(nic_state);
     register_dev(nic_state);
     nic_state->net_ops = ops;
     nic_state->backend_data = private_data;    
 
-    ops->recv = ne2k_rx;
+    ops->recv = rtl8139_rx;
     ops->poll = NULL;
     ops->start_tx = NULL;
     ops->stop_tx = NULL;
 }
 
 
-static int rtl8139_free(struct ne2k_state * nic_state) {
-    int i;
+static int rtl8139_free(void * private_data) {
+    struct rtl8139_state * nic_state = (struct rtl8139_state *)private_data;
 
     /* dettached from backend */
 
-    if(nic_state->pci_bus == NULL){
-       for (i = 0; i < 16; i++){               
-           v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + i);
-       }
-    
-       v3_dev_unhook_io(nic_state->dev, NIC_DATA_PORT);
-       v3_dev_unhook_io(nic_state->dev, NIC_RESET_PORT);
-    }else {
-       /* unregistered from PCI? */
-    }
-  
-    return 0;
+    /* unregistered from PCI? */
 
     V3_Free(nic_state);
        
 
 
 static struct v3_device_ops dev_ops = {
-    .free = (int (*)(void *))rtl8139_free,
+    .free = rtl8139_free,
 };
 
 
     char * macstr = v3_cfg_val(cfg, "mac");
 
     nic_state  = (struct rtl8139_state *)V3_Malloc(sizeof(struct rtl8139_state));
-    memset(nic_state, 0, sizeof(struct ne2k_state));
+    memset(nic_state, 0, sizeof(struct rtl8139_state));
 
     nic_state->pci_bus = pci_bus;
     nic_state->vm = vm;