Better handling of latency/frequency parameter types
[gem5.git] / dev / ns_gige.cc
index f5cbdbb9a1154c147923f6fcef827133637b964c..53a881ef704dbf41f8dbfc57897070657fa052d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "base/inet.hh"
 #include "cpu/exec_context.hh"
-#include "cpu/intr_control.hh"
 #include "dev/dma.hh"
-#include "dev/ns_gige.hh"
 #include "dev/etherlink.hh"
+#include "dev/ns_gige.hh"
+#include "dev/pciconfigall.hh"
 #include "mem/bus/bus.hh"
 #include "mem/bus/dma_interface.hh"
 #include "mem/bus/pio_interface.hh"
 #include "mem/functional_mem/memory_control.hh"
 #include "mem/functional_mem/physical_memory.hh"
 #include "sim/builder.hh"
+#include "sim/debug.hh"
 #include "sim/host.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 #include "targetarch/vtophys.hh"
-#include "dev/pciconfigall.hh"
-#include "dev/tsunami_cchip.hh"
 
 const char *NsRxStateStrings[] =
 {
@@ -85,80 +84,75 @@ const char *NsDmaState[] =
 };
 
 using namespace std;
+using namespace Net;
 
 ///////////////////////////////////////////////////////////////////////
 //
-// EtherDev PCI Device
+// NSGigE PCI Device
 //
-EtherDev::EtherDev(const std::string &name, IntrControl *i, Tick intr_delay,
-             PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
-             MemoryController *mmu, HierParams *hier, Bus *header_bus,
-             Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
-             bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
-             Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
-             PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
-             uint32_t func, bool rx_filter, const int eaddr[6], Addr addr)
-    : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t),
-      addr(addr), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
-      txXferLen(0), rxXferLen(0), txPktXmitted(0), txState(txIdle), CTDD(false),
-      txFifoCnt(0), txFifoAvail(MAX_TX_FIFO_SIZE), txHalt(false),
+NSGigE::NSGigE(Params *p)
+    : PciDev(p), ioEnable(false),
+      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
+      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
+      txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false),
+      CTDD(false),
       txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
-      CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false),
+      rxEnable(false), CRDD(false), rxPktBytes(0),
       rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
       rxDmaReadEvent(this), rxDmaWriteEvent(this),
       txDmaReadEvent(this), txDmaWriteEvent(this),
-      dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free),
-      txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0),
-      txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false),
+      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
+      txDelay(p->tx_delay), rxDelay(p->rx_delay),
+      rxKickTick(0), txKickTick(0),
+      txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
       acceptMulticast(false), acceptUnicast(false),
       acceptPerfect(false), acceptArp(false),
-      physmem(pmem), intctrl(i), intrTick(0),
-      cpuPendingIntr(false), intrEvent(0), interface(0), pioLatency(pio_latency)
+      physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
+      intrEvent(0), interface(0)
 {
-    mmu->add_child(this, Range<Addr>(addr, addr + size));
-    tsunami->ethernet = this;
-
-    if (header_bus) {
-        pioInterface = newPioInterface(name, hier, header_bus, this,
-                                       &EtherDev::cacheAccess);
-        pioInterface->addAddrRange(addr, addr + size - 1);
-        if (payload_bus)
-            dmaInterface = new DMAInterface<Bus>(name + ".dma",
-                                                 header_bus, payload_bus, 1);
-        else
-            dmaInterface = new DMAInterface<Bus>(name + ".dma",
-                                                 header_bus, header_bus, 1);
-    } else if (payload_bus) {
-        pioInterface = newPioInterface(name, hier, payload_bus, this,
-                                       &EtherDev::cacheAccess);
-        pioInterface->addAddrRange(addr, addr + size - 1);
-        dmaInterface = new DMAInterface<Bus>(name + ".dma",
-                                             payload_bus, payload_bus, 1);
+    if (p->header_bus) {
+        pioInterface = newPioInterface(name(), p->hier,
+                                       p->header_bus, this,
+                                       &NSGigE::cacheAccess);
+
+        pioLatency = p->pio_latency * p->header_bus->clockRatio;
 
+        if (p->payload_bus)
+            dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+                                                 p->header_bus,
+                                                 p->payload_bus, 1);
+        else
+            dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+                                                 p->header_bus,
+                                                 p->header_bus, 1);
+    } else if (p->payload_bus) {
+        pioInterface = newPioInterface(name(), p->hier,
+                                       p->payload_bus, this,
+                                       &NSGigE::cacheAccess);
+
+        pioLatency = p->pio_latency * p->payload_bus->clockRatio;
+
+        dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+                                             p->payload_bus,
+                                             p->payload_bus, 1);
     }
 
 
-    intrDelay = US2Ticks(intr_delay);
-    dmaReadDelay = dma_read_delay;
-    dmaWriteDelay = dma_write_delay;
-    dmaReadFactor = dma_read_factor;
-    dmaWriteFactor = dma_write_factor;
+    intrDelay = US2Ticks(p->intr_delay);
+    dmaReadDelay = p->dma_read_delay;
+    dmaWriteDelay = p->dma_write_delay;
+    dmaReadFactor = p->dma_read_factor;
+    dmaWriteFactor = p->dma_write_factor;
 
-    memset(&regs, 0, sizeof(regs));
     regsReset();
-    rom.perfectMatch[0] = eaddr[0];
-    rom.perfectMatch[1] = eaddr[1];
-    rom.perfectMatch[2] = eaddr[2];
-    rom.perfectMatch[3] = eaddr[3];
-    rom.perfectMatch[4] = eaddr[4];
-    rom.perfectMatch[5] = eaddr[5];
+    memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
 }
 
-EtherDev::~EtherDev()
+NSGigE::~NSGigE()
 {}
 
 void
-EtherDev::regStats()
+NSGigE::regStats()
 {
     txBytes
         .name(name() + ".txBytes")
@@ -184,6 +178,72 @@ EtherDev::regStats()
         .prereq(rxBytes)
         ;
 
+    txIpChecksums
+        .name(name() + ".txIpChecksums")
+        .desc("Number of tx IP Checksums done by device")
+        .precision(0)
+        .prereq(txBytes)
+        ;
+
+    rxIpChecksums
+        .name(name() + ".rxIpChecksums")
+        .desc("Number of rx IP Checksums done by device")
+        .precision(0)
+        .prereq(rxBytes)
+        ;
+
+    txTcpChecksums
+        .name(name() + ".txTcpChecksums")
+        .desc("Number of tx TCP Checksums done by device")
+        .precision(0)
+        .prereq(txBytes)
+        ;
+
+    rxTcpChecksums
+        .name(name() + ".rxTcpChecksums")
+        .desc("Number of rx TCP Checksums done by device")
+        .precision(0)
+        .prereq(rxBytes)
+        ;
+
+    txUdpChecksums
+        .name(name() + ".txUdpChecksums")
+        .desc("Number of tx UDP Checksums done by device")
+        .precision(0)
+        .prereq(txBytes)
+        ;
+
+    rxUdpChecksums
+        .name(name() + ".rxUdpChecksums")
+        .desc("Number of rx UDP Checksums done by device")
+        .precision(0)
+        .prereq(rxBytes)
+        ;
+
+    descDmaReads
+        .name(name() + ".descDMAReads")
+        .desc("Number of descriptors the device read w/ DMA")
+        .precision(0)
+        ;
+
+    descDmaWrites
+        .name(name() + ".descDMAWrites")
+        .desc("Number of descriptors the device wrote w/ DMA")
+        .precision(0)
+        ;
+
+    descDmaRdBytes
+        .name(name() + ".descDmaReadBytes")
+        .desc("number of descriptor bytes read w/ DMA")
+        .precision(0)
+        ;
+
+   descDmaWrBytes
+        .name(name() + ".descDmaWriteBytes")
+        .desc("number of descriptor bytes write w/ DMA")
+        .precision(0)
+        ;
+
     txBandwidth
         .name(name() + ".txBandwidth")
         .desc("Transmit Bandwidth (bits/s)")
@@ -198,6 +258,34 @@ EtherDev::regStats()
         .prereq(rxBytes)
         ;
 
+    totBandwidth
+        .name(name() + ".totBandwidth")
+        .desc("Total Bandwidth (bits/s)")
+        .precision(0)
+        .prereq(totBytes)
+        ;
+
+    totPackets
+        .name(name() + ".totPackets")
+        .desc("Total Packets")
+        .precision(0)
+        .prereq(totBytes)
+        ;
+
+    totBytes
+        .name(name() + ".totBytes")
+        .desc("Total Bytes")
+        .precision(0)
+        .prereq(totBytes)
+        ;
+
+    totPacketRate
+        .name(name() + ".totPPS")
+        .desc("Total Tranmission Rate (packets/s)")
+        .precision(0)
+        .prereq(totBytes)
+        ;
+
     txPacketRate
         .name(name() + ".txPPS")
         .desc("Packet Tranmission Rate (packets/s)")
@@ -212,8 +300,186 @@ EtherDev::regStats()
         .prereq(rxBytes)
         ;
 
+    postedSwi
+        .name(name() + ".postedSwi")
+        .desc("number of software interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalSwi
+        .name(name() + ".totalSwi")
+        .desc("number of total Swi written to ISR")
+        .precision(0)
+        ;
+
+    coalescedSwi
+        .name(name() + ".coalescedSwi")
+        .desc("average number of Swi's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedRxIdle
+        .name(name() + ".postedRxIdle")
+        .desc("number of rxIdle interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalRxIdle
+        .name(name() + ".totalRxIdle")
+        .desc("number of total RxIdle written to ISR")
+        .precision(0)
+        ;
+
+    coalescedRxIdle
+        .name(name() + ".coalescedRxIdle")
+        .desc("average number of RxIdle's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedRxOk
+        .name(name() + ".postedRxOk")
+        .desc("number of RxOk interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalRxOk
+        .name(name() + ".totalRxOk")
+        .desc("number of total RxOk written to ISR")
+        .precision(0)
+        ;
+
+    coalescedRxOk
+        .name(name() + ".coalescedRxOk")
+        .desc("average number of RxOk's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedRxDesc
+        .name(name() + ".postedRxDesc")
+        .desc("number of RxDesc interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalRxDesc
+        .name(name() + ".totalRxDesc")
+        .desc("number of total RxDesc written to ISR")
+        .precision(0)
+        ;
+
+    coalescedRxDesc
+        .name(name() + ".coalescedRxDesc")
+        .desc("average number of RxDesc's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedTxOk
+        .name(name() + ".postedTxOk")
+        .desc("number of TxOk interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalTxOk
+        .name(name() + ".totalTxOk")
+        .desc("number of total TxOk written to ISR")
+        .precision(0)
+        ;
+
+    coalescedTxOk
+        .name(name() + ".coalescedTxOk")
+        .desc("average number of TxOk's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedTxIdle
+        .name(name() + ".postedTxIdle")
+        .desc("number of TxIdle interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalTxIdle
+        .name(name() + ".totalTxIdle")
+        .desc("number of total TxIdle written to ISR")
+        .precision(0)
+        ;
+
+    coalescedTxIdle
+        .name(name() + ".coalescedTxIdle")
+        .desc("average number of TxIdle's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedTxDesc
+        .name(name() + ".postedTxDesc")
+        .desc("number of TxDesc interrupts posted to CPU")
+        .precision(0)
+        ;
+
+    totalTxDesc
+        .name(name() + ".totalTxDesc")
+        .desc("number of total TxDesc written to ISR")
+        .precision(0)
+        ;
+
+    coalescedTxDesc
+        .name(name() + ".coalescedTxDesc")
+        .desc("average number of TxDesc's coalesced into each post")
+        .precision(0)
+        ;
+
+    postedRxOrn
+        .name(name() + ".postedRxOrn")
+        .desc("number of RxOrn posted to CPU")
+        .precision(0)
+        ;
+
+    totalRxOrn
+        .name(name() + ".totalRxOrn")
+        .desc("number of total RxOrn written to ISR")
+        .precision(0)
+        ;
+
+    coalescedRxOrn
+        .name(name() + ".coalescedRxOrn")
+        .desc("average number of RxOrn's coalesced into each post")
+        .precision(0)
+        ;
+
+    coalescedTotal
+        .name(name() + ".coalescedTotal")
+        .desc("average number of interrupts coalesced into each post")
+        .precision(0)
+        ;
+
+    postedInterrupts
+        .name(name() + ".postedInterrupts")
+        .desc("number of posts to CPU")
+        .precision(0)
+        ;
+
+    droppedPackets
+        .name(name() + ".droppedPackets")
+        .desc("number of packets dropped")
+        .precision(0)
+        ;
+
+    coalescedSwi = totalSwi / postedInterrupts;
+    coalescedRxIdle = totalRxIdle / postedInterrupts;
+    coalescedRxOk = totalRxOk / postedInterrupts;
+    coalescedRxDesc = totalRxDesc / postedInterrupts;
+    coalescedTxOk = totalTxOk / postedInterrupts;
+    coalescedTxIdle = totalTxIdle / postedInterrupts;
+    coalescedTxDesc = totalTxDesc / postedInterrupts;
+    coalescedRxOrn = totalRxOrn / postedInterrupts;
+
+    coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + totalTxOk
+                      + totalTxIdle + totalTxDesc + totalRxOrn) / postedInterrupts;
+
     txBandwidth = txBytes * Stats::constant(8) / simSeconds;
     rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+    totBandwidth = txBandwidth + rxBandwidth;
+    totBytes = txBytes + rxBytes;
+    totPackets = txPackets + rxPackets;
+
     txPacketRate = txPackets / simSeconds;
     rxPacketRate = rxPackets / simSeconds;
 }
@@ -222,25 +488,70 @@ EtherDev::regStats()
  * This is to read the PCI general configuration registers
  */
 void
-EtherDev::ReadConfig(int offset, int size, uint8_t *data)
+NSGigE::ReadConfig(int offset, int size, uint8_t *data)
 {
     if (offset < PCI_DEVICE_SPECIFIC)
         PciDev::ReadConfig(offset, size, data);
-    else {
-        panic("need to do this\n");
-    }
+    else
+        panic("Device specific PCI config space not implemented!\n");
 }
 
 /**
  * This is to write to the PCI general configuration registers
  */
 void
-EtherDev::WriteConfig(int offset, int size, uint32_t data)
+NSGigE::WriteConfig(int offset, int size, uint32_t data)
 {
     if (offset < PCI_DEVICE_SPECIFIC)
         PciDev::WriteConfig(offset, size, data);
     else
-        panic("Need to do that\n");
+        panic("Device specific PCI config space not implemented!\n");
+
+    // Need to catch writes to BARs to update the PIO interface
+    switch (offset) {
+        // seems to work fine without all these PCI settings, but i
+        // put in the IO to double check, an assertion will fail if we
+        // need to properly implement it
+      case PCI_COMMAND:
+        if (config.data[offset] & PCI_CMD_IOSE)
+            ioEnable = true;
+        else
+            ioEnable = false;
+
+#if 0
+        if (config.data[offset] & PCI_CMD_BME) {
+            bmEnabled = true;
+        }
+        else {
+            bmEnabled = false;
+        }
+
+        if (config.data[offset] & PCI_CMD_MSE) {
+            memEnable = true;
+        }
+        else {
+            memEnable = false;
+        }
+#endif
+        break;
+
+      case PCI0_BASE_ADDR0:
+        if (BARAddrs[0] != 0) {
+            if (pioInterface)
+                pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+
+            BARAddrs[0] &= EV5::PAddrUncachedMask;
+        }
+        break;
+      case PCI0_BASE_ADDR1:
+        if (BARAddrs[1] != 0) {
+            if (pioInterface)
+                pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
+
+            BARAddrs[1] &= EV5::PAddrUncachedMask;
+        }
+        break;
+    }
 }
 
 /**
@@ -248,16 +559,18 @@ EtherDev::WriteConfig(int offset, int size, uint32_t data)
  * spec sheet
  */
 Fault
-EtherDev::read(MemReqPtr &req, uint8_t *data)
+NSGigE::read(MemReqPtr &req, uint8_t *data)
 {
+    assert(ioEnable);
+
     //The mask is to give you only the offset into the device register file
     Addr daddr = req->paddr & 0xfff;
     DPRINTF(EthernetPIO, "read  da=%#x pa=%#x va=%#x size=%d\n",
             daddr, req->paddr, req->vaddr, req->size);
 
 
-    //there are some reserved registers, you can see ns_gige_reg.h and
-    //the spec sheet for details
+    // there are some reserved registers, you can see ns_gige_reg.h and
+    // the spec sheet for details
     if (daddr > LAST && daddr <=  RESERVED) {
         panic("Accessing reserved register");
     } else if (daddr > RESERVED && daddr <= 0x3FC) {
@@ -354,16 +667,16 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
                 reg = regs.pcr;
                 break;
 
-                //see the spec sheet for how RFCR and RFDR work
-                //basically, you write to RFCR to tell the machine what you want to do next
-                //then you act upon RFDR, and the device will be prepared b/c
-                //of what you wrote to RFCR
+                // see the spec sheet for how RFCR and RFDR work
+                // basically, you write to RFCR to tell the machine
+                // what you want to do next, then you act upon RFDR,
+                // and the device will be prepared b/c of what you
+                // wrote to RFCR
               case RFCR:
                 reg = regs.rfcr;
                 break;
 
               case RFDR:
-                DPRINTF(Ethernet, "reading from RFDR\n");
                 switch (regs.rfcr & RFCR_RFADDR) {
                   case 0x000:
                     reg = rom.perfectMatch[1];
@@ -379,8 +692,9 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
                     reg += rom.perfectMatch[4];
                     break;
                   default:
-                    panic("reading from RFDR for something for other than PMATCH!\n");
-                    //didn't implement other RFDR functionality b/c driver didn't use
+                    panic("reading RFDR for something other than PMATCH!\n");
+                    // didn't implement other RFDR functionality b/c
+                    // driver didn't use it
                 }
                 break;
 
@@ -434,10 +748,11 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
                 break;
 
               default:
-                panic("reading unimplemented register: addr = %#x", daddr);
+                panic("reading unimplemented register: addr=%#x", daddr);
             }
 
-            DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", daddr, reg, reg);
+            DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
+                    daddr, reg, reg);
         }
         break;
 
@@ -450,8 +765,10 @@ EtherDev::read(MemReqPtr &req, uint8_t *data)
 }
 
 Fault
-EtherDev::write(MemReqPtr &req, const uint8_t *data)
+NSGigE::write(MemReqPtr &req, const uint8_t *data)
 {
+    assert(ioEnable);
+
     Addr daddr = req->paddr & 0xfff;
     DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n",
             daddr, req->paddr, req->vaddr, req->size);
@@ -471,24 +788,23 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
         switch (daddr) {
           case CR:
             regs.command = reg;
-            if ((reg & (CR_TXE | CR_TXD)) == (CR_TXE | CR_TXD)) {
-                txHalt = true;
+            if (reg & CR_TXD) {
+                txEnable = false;
             } else if (reg & CR_TXE) {
-                //the kernel is enabling the transmit machine
+                txEnable = true;
+
+                // the kernel is enabling the transmit machine
                 if (txState == txIdle)
                     txKick();
-            } else if (reg & CR_TXD) {
-                txHalt = true;
             }
 
-            if ((reg & (CR_RXE | CR_RXD)) == (CR_RXE | CR_RXD)) {
-                rxHalt = true;
+            if (reg & CR_RXD) {
+                rxEnable = false;
             } else if (reg & CR_RXE) {
-                if (rxState == rxIdle) {
+                rxEnable = true;
+
+                if (rxState == rxIdle)
                     rxKick();
-                }
-            } else if (reg & CR_RXD) {
-                rxHalt = true;
             }
 
             if (reg & CR_TXR)
@@ -509,26 +825,34 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
             break;
 
           case CFG:
-            if (reg & CFG_LNKSTS || reg & CFG_SPDSTS || reg & CFG_DUPSTS
-                || reg & CFG_RESERVED || reg & CFG_T64ADDR
-                || reg & CFG_PCI64_DET)
+            if (reg & CFG_LNKSTS ||
+                reg & CFG_SPDSTS ||
+                reg & CFG_DUPSTS ||
+                reg & CFG_RESERVED ||
+                reg & CFG_T64ADDR ||
+                reg & CFG_PCI64_DET)
                 panic("writing to read-only or reserved CFG bits!\n");
 
-            regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | CFG_RESERVED |
-                                  CFG_T64ADDR | CFG_PCI64_DET);
+            regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS |
+                                   CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET);
 
-// all these #if 0's are because i don't THINK the kernel needs to have these implemented
-// if there is a problem relating to one of these, you may need to add functionality in
+// all these #if 0's are because i don't THINK the kernel needs to
+// have these implemented. if there is a problem relating to one of
+// these, you may need to add functionality in.
 #if 0
-              if (reg & CFG_TBI_EN) ;
-              if (reg & CFG_MODE_1000) ;
+            if (reg & CFG_TBI_EN) ;
+            if (reg & CFG_MODE_1000) ;
 #endif
 
             if (reg & CFG_AUTO_1000)
                 panic("CFG_AUTO_1000 not implemented!\n");
 
 #if 0
-            if (reg & CFG_PINT_DUPSTS || reg & CFG_PINT_LNKSTS || reg & CFG_PINT_SPDSTS) ;
+            if (reg & CFG_PINT_DUPSTS ||
+                reg & CFG_PINT_LNKSTS ||
+                reg & CFG_PINT_SPDSTS)
+                ;
+
             if (reg & CFG_TMRTEST) ;
             if (reg & CFG_MRM_DIS) ;
             if (reg & CFG_MWI_DIS) ;
@@ -564,11 +888,12 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
 
           case MEAR:
             regs.mear = reg;
-            /* since phy is completely faked, MEAR_MD* don't matter
-               and since the driver never uses MEAR_EE*, they don't matter */
+            // since phy is completely faked, MEAR_MD* don't matter
+            // and since the driver never uses MEAR_EE*, they don't
+            // matter
 #if 0
             if (reg & MEAR_EEDI) ;
-            if (reg & MEAR_EEDO) ; //this one is read only
+            if (reg & MEAR_EEDO) ; // this one is read only
             if (reg & MEAR_EECLK) ;
             if (reg & MEAR_EESEL) ;
             if (reg & MEAR_MDIO) ;
@@ -579,8 +904,8 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
 
           case PTSCR:
             regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
-            /* these control BISTs for various parts of chip - we don't care or do
-               just fake that the BIST is done */
+            // these control BISTs for various parts of chip - we
+            // don't care or do just fake that the BIST is done
             if (reg & PTSCR_RBIST_EN)
                 regs.ptscr |= PTSCR_RBIST_DONE;
             if (reg & PTSCR_EEBIST_EN)
@@ -623,16 +948,26 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
             if (reg & TXCFG_HBI) ;
             if (reg & TXCFG_MLB) ;
             if (reg & TXCFG_ATP) ;
-            if (reg & TXCFG_ECRETRY) ;  /* this could easily be implemented, but
-                                           considering the network is just a fake
-                                           pipe, wouldn't make sense to do this */
+            if (reg & TXCFG_ECRETRY) {
+                /*
+                 * this could easily be implemented, but considering
+                 * the network is just a fake pipe, wouldn't make
+                 * sense to do this
+                 */
+            }
 
             if (reg & TXCFG_BRST_DIS) ;
 #endif
 
-
+#if 0
             /* we handle our own DMA, ignore the kernel's exhortations */
             if (reg & TXCFG_MXDMA) ;
+#endif
+
+            // also, we currently don't care about fill/drain
+            // thresholds though this may change in the future with
+            // more realistic networks or a driver which changes it
+            // according to feedback
 
             break;
 
@@ -643,6 +978,7 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
 
           case RXDP:
             regs.rxdp = reg;
+            CRDD = false;
             break;
 
           case RXDP_HI:
@@ -658,12 +994,13 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
             if (reg & RXCFG_RX_RD) ;
             if (reg & RXCFG_ALP) ;
             if (reg & RXCFG_AIRL) ;
-#endif
 
             /* we handle our own DMA, ignore what kernel says about it */
             if (reg & RXCFG_MXDMA) ;
 
-#if 0
+            //also, we currently don't care about fill/drain thresholds
+            //though this may change in the future with more realistic
+            //networks or a driver which changes it according to feedback
             if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ;
 #endif
             break;
@@ -685,22 +1022,18 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
 
           case RFCR:
             regs.rfcr = reg;
-            DPRINTF(Ethernet, "Writing to RFCR, RFADDR is %#x\n", reg & RFCR_RFADDR);
 
             rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
-
             acceptBroadcast = (reg & RFCR_AAB) ? true : false;
-
             acceptMulticast = (reg & RFCR_AAM) ? true : false;
-
             acceptUnicast = (reg & RFCR_AAU) ? true : false;
-
             acceptPerfect = (reg & RFCR_APM) ? true : false;
-
             acceptArp = (reg & RFCR_AARP) ? true : false;
 
-            if (reg & RFCR_APAT) ;
-//                panic("RFCR_APAT not implemented!\n");
+#if 0
+            if (reg & RFCR_APAT)
+                panic("RFCR_APAT not implemented!\n");
+#endif
 
             if (reg & RFCR_MHEN || reg & RFCR_UHEN)
                 panic("hash filtering not implemented!\n");
@@ -781,147 +1114,122 @@ EtherDev::write(MemReqPtr &req, const uint8_t *data)
             break;
 
           default:
-            panic("thought i covered all the register, what is this? addr=%#x",
-                  daddr);
+            panic("invalid register access daddr=%#x", daddr);
         }
-    } else
+    } else {
         panic("Invalid Request Size");
+    }
 
     return No_Fault;
 }
 
 void
-EtherDev::devIntrPost(uint32_t interrupts)
+NSGigE::devIntrPost(uint32_t interrupts)
 {
-    DPRINTF(Ethernet, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
-            interrupts, regs.isr, regs.imr);
-
-    bool delay = false;
-
     if (interrupts & ISR_RESERVE)
         panic("Cannot set a reserved interrupt");
 
-    if (interrupts & ISR_TXRCMP)
-        regs.isr |= ISR_TXRCMP;
-
-    if (interrupts & ISR_RXRCMP)
-        regs.isr |= ISR_RXRCMP;
-
-//ISR_DPERR  not implemented
-//ISR_SSERR not implemented
-//ISR_RMABT not implemented
-//ISR_RXSOVR not implemented
-//ISR_HIBINT not implemented
-//ISR_PHY not implemented
-//ISR_PME not implemented
-
-    if (interrupts & ISR_SWI)
-        regs.isr |= ISR_SWI;
+    if (interrupts & ISR_NOIMPL)
+        warn("interrupt not implemented %#x\n", interrupts);
 
-//ISR_MIB not implemented
-//ISR_TXURN not implemented
+    interrupts &= ~ISR_NOIMPL;
+    regs.isr |= interrupts;
 
-    if (interrupts & ISR_TXIDLE)
-        regs.isr |= ISR_TXIDLE;
-
-    if (interrupts & ISR_TXERR)
-        regs.isr |= ISR_TXERR;
-
-    if (interrupts & ISR_TXDESC)
-        regs.isr |= ISR_TXDESC;
-
-    if (interrupts & ISR_TXOK) {
-        regs.isr |= ISR_TXOK;
-        delay = true;
+    if (interrupts & regs.imr) {
+        if (interrupts & ISR_SWI) {
+            totalSwi++;
+        }
+        if (interrupts & ISR_RXIDLE) {
+            totalRxIdle++;
+        }
+        if (interrupts & ISR_RXOK) {
+            totalRxOk++;
+        }
+        if (interrupts & ISR_RXDESC) {
+            totalRxDesc++;
+        }
+        if (interrupts & ISR_TXOK) {
+            totalTxOk++;
+        }
+        if (interrupts & ISR_TXIDLE) {
+            totalTxIdle++;
+        }
+        if (interrupts & ISR_TXDESC) {
+            totalTxDesc++;
+        }
+        if (interrupts & ISR_RXORN) {
+            totalRxOrn++;
+        }
     }
 
-    if (interrupts & ISR_RXORN)
-        regs.isr |= ISR_RXORN;
-
-    if (interrupts & ISR_RXIDLE)
-        regs.isr |= ISR_RXIDLE;
-
-//ISR_RXEARLY not implemented
-
-    if (interrupts & ISR_RXERR)
-        regs.isr |= ISR_RXERR;
-
-    if (interrupts & ISR_RXOK) {
-        delay = true;
-        regs.isr |= ISR_RXOK;
-    }
+    DPRINTF(EthernetIntr,
+            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
+            interrupts, regs.isr, regs.imr);
 
     if ((regs.isr & regs.imr)) {
         Tick when = curTick;
-        if (delay)
+        if (!(regs.isr & regs.imr & ISR_NODELAY))
             when += intrDelay;
         cpuIntrPost(when);
     }
 }
 
+/* writing this interrupt counting stats inside this means that this function
+   is now limited to being used to clear all interrupts upon the kernel
+   reading isr and servicing.  just telling you in case you were thinking
+   of expanding use.
+*/
 void
-EtherDev::devIntrClear(uint32_t interrupts)
+NSGigE::devIntrClear(uint32_t interrupts)
 {
-    DPRINTF(Ethernet, "interrupt cleared intr=%x isr=%x imr=%x\n",
-            interrupts, regs.isr, regs.imr);
-
     if (interrupts & ISR_RESERVE)
         panic("Cannot clear a reserved interrupt");
 
-    if (interrupts & ISR_TXRCMP)
-        regs.isr &= ~ISR_TXRCMP;
-
-    if (interrupts & ISR_RXRCMP)
-        regs.isr &= ~ISR_RXRCMP;
-
-//ISR_DPERR  not implemented
-//ISR_SSERR not implemented
-//ISR_RMABT not implemented
-//ISR_RXSOVR not implemented
-//ISR_HIBINT not implemented
-//ISR_PHY not implemented
-//ISR_PME not implemented
-
-    if (interrupts & ISR_SWI)
-        regs.isr &= ~ISR_SWI;
-
-//ISR_MIB not implemented
-//ISR_TXURN not implemented
-
-    if (interrupts & ISR_TXIDLE)
-        regs.isr &= ~ISR_TXIDLE;
-
-    if (interrupts & ISR_TXERR)
-        regs.isr &= ~ISR_TXERR;
-
-    if (interrupts & ISR_TXDESC)
-        regs.isr &= ~ISR_TXDESC;
-
-    if (interrupts & ISR_TXOK)
-        regs.isr &= ~ISR_TXOK;
-
-    if (interrupts & ISR_RXORN)
-        regs.isr &= ~ISR_RXORN;
-
-    if (interrupts & ISR_RXIDLE)
-        regs.isr &= ~ISR_RXIDLE;
+    if (regs.isr & regs.imr & ISR_SWI) {
+        postedSwi++;
+    }
+    if (regs.isr & regs.imr & ISR_RXIDLE) {
+        postedRxIdle++;
+    }
+    if (regs.isr & regs.imr & ISR_RXOK) {
+        postedRxOk++;
+    }
+    if (regs.isr & regs.imr & ISR_RXDESC) {
+            postedRxDesc++;
+    }
+    if (regs.isr & regs.imr & ISR_TXOK) {
+        postedTxOk++;
+    }
+    if (regs.isr & regs.imr & ISR_TXIDLE) {
+        postedTxIdle++;
+    }
+    if (regs.isr & regs.imr & ISR_TXDESC) {
+        postedTxDesc++;
+    }
+    if (regs.isr & regs.imr & ISR_RXORN) {
+        postedRxOrn++;
+    }
 
-//ISR_RXEARLY not implemented
+    if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC |
+                               ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) )
+        postedInterrupts++;
 
-    if (interrupts & ISR_RXERR)
-        regs.isr &= ~ISR_RXERR;
+    interrupts &= ~ISR_NOIMPL;
+    regs.isr &= ~interrupts;
 
-    if (interrupts & ISR_RXOK)
-        regs.isr &= ~ISR_RXOK;
+    DPRINTF(EthernetIntr,
+            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
+            interrupts, regs.isr, regs.imr);
 
     if (!(regs.isr & regs.imr))
         cpuIntrClear();
 }
 
 void
-EtherDev::devIntrChangeMask()
+NSGigE::devIntrChangeMask()
 {
-    DPRINTF(Ethernet, "interrupt mask changed\n");
+    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
+            regs.isr, regs.imr, regs.isr & regs.imr);
 
     if (regs.isr & regs.imr)
         cpuIntrPost(curTick);
@@ -930,105 +1238,144 @@ EtherDev::devIntrChangeMask()
 }
 
 void
-EtherDev::cpuIntrPost(Tick when)
+NSGigE::cpuIntrPost(Tick when)
 {
-    if (when > intrTick && intrTick != 0)
+    // If the interrupt you want to post is later than an interrupt
+    // already scheduled, just let it post in the coming one and don't
+    // schedule another.
+    // HOWEVER, must be sure that the scheduled intrTick is in the
+    // future (this was formerly the source of a bug)
+    /**
+     * @todo this warning should be removed and the intrTick code should
+     * be fixed.
+     */
+    assert(when >= curTick);
+    assert(intrTick >= curTick || intrTick == 0);
+    if (when > intrTick && intrTick != 0) {
+        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+                intrTick);
         return;
+    }
 
     intrTick = when;
-
-    if (intrEvent) {
-        intrEvent->squash();
-        intrEvent = 0;
+    if (intrTick < curTick) {
+        debug_break();
+        intrTick = curTick;
     }
 
-    if (when < curTick) {
-        cpuInterrupt();
-    } else {
-        intrEvent = new IntrEvent(this, true);
-        intrEvent->schedule(intrTick);
-    }
+    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+            intrTick);
+
+    if (intrEvent)
+        intrEvent->squash();
+    intrEvent = new IntrEvent(this, true);
+    intrEvent->schedule(intrTick);
 }
 
 void
-EtherDev::cpuInterrupt()
+NSGigE::cpuInterrupt()
 {
-    // Don't send an interrupt if there's already one
-    if (cpuPendingIntr)
-        return;
-
-    // Don't send an interrupt if it's supposed to be delayed
-    if (intrTick > curTick)
-        return;
+    assert(intrTick == curTick);
 
     // Whether or not there's a pending interrupt, we don't care about
     // it anymore
     intrEvent = 0;
     intrTick = 0;
 
-    // Send interrupt
-    cpuPendingIntr = true;
-    /** @todo rework the intctrl to be tsunami ok */
-    //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
-    tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
+    // Don't send an interrupt if there's already one
+    if (cpuPendingIntr) {
+        DPRINTF(EthernetIntr,
+                "would send an interrupt now, but there's already pending\n");
+    } else {
+        // Send interrupt
+        cpuPendingIntr = true;
+
+        DPRINTF(EthernetIntr, "posting interrupt\n");
+        intrPost();
+    }
 }
 
 void
-EtherDev::cpuIntrClear()
+NSGigE::cpuIntrClear()
 {
-    if (cpuPendingIntr) {
-        cpuPendingIntr = false;
-        /** @todo rework the intctrl to be tsunami ok */
-        //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
-        tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
+    if (!cpuPendingIntr)
+        return;
+
+    if (intrEvent) {
+        intrEvent->squash();
+        intrEvent = 0;
     }
+
+    intrTick = 0;
+
+    cpuPendingIntr = false;
+
+    DPRINTF(EthernetIntr, "clearing interrupt\n");
+    intrClear();
 }
 
 bool
-EtherDev::cpuIntrPending() const
+NSGigE::cpuIntrPending() const
 { return cpuPendingIntr; }
 
 void
-EtherDev::txReset()
+NSGigE::txReset()
 {
 
     DPRINTF(Ethernet, "transmit reset\n");
 
     CTDD = false;
-    txFifoCnt = 0;
-    txFifoAvail = MAX_TX_FIFO_SIZE;
-    txHalt = false;
+    txEnable = false;;
     txFragPtr = 0;
     assert(txDescCnt == 0);
     txFifo.clear();
-    regs.command &= ~CR_TXE;
     txState = txIdle;
     assert(txDmaState == dmaIdle);
 }
 
 void
-EtherDev::rxReset()
+NSGigE::rxReset()
 {
     DPRINTF(Ethernet, "receive reset\n");
 
     CRDD = false;
     assert(rxPktBytes == 0);
-    rxFifoCnt = 0;
-    rxHalt = false;
+    rxEnable = false;
     rxFragPtr = 0;
     assert(rxDescCnt == 0);
     assert(rxDmaState == dmaIdle);
     rxFifo.clear();
-    regs.command &= ~CR_RXE;
     rxState = rxIdle;
 }
 
 void
-EtherDev::rxDmaReadCopy()
+NSGigE::regsReset()
+{
+    memset(&regs, 0, sizeof(regs));
+    regs.config = CFG_LNKSTS;
+    regs.mear = MEAR_MDDIR | MEAR_EEDO;
+    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
+                        // fill threshold to 32 bytes
+    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
+    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
+    regs.mibc = MIBC_FRZ;
+    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
+    regs.tesr = 0xc000; // TBI capable of both full and half duplex
+
+    extstsEnable = false;
+    acceptBroadcast = false;
+    acceptMulticast = false;
+    acceptUnicast = false;
+    acceptPerfect = false;
+    acceptArp = false;
+}
+
+void
+NSGigE::rxDmaReadCopy()
 {
     assert(rxDmaState == dmaReading);
 
-    memcpy(rxDmaData, physmem->dma_addr(rxDmaAddr, rxDmaLen), rxDmaLen);
+    physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen);
     rxDmaState = dmaIdle;
 
     DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
@@ -1037,7 +1384,7 @@ EtherDev::rxDmaReadCopy()
 }
 
 bool
-EtherDev::doRxDmaRead()
+NSGigE::doRxDmaRead()
 {
     assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
     rxDmaState = dmaReading;
@@ -1047,7 +1394,7 @@ EtherDev::doRxDmaRead()
             rxDmaState = dmaReadWaiting;
         else
             dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick,
-                                &rxDmaReadEvent);
+                                &rxDmaReadEvent, true);
         return true;
     }
 
@@ -1063,7 +1410,7 @@ EtherDev::doRxDmaRead()
 }
 
 void
-EtherDev::rxDmaReadDone()
+NSGigE::rxDmaReadDone()
 {
     assert(rxDmaState == dmaReading);
     rxDmaReadCopy();
@@ -1076,11 +1423,11 @@ EtherDev::rxDmaReadDone()
 }
 
 void
-EtherDev::rxDmaWriteCopy()
+NSGigE::rxDmaWriteCopy()
 {
     assert(rxDmaState == dmaWriting);
 
-    memcpy(physmem->dma_addr(rxDmaAddr, rxDmaLen), rxDmaData, rxDmaLen);
+    physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
     rxDmaState = dmaIdle;
 
     DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
@@ -1089,7 +1436,7 @@ EtherDev::rxDmaWriteCopy()
 }
 
 bool
-EtherDev::doRxDmaWrite()
+NSGigE::doRxDmaWrite()
 {
     assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
     rxDmaState = dmaWriting;
@@ -1099,7 +1446,7 @@ EtherDev::doRxDmaWrite()
             rxDmaState = dmaWriteWaiting;
         else
             dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick,
-                                &rxDmaWriteEvent);
+                                &rxDmaWriteEvent, true);
         return true;
     }
 
@@ -1115,7 +1462,7 @@ EtherDev::doRxDmaWrite()
 }
 
 void
-EtherDev::rxDmaWriteDone()
+NSGigE::rxDmaWriteDone()
 {
     assert(rxDmaState == dmaWriting);
     rxDmaWriteCopy();
@@ -1128,13 +1475,13 @@ EtherDev::rxDmaWriteDone()
 }
 
 void
-EtherDev::rxKick()
+NSGigE::rxKick()
 {
-    DPRINTF(Ethernet, "receive kick state=%s (rxBuf.size=%d)\n",
+    DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n",
             NsRxStateStrings[rxState], rxFifo.size());
 
     if (rxKickTick > curTick) {
-        DPRINTF(Ethernet, "receive kick exiting, can't run till %d\n",
+        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
                 rxKickTick);
         return;
     }
@@ -1154,15 +1501,16 @@ EtherDev::rxKick()
     }
 
     // see state machine from spec for details
-    // the way this works is, if you finish work on one state and can go directly to
-    // another, you do that through jumping to the label "next".  however, if you have
-    // intermediate work, like DMA so that you can't go to the next state yet, you go to
-    // exit and exit the loop.  however, when the DMA is done it will trigger an
-    // event and come back to this loop.
+    // the way this works is, if you finish work on one state and can
+    // go directly to another, you do that through jumping to the
+    // label "next".  however, if you have intermediate work, like DMA
+    // so that you can't go to the next state yet, you go to exit and
+    // exit the loop.  however, when the DMA is done it will trigger
+    // an event and come back to this loop.
     switch (rxState) {
       case rxIdle:
-        if (!regs.command & CR_RXE) {
-            DPRINTF(Ethernet, "Receive Disabled! Nothing to do.\n");
+        if (!rxEnable) {
+            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
             goto exit;
         }
 
@@ -1174,6 +1522,9 @@ EtherDev::rxKick()
             rxDmaLen = sizeof(rxDescCache.link);
             rxDmaFree = dmaDescFree;
 
+            descDmaReads++;
+            descDmaRdBytes += rxDmaLen;
+
             if (doRxDmaRead())
                 goto exit;
         } else {
@@ -1184,6 +1535,9 @@ EtherDev::rxKick()
             rxDmaLen = sizeof(ns_desc);
             rxDmaFree = dmaDescFree;
 
+            descDmaReads++;
+            descDmaRdBytes += rxDmaLen;
+
             if (doRxDmaRead())
                 goto exit;
         }
@@ -1200,8 +1554,18 @@ EtherDev::rxKick()
         if (rxDmaState != dmaIdle)
             goto exit;
 
+        DPRINTF(EthernetDesc,
+                "rxDescCache: addr=%08x read descriptor\n",
+                regs.rxdp & 0x3fffffff);
+        DPRINTF(EthernetDesc,
+                "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
+                rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
+                rxDescCache.extsts);
+
         if (rxDescCache.cmdsts & CMDSTS_OWN) {
+            devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
+            goto exit;
         } else {
             rxState = rxFifoBlock;
             rxFragPtr = rxDescCache.bufptr;
@@ -1219,25 +1583,41 @@ EtherDev::rxKick()
             if (rxFifo.empty())
                 goto exit;
 
+            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
+
             // If we don't have a packet, grab a new one from the fifo.
             rxPacket = rxFifo.front();
             rxPktBytes = rxPacket->length;
             rxPacketBufPtr = rxPacket->data;
 
+#if TRACING_ON
+            if (DTRACE(Ethernet)) {
+                IpPtr ip(rxPacket);
+                if (ip) {
+                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
+                    TcpPtr tcp(ip);
+                    if (tcp) {
+                        DPRINTF(Ethernet,
+                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+                                tcp->sport(), tcp->dport(), tcp->seq(),
+                                tcp->ack());
+                    }
+                }
+            }
+#endif
+
             // sanity check - i think the driver behaves like this
             assert(rxDescCnt >= rxPktBytes);
-
-            // Must clear the value before popping to decrement the
-            // reference count
-            rxFifo.front() = NULL;
-            rxFifo.pop_front();
+            rxFifo.pop();
         }
 
 
-        // dont' need the && rxDescCnt > 0 if driver sanity check above holds
+        // dont' need the && rxDescCnt > 0 if driver sanity check
+        // above holds
         if (rxPktBytes > 0) {
             rxState = rxFragWrite;
-            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds
+            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
+            // check holds
             rxXferLen = rxPktBytes;
 
             rxDmaAddr = rxFragPtr & 0x3fffffff;
@@ -1253,62 +1633,86 @@ EtherDev::rxKick()
 
             //if (rxPktBytes == 0) {  /* packet is done */
             assert(rxPktBytes == 0);
-
-            rxFifoCnt -= rxPacket->length;
-            rxPacket = 0;
+            DPRINTF(EthernetSM, "done with receiving packet\n");
 
             rxDescCache.cmdsts |= CMDSTS_OWN;
             rxDescCache.cmdsts &= ~CMDSTS_MORE;
             rxDescCache.cmdsts |= CMDSTS_OK;
+            rxDescCache.cmdsts &= 0xffff0000;
             rxDescCache.cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
 
 #if 0
-            /* all the driver uses these are for its own stats keeping
-               which we don't care about, aren't necessary for functionality
-               and doing this would just slow us down.  if they end up using
-               this in a later version for functional purposes, just undef
-            */
+            /*
+             * all the driver uses these are for its own stats keeping
+             * which we don't care about, aren't necessary for
+             * functionality and doing this would just slow us down.
+             * if they end up using this in a later version for
+             * functional purposes, just undef
+             */
             if (rxFilterEnable) {
                 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
-                if (rxFifo.front()->IsUnicast())
+                const EthAddr &dst = rxFifoFront()->dst();
+                if (dst->unicast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
-                if (rxFifo.front()->IsMulticast())
+                if (dst->multicast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
-                if (rxFifo.front()->IsBroadcast())
+                if (dst->broadcast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
             }
 #endif
 
-            eth_header *eth = (eth_header *) rxPacket->data;
-            // eth->type 0x800 indicated that it's an ip packet.
-            if (eth->type == 0x800 && extstsEnable) {
+            IpPtr ip(rxPacket);
+            if (extstsEnable && ip) {
                 rxDescCache.extsts |= EXTSTS_IPPKT;
-                if (!ipChecksum(rxPacket, false))
+                rxIpChecksums++;
+                if (cksum(ip) != 0) {
+                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
                     rxDescCache.extsts |= EXTSTS_IPERR;
-                ip_header *ip = rxFifo.front()->getIpHdr();
-
-                if (ip->protocol == 6) {
+                }
+                TcpPtr tcp(ip);
+                UdpPtr udp(ip);
+                if (tcp) {
                     rxDescCache.extsts |= EXTSTS_TCPPKT;
-                    if (!tcpChecksum(rxPacket, false))
+                    rxTcpChecksums++;
+                    if (cksum(tcp) != 0) {
+                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
                         rxDescCache.extsts |= EXTSTS_TCPERR;
-                } else if (ip->protocol == 17) {
+
+                    }
+                } else if (udp) {
                     rxDescCache.extsts |= EXTSTS_UDPPKT;
-                    if (!udpChecksum(rxPacket, false))
+                    rxUdpChecksums++;
+                    if (cksum(udp) != 0) {
+                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
                         rxDescCache.extsts |= EXTSTS_UDPERR;
+                    }
                 }
             }
+            rxPacket = 0;
 
-            /* the driver seems to always receive into desc buffers
-               of size 1514, so you never have a pkt that is split
-               into multiple descriptors on the receive side, so
-               i don't implement that case, hence the assert above.
-            */
+            /*
+             * the driver seems to always receive into desc buffers
+             * of size 1514, so you never have a pkt that is split
+             * into multiple descriptors on the receive side, so
+             * i don't implement that case, hence the assert above.
+             */
+
+            DPRINTF(EthernetDesc,
+                    "rxDescCache: addr=%08x writeback cmdsts extsts\n",
+                    regs.rxdp & 0x3fffffff);
+            DPRINTF(EthernetDesc,
+                    "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
+                    rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
+                    rxDescCache.extsts);
 
             rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
             rxDmaData = &(rxDescCache.cmdsts);
             rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts);
             rxDmaFree = dmaDescFree;
 
+            descDmaWrites++;
+            descDmaWrBytes += rxDmaLen;
+
             if (doRxDmaWrite())
                 goto exit;
         }
@@ -1337,17 +1741,20 @@ EtherDev::rxKick()
         if (rxDescCache.cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_RXDESC);
 
-        if (rxHalt) {
+        if (!rxEnable) {
+            DPRINTF(EthernetSM, "Halting the RX state machine\n");
             rxState = rxIdle;
-            rxHalt = false;
+            goto exit;
         } else
             rxState = rxAdvance;
         break;
 
       case rxAdvance:
         if (rxDescCache.link == 0) {
+            devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
-            return;
+            CRDD = true;
+            goto exit;
         } else {
             rxState = rxDescRead;
             regs.rxdp = rxDescCache.link;
@@ -1367,52 +1774,62 @@ EtherDev::rxKick()
         panic("Invalid rxState!");
     }
 
-
-    DPRINTF(Ethernet, "entering next rx state = %s\n",
+    DPRINTF(EthernetSM, "entering next rxState=%s\n",
             NsRxStateStrings[rxState]);
 
-    if (rxState == rxIdle) {
-        regs.command &= ~CR_RXE;
-        devIntrPost(ISR_RXIDLE);
-        return;
-    }
-
     goto next;
 
   exit:
     /**
      * @todo do we want to schedule a future kick?
      */
-    DPRINTF(Ethernet, "rx state machine exited state=%s\n",
+    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
             NsRxStateStrings[rxState]);
 }
 
 void
-EtherDev::transmit()
+NSGigE::transmit()
 {
     if (txFifo.empty()) {
         DPRINTF(Ethernet, "nothing to transmit\n");
         return;
     }
 
-   if (interface->sendPacket(txFifo.front())) {
-        DPRINTF(Ethernet, "transmit packet\n");
-        DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length);
+    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
+            txFifo.size());
+    if (interface->sendPacket(txFifo.front())) {
+#if TRACING_ON
+        if (DTRACE(Ethernet)) {
+            IpPtr ip(txFifo.front());
+            if (ip) {
+                DPRINTF(Ethernet, "ID is %d\n", ip->id());
+                TcpPtr tcp(ip);
+                if (tcp) {
+                    DPRINTF(Ethernet,
+                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+                            tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack());
+                }
+            }
+        }
+#endif
+
+        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
         txBytes += txFifo.front()->length;
         txPackets++;
 
-        txFifoCnt -= (txFifo.front()->length - txPktXmitted);
-        txPktXmitted = 0;
-        txFifo.front() = NULL;
-        txFifo.pop_front();
-
-        /* normally do a writeback of the descriptor here, and ONLY after that is
-           done, send this interrupt.  but since our stuff never actually fails,
-           just do this interrupt here, otherwise the code has to stray from this
-           nice format.  besides, it's functionally the same.
-        */
+        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
+                txFifo.avail());
+        txFifo.pop();
+
+        /*
+         * normally do a writeback of the descriptor here, and ONLY
+         * after that is done, send this interrupt.  but since our
+         * stuff never actually fails, just do this interrupt here,
+         * otherwise the code has to stray from this nice format.
+         * besides, it's functionally the same.
+         */
         devIntrPost(ISR_TXOK);
-   }
+    }
 
    if (!txFifo.empty() && !txEvent.scheduled()) {
        DPRINTF(Ethernet, "reschedule transmit\n");
@@ -1421,11 +1838,11 @@ EtherDev::transmit()
 }
 
 void
-EtherDev::txDmaReadCopy()
+NSGigE::txDmaReadCopy()
 {
     assert(txDmaState == dmaReading);
 
-    memcpy(txDmaData, physmem->dma_addr(txDmaAddr, txDmaLen), txDmaLen);
+    physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
     txDmaState = dmaIdle;
 
     DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
@@ -1434,7 +1851,7 @@ EtherDev::txDmaReadCopy()
 }
 
 bool
-EtherDev::doTxDmaRead()
+NSGigE::doTxDmaRead()
 {
     assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
     txDmaState = dmaReading;
@@ -1444,7 +1861,7 @@ EtherDev::doTxDmaRead()
             txDmaState = dmaReadWaiting;
         else
             dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick,
-                                &txDmaReadEvent);
+                                &txDmaReadEvent, true);
         return true;
     }
 
@@ -1460,7 +1877,7 @@ EtherDev::doTxDmaRead()
 }
 
 void
-EtherDev::txDmaReadDone()
+NSGigE::txDmaReadDone()
 {
     assert(txDmaState == dmaReading);
     txDmaReadCopy();
@@ -1473,11 +1890,11 @@ EtherDev::txDmaReadDone()
 }
 
 void
-EtherDev::txDmaWriteCopy()
+NSGigE::txDmaWriteCopy()
 {
     assert(txDmaState == dmaWriting);
 
-    memcpy(physmem->dma_addr(txDmaAddr, txDmaLen), txDmaData, txDmaLen);
+    physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen);
     txDmaState = dmaIdle;
 
     DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
@@ -1486,7 +1903,7 @@ EtherDev::txDmaWriteCopy()
 }
 
 bool
-EtherDev::doTxDmaWrite()
+NSGigE::doTxDmaWrite()
 {
     assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
     txDmaState = dmaWriting;
@@ -1496,7 +1913,7 @@ EtherDev::doTxDmaWrite()
             txDmaState = dmaWriteWaiting;
         else
             dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick,
-                                &txDmaWriteEvent);
+                                &txDmaWriteEvent, true);
         return true;
     }
 
@@ -1512,7 +1929,7 @@ EtherDev::doTxDmaWrite()
 }
 
 void
-EtherDev::txDmaWriteDone()
+NSGigE::txDmaWriteDone()
 {
     assert(txDmaState == dmaWriting);
     txDmaWriteCopy();
@@ -1525,13 +1942,14 @@ EtherDev::txDmaWriteDone()
 }
 
 void
-EtherDev::txKick()
+NSGigE::txKick()
 {
-    DPRINTF(Ethernet, "transmit kick state=%s\n", NsTxStateStrings[txState]);
+    DPRINTF(EthernetSM, "transmit kick txState=%s\n",
+            NsTxStateStrings[txState]);
 
-    if (rxKickTick > curTick) {
-        DPRINTF(Ethernet, "receive kick exiting, can't run till %d\n",
-                rxKickTick);
+    if (txKickTick > curTick) {
+        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
+                txKickTick);
 
         return;
     }
@@ -1552,19 +1970,22 @@ EtherDev::txKick()
 
     switch (txState) {
       case txIdle:
-        if (!regs.command & CR_TXE) {
-            DPRINTF(Ethernet, "Transmit disabled.  Nothing to do.\n");
+        if (!txEnable) {
+            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
             goto exit;
         }
 
         if (CTDD) {
             txState = txDescRefr;
 
-            txDmaAddr = txDescCache.link & 0x3fffffff;
-            txDmaData = &txDescCache;
+            txDmaAddr = regs.txdp & 0x3fffffff;
+            txDmaData = &txDescCache + offsetof(ns_desc, link);
             txDmaLen = sizeof(txDescCache.link);
             txDmaFree = dmaDescFree;
 
+            descDmaReads++;
+            descDmaRdBytes += txDmaLen;
+
             if (doTxDmaRead())
                 goto exit;
 
@@ -1572,10 +1993,13 @@ EtherDev::txKick()
             txState = txDescRead;
 
             txDmaAddr = regs.txdp & 0x3fffffff;
-            txDmaData = &txDescCache + offsetof(ns_desc, link);
+            txDmaData = &txDescCache;
             txDmaLen = sizeof(ns_desc);
             txDmaFree = dmaDescFree;
 
+            descDmaReads++;
+            descDmaRdBytes += txDmaLen;
+
             if (doTxDmaRead())
                 goto exit;
         }
@@ -1592,32 +2016,39 @@ EtherDev::txKick()
         if (txDmaState != dmaIdle)
             goto exit;
 
+        DPRINTF(EthernetDesc,
+                "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
+                txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts,
+                txDescCache.extsts);
+
         if (txDescCache.cmdsts & CMDSTS_OWN) {
             txState = txFifoBlock;
             txFragPtr = txDescCache.bufptr;
             txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK;
         } else {
+            devIntrPost(ISR_TXIDLE);
             txState = txIdle;
+            goto exit;
         }
         break;
 
       case txFifoBlock:
         if (!txPacket) {
-            DPRINTF(Ethernet, "starting the tx of a new packet\n");
-            txPacket = new EtherPacket;
-            txPacket->data = new uint8_t[16384];
+            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
+            txPacket = new PacketData(16384);
             txPacketBufPtr = txPacket->data;
         }
 
         if (txDescCnt == 0) {
-            DPRINTF(Ethernet, "the txDescCnt == 0, done with descriptor\n");
+            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
             if (txDescCache.cmdsts & CMDSTS_MORE) {
-                DPRINTF(Ethernet, "there are more descriptors to come\n");
+                DPRINTF(EthernetSM, "there are more descriptors to come\n");
                 txState = txDescWrite;
 
                 txDescCache.cmdsts &= ~CMDSTS_OWN;
 
-                txDmaAddr = (regs.txdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
+                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
+                txDmaAddr &= 0x3fffffff;
                 txDmaData = &(txDescCache.cmdsts);
                 txDmaLen = sizeof(txDescCache.cmdsts);
                 txDmaFree = dmaDescFree;
@@ -1626,79 +2057,107 @@ EtherDev::txKick()
                     goto exit;
 
             } else { /* this packet is totally done */
-                DPRINTF(Ethernet, "This packet is done, let's wrap it up\n");
+                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
                 /* deal with the the packet that just finished */
                 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
+                    IpPtr ip(txPacket);
                     if (txDescCache.extsts & EXTSTS_UDPPKT) {
-                        udpChecksum(txPacket, true);
+                        UdpPtr udp(ip);
+                        udp->sum(0);
+                        udp->sum(cksum(udp));
+                        txUdpChecksums++;
                     } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
-                        tcpChecksum(txPacket, true);
-                    } else if (txDescCache.extsts & EXTSTS_IPPKT) {
-                        ipChecksum(txPacket, true);
+                        TcpPtr tcp(ip);
+                        tcp->sum(0);
+                        tcp->sum(cksum(tcp));
+                        txTcpChecksums++;
+                    }
+                    if (txDescCache.extsts & EXTSTS_IPPKT) {
+                        ip->sum(0);
+                        ip->sum(cksum(ip));
+                        txIpChecksums++;
                     }
                 }
 
                 txPacket->length = txPacketBufPtr - txPacket->data;
-                /* this is just because the receive can't handle a packet bigger
-                   want to make sure */
+                // this is just because the receive can't handle a
+                // packet bigger want to make sure
                 assert(txPacket->length <= 1514);
-                txFifo.push_back(txPacket);
-
+#ifndef NDEBUG
+                bool success =
+#endif
+                    txFifo.push(txPacket);
+                assert(success);
+
+                /*
+                 * this following section is not tqo spec, but
+                 * functionally shouldn't be any different.  normally,
+                 * the chip will wait til the transmit has occurred
+                 * before writing back the descriptor because it has
+                 * to wait to see that it was successfully transmitted
+                 * to decide whether to set CMDSTS_OK or not.
+                 * however, in the simulator since it is always
+                 * successfully transmitted, and writing it exactly to
+                 * spec would complicate the code, we just do it here
+                 */
 
-                /* this following section is not to spec, but functionally shouldn't
-                   be any different.  normally, the chip will wait til the transmit has
-                   occurred before writing back the descriptor because it has to wait
-                   to see that it was successfully transmitted to decide whether to set
-                   CMDSTS_OK or not.  however, in the simulator since it is always
-                   successfully transmitted, and writing it exactly to spec would
-                   complicate the code, we just do it here
-                */
                 txDescCache.cmdsts &= ~CMDSTS_OWN;
                 txDescCache.cmdsts |= CMDSTS_OK;
 
-                txDmaAddr = regs.txdp & 0x3fffffff;
-                txDmaData = &txDescCache + offsetof(ns_desc, cmdsts);
-                txDmaLen = sizeof(txDescCache.cmdsts) + sizeof(txDescCache.extsts);
-                txDmaFree = dmaDescFree;
+                DPRINTF(EthernetDesc,
+                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
+                        txDescCache.cmdsts, txDescCache.extsts);
 
+                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
+                txDmaAddr &= 0x3fffffff;
+                txDmaData = &(txDescCache.cmdsts);
+                txDmaLen = sizeof(txDescCache.cmdsts) +
+                    sizeof(txDescCache.extsts);
+                txDmaFree = dmaDescFree;
 
-                if (doTxDmaWrite())
-                    goto exit;
+                descDmaWrites++;
+                descDmaWrBytes += txDmaLen;
 
-                txPacket = 0;
                 transmit();
+                txPacket = 0;
 
-                if (txHalt) {
+                if (!txEnable) {
+                    DPRINTF(EthernetSM, "halting TX state machine\n");
                     txState = txIdle;
-                    txHalt = false;
+                    goto exit;
                 } else
                     txState = txAdvance;
+
+                if (doTxDmaWrite())
+                    goto exit;
             }
         } else {
-            DPRINTF(Ethernet, "this descriptor isn't done yet\n");
-            /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
-               value, shift left by 5 to get the real number of bytes */
-            if (txFifoAvail < ((regs.txcfg & TXCFG_FLTH_MASK) >> 3)) {
-                DPRINTF(Ethernet, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
-                        txFifoAvail, regs.txcfg & TXCFG_FLTH_MASK);
+            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
+            if (!txFifo.full()) {
+                txState = txFragRead;
+
+                /*
+                 * The number of bytes transferred is either whatever
+                 * is left in the descriptor (txDescCnt), or if there
+                 * is not enough room in the fifo, just whatever room
+                 * is left in the fifo
+                 */
+                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
+
+                txDmaAddr = txFragPtr & 0x3fffffff;
+                txDmaData = txPacketBufPtr;
+                txDmaLen = txXferLen;
+                txDmaFree = dmaDataFree;
+
+                if (doTxDmaRead())
+                    goto exit;
+            } else {
+                txState = txFifoBlock;
+                transmit();
+
                 goto exit;
             }
 
-            txState = txFragRead;
-
-            /* The number of bytes transferred is either whatever is left
-               in the descriptor (txDescCnt), or if there is not enough
-               room in the fifo, just whatever room is left in the fifo
-            */
-            txXferLen = min<uint32_t>(txDescCnt, txFifoAvail);
-
-            txDmaAddr = txFragPtr & 0x3fffffff;
-            txDmaData = txPacketBufPtr;
-            txDmaLen = txXferLen;
-            txDmaFree = dmaDataFree;
-
-            if (doTxDmaRead())
-                goto exit;
         }
         break;
 
@@ -1708,8 +2167,8 @@ EtherDev::txKick()
 
         txPacketBufPtr += txXferLen;
         txFragPtr += txXferLen;
-        txFifoCnt += txXferLen;
         txDescCnt -= txXferLen;
+        txFifo.reserve(txXferLen);
 
         txState = txFifoBlock;
         break;
@@ -1718,26 +2177,17 @@ EtherDev::txKick()
         if (txDmaState != dmaIdle)
             goto exit;
 
-        if (txFifoCnt >= ((regs.txcfg & TXCFG_DRTH_MASK) << 5)) {
-            if (txFifo.empty()) {
-                uint32_t xmitted = (uint32_t) (txPacketBufPtr - txPacket->data - txPktXmitted);
-                txFifoCnt -= xmitted;
-                txPktXmitted += xmitted;
-            } else {
-                transmit();
-            }
-        }
-
-        if (txDescCache.cmdsts & CMDSTS_INTR) {
+        if (txDescCache.cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_TXDESC);
-        }
 
         txState = txAdvance;
         break;
 
       case txAdvance:
         if (txDescCache.link == 0) {
+            devIntrPost(ISR_TXIDLE);
             txState = txIdle;
+            goto exit;
         } else {
             txState = txDescRead;
             regs.txdp = txDescCache.link;
@@ -1757,32 +2207,28 @@ EtherDev::txKick()
         panic("invalid state");
     }
 
-    DPRINTF(Ethernet, "entering next tx state=%s\n",
+    DPRINTF(EthernetSM, "entering next txState=%s\n",
             NsTxStateStrings[txState]);
 
-    if (txState == txIdle) {
-        regs.command &= ~CR_TXE;
-        devIntrPost(ISR_TXIDLE);
-        return;
-    }
-
     goto next;
 
   exit:
     /**
      * @todo do we want to schedule a future kick?
      */
-    DPRINTF(Ethernet, "tx state machine exited state=%s\n",
+    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
             NsTxStateStrings[txState]);
 }
 
 void
-EtherDev::transferDone()
+NSGigE::transferDone()
 {
-    if (txFifo.empty())
+    if (txFifo.empty()) {
+        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
         return;
+    }
 
-    DPRINTF(Ethernet, "schedule transmit\n");
+    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
 
     if (txEvent.scheduled())
         txEvent.reschedule(curTick + 1);
@@ -1791,45 +2237,35 @@ EtherDev::transferDone()
 }
 
 bool
-EtherDev::rxFilter(PacketPtr packet)
+NSGigE::rxFilter(const PacketPtr &packet)
 {
+    EthPtr eth = packet;
     bool drop = true;
     string type;
 
-    if (packet->IsUnicast()) {
-        type = "unicast";
-
+    const EthAddr &dst = eth->dst();
+    if (dst.unicast()) {
         // If we're accepting all unicast addresses
         if (acceptUnicast)
             drop = false;
 
         // If we make a perfect match
-        if ((acceptPerfect)
-            && (memcmp(rom.perfectMatch, packet->data, sizeof(rom.perfectMatch)) == 0))
+        if (acceptPerfect && dst == rom.perfectMatch)
             drop = false;
 
-        eth_header *eth = (eth_header *) packet->data;
-        if ((acceptArp) && (eth->type == 0x806))
+        if (acceptArp && eth->type() == ETH_TYPE_ARP)
             drop = false;
 
-    } else if (packet->IsBroadcast()) {
-        type = "broadcast";
-
+    } else if (dst.broadcast()) {
         // if we're accepting broadcasts
         if (acceptBroadcast)
             drop = false;
 
-    } else if (packet->IsMulticast()) {
-        type = "multicast";
-
+    } else if (dst.multicast()) {
         // if we're accepting all multicasts
         if (acceptMulticast)
             drop = false;
 
-    } else {
-        type = "unknown";
-
-        // oh well, punt on this one
     }
 
     if (drop) {
@@ -1841,13 +2277,17 @@ EtherDev::rxFilter(PacketPtr packet)
 }
 
 bool
-EtherDev::recvPacket(PacketPtr packet)
+NSGigE::recvPacket(PacketPtr packet)
 {
     rxBytes += packet->length;
     rxPackets++;
 
-    if (rxState == rxIdle) {
+    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
+            rxFifo.avail());
+
+    if (!rxEnable) {
         DPRINTF(Ethernet, "receive disabled...packet dropped\n");
+        debug_break();
         interface->recvDone();
         return true;
     }
@@ -1858,128 +2298,40 @@ EtherDev::recvPacket(PacketPtr packet)
         return true;
     }
 
-    if (rxFifoCnt + packet->length >= MAX_RX_FIFO_SIZE) {
-        DPRINTF(Ethernet,
-                "packet will not fit in receive buffer...packet dropped\n");
+    if (rxFifo.avail() < packet->length) {
+#if TRACING_ON
+        IpPtr ip(packet);
+        TcpPtr tcp(ip);
+        if (ip) {
+            DPRINTF(Ethernet,
+                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
+                    ip->id());
+            if (tcp) {
+                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
+            }
+        }
+#endif
+        droppedPackets++;
         devIntrPost(ISR_RXORN);
         return false;
     }
 
-    rxFifo.push_back(packet);
-    rxFifoCnt += packet->length;
+    rxFifo.push(packet);
     interface->recvDone();
 
     rxKick();
     return true;
 }
 
-/**
- * does a udp checksum.  if gen is true, then it generates it and puts it in the right place
- * else, it just checks what it calculates against the value in the header in packet
- */
-bool
-EtherDev::udpChecksum(PacketPtr packet, bool gen)
-{
-    udp_header *hdr = (udp_header *)  packet->getTransportHdr();
-
-    ip_header *ip = packet->getIpHdr();
-
-    pseudo_header *pseudo = new pseudo_header;
-
-    pseudo->src_ip_addr = ip->src_ip_addr;
-    pseudo->dest_ip_addr = ip->dest_ip_addr;
-    pseudo->protocol = ip->protocol;
-    pseudo->len = hdr->len;
-
-    uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
-                                  (uint32_t) hdr->len);
-
-    delete pseudo;
-    if (gen)
-        hdr->chksum = cksum;
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-bool
-EtherDev::tcpChecksum(PacketPtr packet, bool gen)
-{
-    tcp_header *hdr = (tcp_header *) packet->getTransportHdr();
-
-    ip_header *ip = packet->getIpHdr();
-
-    pseudo_header *pseudo = new pseudo_header;
-
-    pseudo->src_ip_addr = ip->src_ip_addr;
-    pseudo->dest_ip_addr = ip->dest_ip_addr;
-    pseudo->protocol = ip->protocol;
-    pseudo->len = ip->dgram_len - (ip->vers_len & 0xf);
-
-    uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
-                                  (uint32_t) pseudo->len);
-
-    delete pseudo;
-    if (gen)
-        hdr->chksum = cksum;
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-bool
-EtherDev::ipChecksum(PacketPtr packet, bool gen)
-{
-    ip_header *hdr = packet->getIpHdr();
-
-    uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, (hdr->vers_len & 0xf));
-
-    if (gen)
-        hdr->hdr_chksum = cksum;
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-uint16_t
-EtherDev::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
-{
-    uint32_t sum = 0;
-
-    uint16_t last_pad = 0;
-    if (len & 1) {
-        last_pad = buf[len/2] & 0xff;
-        len--;
-        sum += last_pad;
-    }
-
-    if (pseudo) {
-        sum = pseudo[0] + pseudo[1] + pseudo[2] +
-            pseudo[3] + pseudo[4] + pseudo[5];
-    }
-
-    for (int i=0; i < (len/2); ++i) {
-        sum += buf[i];
-    }
-
-    while (sum >> 16)
-        sum = (sum >> 16) + (sum & 0xffff);
-
-    return ~sum;
-}
-
 //=====================================================================
 //
 //
 void
-EtherDev::serialize(ostream &os)
+NSGigE::serialize(ostream &os)
 {
+    // Serialize the PciDev base class
+    PciDev::serialize(os);
+
     /*
      * Finalize any DMA events now.
      */
@@ -2028,23 +2380,38 @@ EtherDev::serialize(ostream &os)
     SERIALIZE_SCALAR(regs.taner);
     SERIALIZE_SCALAR(regs.tesr);
 
-    SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
+
+    SERIALIZE_SCALAR(ioEnable);
 
     /*
-     * Serialize the various helper variables
+     * Serialize the data Fifos
      */
-    uint32_t txPktBufPtr = (uint32_t) txPacketBufPtr;
-    SERIALIZE_SCALAR(txPktBufPtr);
-    uint32_t rxPktBufPtr = (uint32_t) rxPktBufPtr;
-    SERIALIZE_SCALAR(rxPktBufPtr);
-    SERIALIZE_SCALAR(txXferLen);
-    SERIALIZE_SCALAR(rxXferLen);
-    SERIALIZE_SCALAR(txPktXmitted);
+    rxFifo.serialize("rxFifo", os);
+    txFifo.serialize("txFifo", os);
 
+    /*
+     * Serialize the various helper variables
+     */
     bool txPacketExists = txPacket;
     SERIALIZE_SCALAR(txPacketExists);
+    if (txPacketExists) {
+        txPacket->length = txPacketBufPtr - txPacket->data;
+        txPacket->serialize("txPacket", os);
+        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
+        SERIALIZE_SCALAR(txPktBufPtr);
+    }
+
     bool rxPacketExists = rxPacket;
     SERIALIZE_SCALAR(rxPacketExists);
+    if (rxPacketExists) {
+        rxPacket->serialize("rxPacket", os);
+        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
+        SERIALIZE_SCALAR(rxPktBufPtr);
+    }
+
+    SERIALIZE_SCALAR(txXferLen);
+    SERIALIZE_SCALAR(rxXferLen);
 
     /*
      * Serialize DescCaches
@@ -2061,14 +2428,10 @@ EtherDev::serialize(ostream &os)
     /*
      * Serialize tx state machine
      */
-    int txNumPkts = txFifo.size();
-    SERIALIZE_SCALAR(txNumPkts);
     int txState = this->txState;
     SERIALIZE_SCALAR(txState);
+    SERIALIZE_SCALAR(txEnable);
     SERIALIZE_SCALAR(CTDD);
-    SERIALIZE_SCALAR(txFifoCnt);
-    SERIALIZE_SCALAR(txFifoAvail);
-    SERIALIZE_SCALAR(txHalt);
     SERIALIZE_SCALAR(txFragPtr);
     SERIALIZE_SCALAR(txDescCnt);
     int txDmaState = this->txDmaState;
@@ -2077,27 +2440,35 @@ EtherDev::serialize(ostream &os)
     /*
      * Serialize rx state machine
      */
-    int rxNumPkts = rxFifo.size();
-    SERIALIZE_SCALAR(rxNumPkts);
     int rxState = this->rxState;
     SERIALIZE_SCALAR(rxState);
+    SERIALIZE_SCALAR(rxEnable);
     SERIALIZE_SCALAR(CRDD);
     SERIALIZE_SCALAR(rxPktBytes);
-    SERIALIZE_SCALAR(rxFifoCnt);
-    SERIALIZE_SCALAR(rxHalt);
+    SERIALIZE_SCALAR(rxFragPtr);
     SERIALIZE_SCALAR(rxDescCnt);
     int rxDmaState = this->rxDmaState;
     SERIALIZE_SCALAR(rxDmaState);
 
     SERIALIZE_SCALAR(extstsEnable);
 
-   /*
+    /*
      * If there's a pending transmit, store the time so we can
      * reschedule it later
      */
     Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
     SERIALIZE_SCALAR(transmitTick);
 
+    /*
+     * receive address filter settings
+     */
+    SERIALIZE_SCALAR(rxFilterEnable);
+    SERIALIZE_SCALAR(acceptBroadcast);
+    SERIALIZE_SCALAR(acceptMulticast);
+    SERIALIZE_SCALAR(acceptUnicast);
+    SERIALIZE_SCALAR(acceptPerfect);
+    SERIALIZE_SCALAR(acceptArp);
+
     /*
      * Keep track of pending interrupt status.
      */
@@ -2108,29 +2479,14 @@ EtherDev::serialize(ostream &os)
         intrEventTick = intrEvent->when();
     SERIALIZE_SCALAR(intrEventTick);
 
-    int i = 0;
-    for (pktiter_t p = rxFifo.begin(); p != rxFifo.end(); ++p) {
-        nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
-        (*p)->serialize(os);
-    }
-    if (rxPacketExists) {
-        nameOut(os, csprintf("%s.rxPacket", name()));
-        rxPacket->serialize(os);
-    }
-    i = 0;
-    for (pktiter_t p = txFifo.begin(); p != txFifo.end(); ++p) {
-        nameOut(os, csprintf("%s.txFifo%d", name(), i++));
-        (*p)->serialize(os);
-    }
-    if (txPacketExists) {
-        nameOut(os, csprintf("%s.txPacket", name()));
-        txPacket->serialize(os);
-    }
 }
 
 void
-EtherDev::unserialize(Checkpoint *cp, const std::string &section)
+NSGigE::unserialize(Checkpoint *cp, const std::string &section)
 {
+    // Unserialize the PciDev base class
+    PciDev::unserialize(cp, section);
+
     UNSERIALIZE_SCALAR(regs.command);
     UNSERIALIZE_SCALAR(regs.config);
     UNSERIALIZE_SCALAR(regs.mear);
@@ -2164,25 +2520,44 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(regs.taner);
     UNSERIALIZE_SCALAR(regs.tesr);
 
-    UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
+
+    UNSERIALIZE_SCALAR(ioEnable);
 
     /*
-     * unserialize the various helper variables
+     * unserialize the data fifos
      */
-    uint32_t txPktBufPtr;
-    UNSERIALIZE_SCALAR(txPktBufPtr);
-    txPacketBufPtr = (uint8_t *) txPktBufPtr;
-    uint32_t rxPktBufPtr;
-    UNSERIALIZE_SCALAR(rxPktBufPtr);
-    rxPacketBufPtr = (uint8_t *) rxPktBufPtr;
-    UNSERIALIZE_SCALAR(txXferLen);
-    UNSERIALIZE_SCALAR(rxXferLen);
-    UNSERIALIZE_SCALAR(txPktXmitted);
+    rxFifo.unserialize("rxFifo", cp, section);
+    txFifo.unserialize("txFifo", cp, section);
 
+    /*
+     * unserialize the various helper variables
+     */
     bool txPacketExists;
     UNSERIALIZE_SCALAR(txPacketExists);
+    if (txPacketExists) {
+        txPacket = new PacketData(16384);
+        txPacket->unserialize("txPacket", cp, section);
+        uint32_t txPktBufPtr;
+        UNSERIALIZE_SCALAR(txPktBufPtr);
+        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
+    } else
+        txPacket = 0;
+
     bool rxPacketExists;
     UNSERIALIZE_SCALAR(rxPacketExists);
+    rxPacket = 0;
+    if (rxPacketExists) {
+        rxPacket = new PacketData(16384);
+        rxPacket->unserialize("rxPacket", cp, section);
+        uint32_t rxPktBufPtr;
+        UNSERIALIZE_SCALAR(rxPktBufPtr);
+        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
+    } else
+        rxPacket = 0;
+
+    UNSERIALIZE_SCALAR(txXferLen);
+    UNSERIALIZE_SCALAR(rxXferLen);
 
     /*
      * Unserialize DescCaches
@@ -2199,15 +2574,11 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
     /*
      * unserialize tx state machine
      */
-    int txNumPkts;
-    UNSERIALIZE_SCALAR(txNumPkts);
     int txState;
     UNSERIALIZE_SCALAR(txState);
     this->txState = (TxState) txState;
+    UNSERIALIZE_SCALAR(txEnable);
     UNSERIALIZE_SCALAR(CTDD);
-    UNSERIALIZE_SCALAR(txFifoCnt);
-    UNSERIALIZE_SCALAR(txFifoAvail);
-    UNSERIALIZE_SCALAR(txHalt);
     UNSERIALIZE_SCALAR(txFragPtr);
     UNSERIALIZE_SCALAR(txDescCnt);
     int txDmaState;
@@ -2217,15 +2588,13 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
     /*
      * unserialize rx state machine
      */
-    int rxNumPkts;
-    UNSERIALIZE_SCALAR(rxNumPkts);
     int rxState;
     UNSERIALIZE_SCALAR(rxState);
     this->rxState = (RxState) rxState;
+    UNSERIALIZE_SCALAR(rxEnable);
     UNSERIALIZE_SCALAR(CRDD);
     UNSERIALIZE_SCALAR(rxPktBytes);
-    UNSERIALIZE_SCALAR(rxFifoCnt);
-    UNSERIALIZE_SCALAR(rxHalt);
+    UNSERIALIZE_SCALAR(rxFragPtr);
     UNSERIALIZE_SCALAR(rxDescCnt);
     int rxDmaState;
     UNSERIALIZE_SCALAR(rxDmaState);
@@ -2234,14 +2603,23 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(extstsEnable);
 
      /*
-     * If there's a pending transmit, store the time so we can
-     * reschedule it later
+     * If there's a pending transmit, reschedule it now
      */
     Tick transmitTick;
     UNSERIALIZE_SCALAR(transmitTick);
     if (transmitTick)
         txEvent.schedule(curTick + transmitTick);
 
+    /*
+     * unserialize receive address filter settings
+     */
+    UNSERIALIZE_SCALAR(rxFilterEnable);
+    UNSERIALIZE_SCALAR(acceptBroadcast);
+    UNSERIALIZE_SCALAR(acceptMulticast);
+    UNSERIALIZE_SCALAR(acceptUnicast);
+    UNSERIALIZE_SCALAR(acceptPerfect);
+    UNSERIALIZE_SCALAR(acceptArp);
+
     /*
      * Keep track of pending interrupt status.
      */
@@ -2254,55 +2632,40 @@ EtherDev::unserialize(Checkpoint *cp, const std::string &section)
         intrEvent->schedule(intrEventTick);
     }
 
-    for (int i = 0; i < rxNumPkts; ++i) {
-        PacketPtr p = new EtherPacket;
-        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
-        rxFifo.push_back(p);
-    }
-    rxPacket = NULL;
-    if (rxPacketExists) {
-        rxPacket = new EtherPacket;
-        rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
-    }
-    for (int i = 0; i < txNumPkts; ++i) {
-        PacketPtr p = new EtherPacket;
-        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
-        txFifo.push_back(p);
-    }
-    if (txPacketExists) {
-        txPacket = new EtherPacket;
-        txPacket->unserialize(cp, csprintf("%s.txPacket", section));
+    /*
+     * re-add addrRanges to bus bridges
+     */
+    if (pioInterface) {
+        pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+        pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
     }
 }
 
-
 Tick
-EtherDev::cacheAccess(MemReqPtr &req)
+NSGigE::cacheAccess(MemReqPtr &req)
 {
     DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
             req->paddr, req->paddr - addr);
     return curTick + pioLatency;
 }
-//=====================================================================
 
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
 
     SimObjectParam<EtherInt *> peer;
-    SimObjectParam<EtherDev *> device;
+    SimObjectParam<NSGigE *> device;
 
-END_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt)
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
 
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDevInt)
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
 
     INIT_PARAM_DFLT(peer, "peer interface", NULL),
     INIT_PARAM(device, "Ethernet device of this interface")
 
-END_INIT_SIM_OBJECT_PARAMS(EtherDevInt)
+END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
 
-CREATE_SIM_OBJECT(EtherDevInt)
+CREATE_SIM_OBJECT(NSGigEInt)
 {
-    EtherDevInt *dev_int = new EtherDevInt(getInstanceName(), device);
+    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
 
     EtherInt *p = (EtherInt *)peer;
     if (p) {
@@ -2313,21 +2676,20 @@ CREATE_SIM_OBJECT(EtherDevInt)
     return dev_int;
 }
 
-REGISTER_SIM_OBJECT("EtherDevInt", EtherDevInt)
+REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
 
 
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
 
+    Param<Addr> addr;
     Param<Tick> tx_delay;
     Param<Tick> rx_delay;
-    SimObjectParam<IntrControl *> intr_ctrl;
     Param<Tick> intr_delay;
     SimObjectParam<MemoryController *> mmu;
     SimObjectParam<PhysicalMemory *> physmem;
-    Param<Addr> addr;
     Param<bool> rx_filter;
     Param<string> hardware_address;
-    SimObjectParam<Bus*> header_bus;
+    SimObjectParam<Bus*> io_bus;
     SimObjectParam<Bus*> payload_bus;
     SimObjectParam<HierParams *> hier;
     Param<Tick> pio_latency;
@@ -2339,29 +2701,30 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
     Param<Tick> dma_write_factor;
     SimObjectParam<PciConfigAll *> configspace;
     SimObjectParam<PciConfigData *> configdata;
-    SimObjectParam<Tsunami *> tsunami;
+    SimObjectParam<Platform *> platform;
     Param<uint32_t> pci_bus;
     Param<uint32_t> pci_dev;
     Param<uint32_t> pci_func;
+    Param<uint32_t> tx_fifo_size;
+    Param<uint32_t> rx_fifo_size;
 
-END_DECLARE_SIM_OBJECT_PARAMS(EtherDev)
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
 
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev)
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
 
+    INIT_PARAM(addr, "Device Address"),
     INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
     INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
-    INIT_PARAM(intr_ctrl, "Interrupt Controller"),
     INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
     INIT_PARAM(mmu, "Memory Controller"),
     INIT_PARAM(physmem, "Physical Memory"),
-    INIT_PARAM(addr, "Device Address"),
     INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
     INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
                     "00:99:00:00:00:01"),
-    INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
+    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL),
     INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
     INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
-    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
+    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
     INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false),
     INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false),
     INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
@@ -2370,27 +2733,48 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev)
     INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
     INIT_PARAM(configspace, "PCI Configspace"),
     INIT_PARAM(configdata, "PCI Config data"),
-    INIT_PARAM(tsunami, "Tsunami"),
+    INIT_PARAM(platform, "Platform"),
     INIT_PARAM(pci_bus, "PCI bus"),
     INIT_PARAM(pci_dev, "PCI device number"),
-    INIT_PARAM(pci_func, "PCI function code")
+    INIT_PARAM(pci_func, "PCI function code"),
+    INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072),
+    INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072)
 
-END_INIT_SIM_OBJECT_PARAMS(EtherDev)
+END_INIT_SIM_OBJECT_PARAMS(NSGigE)
 
 
-CREATE_SIM_OBJECT(EtherDev)
+CREATE_SIM_OBJECT(NSGigE)
 {
-    int eaddr[6];
-    sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
-           &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
-
-    return new EtherDev(getInstanceName(), intr_ctrl, intr_delay,
-                        physmem, tx_delay, rx_delay, mmu, hier, header_bus,
-                        payload_bus, pio_latency, dma_desc_free, dma_data_free,
-                        dma_read_delay, dma_write_delay, dma_read_factor,
-                        dma_write_factor, configspace, configdata,
-                        tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr,
-                        addr);
+    NSGigE::Params *params = new NSGigE::Params;
+
+    params->name = getInstanceName();
+    params->mmu = mmu;
+    params->configSpace = configspace;
+    params->configData = configdata;
+    params->plat = platform;
+    params->busNum = pci_bus;
+    params->deviceNum = pci_dev;
+    params->functionNum = pci_func;
+
+    params->intr_delay = intr_delay;
+    params->pmem = physmem;
+    params->tx_delay = tx_delay;
+    params->rx_delay = rx_delay;
+    params->hier = hier;
+    params->header_bus = io_bus;
+    params->payload_bus = payload_bus;
+    params->pio_latency = pio_latency;
+    params->dma_desc_free = dma_desc_free;
+    params->dma_data_free = dma_data_free;
+    params->dma_read_delay = dma_read_delay;
+    params->dma_write_delay = dma_write_delay;
+    params->dma_read_factor = dma_read_factor;
+    params->dma_write_factor = dma_write_factor;
+    params->rx_filter = rx_filter;
+    params->eaddr = hardware_address;
+    params->tx_fifo_size = tx_fifo_size;
+    params->rx_fifo_size = rx_fifo_size;
+    return new NSGigE(params);
 }
 
-REGISTER_SIM_OBJECT("EtherDev", EtherDev)
+REGISTER_SIM_OBJECT("NSGigE", NSGigE)