Get rid of the xc from the alphaAccess/alphaConsole backdoor device.
[gem5.git] / dev / ns_gige.cc
index 47cd4d7da15cf2c2817918d16cc1311de9669e02..9010850ab8a67cc1e09c497d768cbf1540cc0022 100644 (file)
@@ -109,13 +109,14 @@ NSGigE::NSGigE(Params *p)
       physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
       intrEvent(0), interface(0)
 {
-    if (p->header_bus) {
+    if (p->pio_bus) {
         pioInterface = newPioInterface(name() + ".pio", p->hier,
-                                       p->header_bus, this,
+                                       p->pio_bus, this,
                                        &NSGigE::cacheAccess);
+        pioLatency = p->pio_latency * p->pio_bus->clockRate;
+    }
 
-        pioLatency = p->pio_latency * p->header_bus->clockRate;
-
+    if (p->header_bus) {
         if (p->payload_bus)
             dmaInterface = new DMAInterface<Bus>(name() + ".dma",
                                                  p->header_bus,
@@ -126,19 +127,10 @@ NSGigE::NSGigE(Params *p)
                                                  p->header_bus,
                                                  p->header_bus, 1,
                                                  p->dma_no_allocate);
-    } else if (p->payload_bus) {
-        pioInterface = newPioInterface(name() + ".pio2", p->hier,
-                                       p->payload_bus, this,
-                                       &NSGigE::cacheAccess);
-
-        pioLatency = p->pio_latency * p->payload_bus->clockRate;
-
-        dmaInterface = new DMAInterface<Bus>(name() + ".dma",
-                                             p->payload_bus,
-                                             p->payload_bus, 1,
-                                             p->dma_no_allocate);
-    }
+    } else if (p->payload_bus)
+        panic("Must define a header bus if defining a payload bus");
 
+    pioDelayWrite = p->pio_delay_write && pioInterface;
 
     intrDelay = p->intr_delay;
     dmaReadDelay = p->dma_read_delay;
@@ -148,6 +140,11 @@ NSGigE::NSGigE(Params *p)
 
     regsReset();
     memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
+
+    memset(&rxDesc32, 0, sizeof(rxDesc32));
+    memset(&txDesc32, 0, sizeof(txDesc32));
+    memset(&rxDesc64, 0, sizeof(rxDesc64));
+    memset(&txDesc64, 0, sizeof(txDesc64));
 }
 
 NSGigE::~NSGigE()
@@ -310,7 +307,7 @@ NSGigE::regStats()
 
     totalSwi
         .name(name() + ".totalSwi")
-        .desc("number of total Swi written to ISR")
+        .desc("total number of Swi written to ISR")
         .precision(0)
         ;
 
@@ -328,7 +325,7 @@ NSGigE::regStats()
 
     totalRxIdle
         .name(name() + ".totalRxIdle")
-        .desc("number of total RxIdle written to ISR")
+        .desc("total number of RxIdle written to ISR")
         .precision(0)
         ;
 
@@ -346,7 +343,7 @@ NSGigE::regStats()
 
     totalRxOk
         .name(name() + ".totalRxOk")
-        .desc("number of total RxOk written to ISR")
+        .desc("total number of RxOk written to ISR")
         .precision(0)
         ;
 
@@ -364,7 +361,7 @@ NSGigE::regStats()
 
     totalRxDesc
         .name(name() + ".totalRxDesc")
-        .desc("number of total RxDesc written to ISR")
+        .desc("total number of RxDesc written to ISR")
         .precision(0)
         ;
 
@@ -382,7 +379,7 @@ NSGigE::regStats()
 
     totalTxOk
         .name(name() + ".totalTxOk")
-        .desc("number of total TxOk written to ISR")
+        .desc("total number of TxOk written to ISR")
         .precision(0)
         ;
 
@@ -400,7 +397,7 @@ NSGigE::regStats()
 
     totalTxIdle
         .name(name() + ".totalTxIdle")
-        .desc("number of total TxIdle written to ISR")
+        .desc("total number of TxIdle written to ISR")
         .precision(0)
         ;
 
@@ -418,7 +415,7 @@ NSGigE::regStats()
 
     totalTxDesc
         .name(name() + ".totalTxDesc")
-        .desc("number of total TxDesc written to ISR")
+        .desc("total number of TxDesc written to ISR")
         .precision(0)
         ;
 
@@ -436,7 +433,7 @@ NSGigE::regStats()
 
     totalRxOrn
         .name(name() + ".totalRxOrn")
-        .desc("number of total RxOrn written to ISR")
+        .desc("total number of RxOrn written to ISR")
         .precision(0)
         ;
 
@@ -766,7 +763,11 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
                 break;
 
               case M5REG:
-                reg = params()->m5reg;
+                reg = 0;
+                if (params()->rx_thread)
+                    reg |= M5REG_RX_THREAD;
+                if (params()->tx_thread)
+                    reg |= M5REG_TX_THREAD;
                 break;
 
               default:
@@ -803,6 +804,13 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
     } else if (daddr > 0x3FC)
         panic("Something is messed up!\n");
 
+    if (pioDelayWrite) {
+        int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+        if (cpu >= writeQueue.size())
+            writeQueue.resize(cpu + 1);
+        writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data));
+    }
+
     if (req->size == sizeof(uint32_t)) {
         uint32_t reg = *(uint32_t *)data;
         uint16_t rfaddr;
@@ -815,20 +823,24 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
             if (reg & CR_TXD) {
                 txEnable = false;
             } else if (reg & CR_TXE) {
-                txEnable = true;
+                if (!pioDelayWrite) {
+                    txEnable = true;
 
-                // the kernel is enabling the transmit machine
-                if (txState == txIdle)
-                    txKick();
+                    // the kernel is enabling the transmit machine
+                    if (txState == txIdle)
+                        txKick();
+                }
             }
 
             if (reg & CR_RXD) {
                 rxEnable = false;
             } else if (reg & CR_RXE) {
-                rxEnable = true;
+                if (!pioDelayWrite) {
+                    rxEnable = true;
 
-                if (rxState == rxIdle)
-                    rxKick();
+                    if (rxState == rxIdle)
+                        rxKick();
+                }
             }
 
             if (reg & CR_TXR)
@@ -868,15 +880,12 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
 // 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 & CFGR_TBI_EN) ;
             if (reg & CFGR_MODE_1000) ;
-#endif
 
             if (reg & CFGR_AUTO_1000)
                 panic("CFGR_AUTO_1000 not implemented!\n");
 
-#if 0
             if (reg & CFGR_PINT_DUPSTS ||
                 reg & CFGR_PINT_LNKSTS ||
                 reg & CFGR_PINT_SPDSTS)
@@ -886,8 +895,8 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
             if (reg & CFGR_MRM_DIS) ;
             if (reg & CFGR_MWI_DIS) ;
 
-            if (reg & CFGR_T64ADDR)
-                panic("CFGR_T64ADDR is read only register!\n");
+            if (reg & CFGR_T64ADDR) ;
+            // panic("CFGR_T64ADDR is read only register!\n");
 
             if (reg & CFGR_PCI64_DET)
                 panic("CFGR_PCI64_DET is read only register!\n");
@@ -896,23 +905,20 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
             if (reg & CFGR_M64ADDR) ;
             if (reg & CFGR_PHY_RST) ;
             if (reg & CFGR_PHY_DIS) ;
-#endif
 
             if (reg & CFGR_EXTSTS_EN)
                 extstsEnable = true;
             else
                 extstsEnable = false;
 
-#if 0
-              if (reg & CFGR_REQALG) ;
-              if (reg & CFGR_SB) ;
-              if (reg & CFGR_POW) ;
-              if (reg & CFGR_EXD) ;
-              if (reg & CFGR_PESEL) ;
-              if (reg & CFGR_BROM_DIS) ;
-              if (reg & CFGR_EXT_125) ;
-              if (reg & CFGR_BEM) ;
-#endif
+            if (reg & CFGR_REQALG) ;
+            if (reg & CFGR_SB) ;
+            if (reg & CFGR_POW) ;
+            if (reg & CFGR_EXD) ;
+            if (reg & CFGR_PESEL) ;
+            if (reg & CFGR_BROM_DIS) ;
+            if (reg & CFGR_EXT_125) ;
+            if (reg & CFGR_BEM) ;
             break;
 
           case MEAR:
@@ -936,11 +942,9 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
             eepromClk = reg & MEAR_EECLK;
 
             // since phy is completely faked, MEAR_MD* don't matter
-#if 0
             if (reg & MEAR_MDIO) ;
             if (reg & MEAR_MDDIR) ;
             if (reg & MEAR_MDC) ;
-#endif
             break;
 
           case PTSCR:
@@ -1556,8 +1560,15 @@ NSGigE::rxDmaWriteDone()
 void
 NSGigE::rxKick()
 {
-    DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n",
-            NsRxStateStrings[rxState], rxFifo.size());
+    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
+
+    DPRINTF(EthernetSM,
+            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
+            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
+
+    Addr link, bufptr;
+    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
+    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
 
   next:
     if (clock) {
@@ -1585,6 +1596,9 @@ NSGigE::rxKick()
         break;
     }
 
+    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
+    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
+
     // 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
@@ -1603,8 +1617,9 @@ NSGigE::rxKick()
             rxState = rxDescRefr;
 
             rxDmaAddr = regs.rxdp & 0x3fffffff;
-            rxDmaData = &rxDescCache + offsetof(ns_desc, link);
-            rxDmaLen = sizeof(rxDescCache.link);
+            rxDmaData =
+                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
+            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
             rxDmaFree = dmaDescFree;
 
             descDmaReads++;
@@ -1616,8 +1631,8 @@ NSGigE::rxKick()
             rxState = rxDescRead;
 
             rxDmaAddr = regs.rxdp & 0x3fffffff;
-            rxDmaData = &rxDescCache;
-            rxDmaLen = sizeof(ns_desc);
+            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
+            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
             rxDmaFree = dmaDescFree;
 
             descDmaReads++;
@@ -1639,21 +1654,20 @@ NSGigE::rxKick()
         if (rxDmaState != dmaIdle)
             goto exit;
 
-        DPRINTF(EthernetDesc, "rxDescCache: addr=%08x read descriptor\n",
+        DPRINTF(EthernetDesc, "rxDesc: 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);
+                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
+                link, bufptr, cmdsts, extsts);
 
-        if (rxDescCache.cmdsts & CMDSTS_OWN) {
+        if (cmdsts & CMDSTS_OWN) {
             devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
             goto exit;
         } else {
             rxState = rxFifoBlock;
-            rxFragPtr = rxDescCache.bufptr;
-            rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK;
+            rxFragPtr = bufptr;
+            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
         }
         break;
 
@@ -1719,11 +1733,11 @@ NSGigE::rxKick()
             assert(rxPktBytes == 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
+            cmdsts |= CMDSTS_OWN;
+            cmdsts &= ~CMDSTS_MORE;
+            cmdsts |= CMDSTS_OK;
+            cmdsts &= 0xffff0000;
+            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
 
 #if 0
             /*
@@ -1734,41 +1748,41 @@ NSGigE::rxKick()
              * functional purposes, just undef
              */
             if (rxFilterEnable) {
-                rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
+                cmdsts &= ~CMDSTS_DEST_MASK;
                 const EthAddr &dst = rxFifoFront()->dst();
                 if (dst->unicast())
-                    rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
+                    cmdsts |= CMDSTS_DEST_SELF;
                 if (dst->multicast())
-                    rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
+                    cmdsts |= CMDSTS_DEST_MULTI;
                 if (dst->broadcast())
-                    rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
+                    cmdsts |= CMDSTS_DEST_MASK;
             }
 #endif
 
             IpPtr ip(rxPacket);
             if (extstsEnable && ip) {
-                rxDescCache.extsts |= EXTSTS_IPPKT;
+                extsts |= EXTSTS_IPPKT;
                 rxIpChecksums++;
                 if (cksum(ip) != 0) {
                     DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
-                    rxDescCache.extsts |= EXTSTS_IPERR;
+                    extsts |= EXTSTS_IPERR;
                 }
                 TcpPtr tcp(ip);
                 UdpPtr udp(ip);
                 if (tcp) {
-                    rxDescCache.extsts |= EXTSTS_TCPPKT;
+                    extsts |= EXTSTS_TCPPKT;
                     rxTcpChecksums++;
                     if (cksum(tcp) != 0) {
                         DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
-                        rxDescCache.extsts |= EXTSTS_TCPERR;
+                        extsts |= EXTSTS_TCPERR;
 
                     }
                 } else if (udp) {
-                    rxDescCache.extsts |= EXTSTS_UDPPKT;
+                    extsts |= EXTSTS_UDPPKT;
                     rxUdpChecksums++;
                     if (cksum(udp) != 0) {
                         DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
-                        rxDescCache.extsts |= EXTSTS_UDPERR;
+                        extsts |= EXTSTS_UDPERR;
                     }
                 }
             }
@@ -1782,16 +1796,21 @@ NSGigE::rxKick()
              */
 
             DPRINTF(EthernetDesc,
-                    "rxDescCache: addr=%08x writeback cmdsts extsts\n",
+                    "rxDesc: 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);
+                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
+                    link, bufptr, cmdsts, extsts);
 
-            rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
-            rxDmaData = &(rxDescCache.cmdsts);
-            rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts);
+            rxDmaAddr = regs.rxdp & 0x3fffffff;
+            rxDmaData = &cmdsts;
+            if (is64bit) {
+                rxDmaAddr += offsetof(ns_desc64, cmdsts);
+                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
+            } else {
+                rxDmaAddr += offsetof(ns_desc32, cmdsts);
+                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
+            }
             rxDmaFree = dmaDescFree;
 
             descDmaWrites++;
@@ -1817,12 +1836,12 @@ NSGigE::rxKick()
         if (rxDmaState != dmaIdle)
             goto exit;
 
-        assert(rxDescCache.cmdsts & CMDSTS_OWN);
+        assert(cmdsts & CMDSTS_OWN);
 
         assert(rxPacket == 0);
         devIntrPost(ISR_RXOK);
 
-        if (rxDescCache.cmdsts & CMDSTS_INTR)
+        if (cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_RXDESC);
 
         if (!rxEnable) {
@@ -1834,7 +1853,7 @@ NSGigE::rxKick()
         break;
 
       case rxAdvance:
-        if (rxDescCache.link == 0) {
+        if (link == 0) {
             devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
             CRDD = true;
@@ -1843,12 +1862,12 @@ NSGigE::rxKick()
             if (rxDmaState != dmaIdle)
                 goto exit;
             rxState = rxDescRead;
-            regs.rxdp = rxDescCache.link;
+            regs.rxdp = link;
             CRDD = false;
 
             rxDmaAddr = regs.rxdp & 0x3fffffff;
-            rxDmaData = &rxDescCache;
-            rxDmaLen = sizeof(ns_desc);
+            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
+            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
             rxDmaFree = dmaDescFree;
 
             if (doRxDmaRead())
@@ -1895,7 +1914,8 @@ NSGigE::transmit()
                 if (tcp) {
                     DPRINTF(Ethernet,
                             "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
-                            tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack());
+                            tcp->sport(), tcp->dport(), tcp->seq(),
+                            tcp->ack());
                 }
             }
         }
@@ -2032,8 +2052,14 @@ NSGigE::txDmaWriteDone()
 void
 NSGigE::txKick()
 {
-    DPRINTF(EthernetSM, "transmit kick txState=%s\n",
-            NsTxStateStrings[txState]);
+    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
+
+    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
+            NsTxStateStrings[txState], is64bit ? 64 : 32);
+
+    Addr link, bufptr;
+    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
+    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
 
   next:
     if (clock) {
@@ -2060,6 +2086,8 @@ NSGigE::txKick()
         break;
     }
 
+    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
+    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
     switch (txState) {
       case txIdle:
         if (!txEnable) {
@@ -2071,8 +2099,9 @@ NSGigE::txKick()
             txState = txDescRefr;
 
             txDmaAddr = regs.txdp & 0x3fffffff;
-            txDmaData = &txDescCache + offsetof(ns_desc, link);
-            txDmaLen = sizeof(txDescCache.link);
+            txDmaData =
+                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
+            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
             txDmaFree = dmaDescFree;
 
             descDmaReads++;
@@ -2085,8 +2114,8 @@ NSGigE::txKick()
             txState = txDescRead;
 
             txDmaAddr = regs.txdp & 0x3fffffff;
-            txDmaData = &txDescCache;
-            txDmaLen = sizeof(ns_desc);
+            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
+            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
             txDmaFree = dmaDescFree;
 
             descDmaReads++;
@@ -2108,17 +2137,16 @@ NSGigE::txKick()
         if (txDmaState != dmaIdle)
             goto exit;
 
-        DPRINTF(EthernetDesc, "txDescCache: addr=%08x read descriptor\n",
+        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
                 regs.txdp & 0x3fffffff);
         DPRINTF(EthernetDesc,
-                "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
-                txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts,
-                txDescCache.extsts);
+                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
+                link, bufptr, cmdsts, extsts);
 
-        if (txDescCache.cmdsts & CMDSTS_OWN) {
+        if (cmdsts & CMDSTS_OWN) {
             txState = txFifoBlock;
-            txFragPtr = txDescCache.bufptr;
-            txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK;
+            txFragPtr = bufptr;
+            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
         } else {
             devIntrPost(ISR_TXIDLE);
             txState = txIdle;
@@ -2135,16 +2163,21 @@ NSGigE::txKick()
 
         if (txDescCnt == 0) {
             DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
-            if (txDescCache.cmdsts & CMDSTS_MORE) {
+            if (cmdsts & CMDSTS_MORE) {
                 DPRINTF(EthernetSM, "there are more descriptors to come\n");
                 txState = txDescWrite;
 
-                txDescCache.cmdsts &= ~CMDSTS_OWN;
+                cmdsts &= ~CMDSTS_OWN;
 
-                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
-                txDmaAddr &= 0x3fffffff;
-                txDmaData = &(txDescCache.cmdsts);
-                txDmaLen = sizeof(txDescCache.cmdsts);
+                txDmaAddr = regs.txdp & 0x3fffffff;
+                txDmaData = &cmdsts;
+                if (is64bit) {
+                    txDmaAddr += offsetof(ns_desc64, cmdsts);
+                    txDmaLen = sizeof(txDesc64.cmdsts);
+                } else {
+                    txDmaAddr += offsetof(ns_desc32, cmdsts);
+                    txDmaLen = sizeof(txDesc32.cmdsts);
+                }
                 txDmaFree = dmaDescFree;
 
                 if (doTxDmaWrite())
@@ -2155,18 +2188,18 @@ NSGigE::txKick()
                 /* deal with the the packet that just finished */
                 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
                     IpPtr ip(txPacket);
-                    if (txDescCache.extsts & EXTSTS_UDPPKT) {
+                    if (extsts & EXTSTS_UDPPKT) {
                         UdpPtr udp(ip);
                         udp->sum(0);
                         udp->sum(cksum(udp));
                         txUdpChecksums++;
-                    } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
+                    } else if (extsts & EXTSTS_TCPPKT) {
                         TcpPtr tcp(ip);
                         tcp->sum(0);
                         tcp->sum(cksum(tcp));
                         txTcpChecksums++;
                     }
-                    if (txDescCache.extsts & EXTSTS_IPPKT) {
+                    if (extsts & EXTSTS_IPPKT) {
                         ip->sum(0);
                         ip->sum(cksum(ip));
                         txIpChecksums++;
@@ -2176,7 +2209,10 @@ NSGigE::txKick()
                 txPacket->length = txPacketBufPtr - txPacket->data;
                 // this is just because the receive can't handle a
                 // packet bigger want to make sure
-                assert(txPacket->length <= 1514);
+                if (txPacket->length > 1514)
+                    panic("transmit packet too large, %s > 1514\n",
+                          txPacket->length);
+
 #ifndef NDEBUG
                 bool success =
 #endif
@@ -2195,19 +2231,25 @@ NSGigE::txKick()
                  * spec would complicate the code, we just do it here
                  */
 
-                txDescCache.cmdsts &= ~CMDSTS_OWN;
-                txDescCache.cmdsts |= CMDSTS_OK;
+                cmdsts &= ~CMDSTS_OWN;
+                cmdsts |= CMDSTS_OK;
 
                 DPRINTF(EthernetDesc,
                         "txDesc writeback: cmdsts=%08x extsts=%08x\n",
-                        txDescCache.cmdsts, txDescCache.extsts);
+                        cmdsts, extsts);
 
-                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
-                txDmaAddr &= 0x3fffffff;
-                txDmaData = &(txDescCache.cmdsts);
-                txDmaLen = sizeof(txDescCache.cmdsts) +
-                    sizeof(txDescCache.extsts);
                 txDmaFree = dmaDescFree;
+                txDmaAddr = regs.txdp & 0x3fffffff;
+                txDmaData = &cmdsts;
+                if (is64bit) {
+                    txDmaAddr += offsetof(ns_desc64, cmdsts);
+                    txDmaLen =
+                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
+                } else {
+                    txDmaAddr += offsetof(ns_desc32, cmdsts);
+                    txDmaLen =
+                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
+                }
 
                 descDmaWrites++;
                 descDmaWrBytes += txDmaLen;
@@ -2271,7 +2313,7 @@ NSGigE::txKick()
         if (txDmaState != dmaIdle)
             goto exit;
 
-        if (txDescCache.cmdsts & CMDSTS_INTR)
+        if (cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_TXDESC);
 
         if (!txEnable) {
@@ -2283,7 +2325,7 @@ NSGigE::txKick()
         break;
 
       case txAdvance:
-        if (txDescCache.link == 0) {
+        if (link == 0) {
             devIntrPost(ISR_TXIDLE);
             txState = txIdle;
             goto exit;
@@ -2291,12 +2333,12 @@ NSGigE::txKick()
             if (txDmaState != dmaIdle)
                 goto exit;
             txState = txDescRead;
-            regs.txdp = txDescCache.link;
+            regs.txdp = link;
             CTDD = false;
 
-            txDmaAddr = txDescCache.link & 0x3fffffff;
-            txDmaData = &txDescCache;
-            txDmaLen = sizeof(ns_desc);
+            txDmaAddr = link & 0x3fffffff;
+            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
+            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
             txDmaFree = dmaDescFree;
 
             if (doTxDmaRead())
@@ -2494,20 +2536,17 @@ NSGigE::recvPacket(PacketPtr packet)
 
     if (!rxEnable) {
         DPRINTF(Ethernet, "receive disabled...packet dropped\n");
-        interface->recvDone();
         return true;
     }
 
     if (!rxFilterEnable) {
         DPRINTF(Ethernet,
             "receive packet filtering disabled . . . packet dropped\n");
-        interface->recvDone();
         return true;
     }
 
     if (rxFilter(packet)) {
         DPRINTF(Ethernet, "packet filtered...dropped\n");
-        interface->recvDone();
         return true;
     }
 
@@ -2530,7 +2569,6 @@ NSGigE::recvPacket(PacketPtr packet)
     }
 
     rxFifo.push(packet);
-    interface->recvDone();
 
     rxKick();
     return true;
@@ -2630,16 +2668,24 @@ NSGigE::serialize(ostream &os)
     SERIALIZE_SCALAR(rxXferLen);
 
     /*
-     * Serialize DescCaches
+     * Serialize Cached Descriptors
      */
-    SERIALIZE_SCALAR(txDescCache.link);
-    SERIALIZE_SCALAR(txDescCache.bufptr);
-    SERIALIZE_SCALAR(txDescCache.cmdsts);
-    SERIALIZE_SCALAR(txDescCache.extsts);
-    SERIALIZE_SCALAR(rxDescCache.link);
-    SERIALIZE_SCALAR(rxDescCache.bufptr);
-    SERIALIZE_SCALAR(rxDescCache.cmdsts);
-    SERIALIZE_SCALAR(rxDescCache.extsts);
+    SERIALIZE_SCALAR(rxDesc64.link);
+    SERIALIZE_SCALAR(rxDesc64.bufptr);
+    SERIALIZE_SCALAR(rxDesc64.cmdsts);
+    SERIALIZE_SCALAR(rxDesc64.extsts);
+    SERIALIZE_SCALAR(txDesc64.link);
+    SERIALIZE_SCALAR(txDesc64.bufptr);
+    SERIALIZE_SCALAR(txDesc64.cmdsts);
+    SERIALIZE_SCALAR(txDesc64.extsts);
+    SERIALIZE_SCALAR(rxDesc32.link);
+    SERIALIZE_SCALAR(rxDesc32.bufptr);
+    SERIALIZE_SCALAR(rxDesc32.cmdsts);
+    SERIALIZE_SCALAR(rxDesc32.extsts);
+    SERIALIZE_SCALAR(txDesc32.link);
+    SERIALIZE_SCALAR(txDesc32.bufptr);
+    SERIALIZE_SCALAR(txDesc32.cmdsts);
+    SERIALIZE_SCALAR(txDesc32.extsts);
     SERIALIZE_SCALAR(extstsEnable);
 
     /*
@@ -2792,16 +2838,24 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(rxXferLen);
 
     /*
-     * Unserialize DescCaches
+     * Unserialize Cached Descriptors
      */
-    UNSERIALIZE_SCALAR(txDescCache.link);
-    UNSERIALIZE_SCALAR(txDescCache.bufptr);
-    UNSERIALIZE_SCALAR(txDescCache.cmdsts);
-    UNSERIALIZE_SCALAR(txDescCache.extsts);
-    UNSERIALIZE_SCALAR(rxDescCache.link);
-    UNSERIALIZE_SCALAR(rxDescCache.bufptr);
-    UNSERIALIZE_SCALAR(rxDescCache.cmdsts);
-    UNSERIALIZE_SCALAR(rxDescCache.extsts);
+    UNSERIALIZE_SCALAR(rxDesc64.link);
+    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
+    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
+    UNSERIALIZE_SCALAR(rxDesc64.extsts);
+    UNSERIALIZE_SCALAR(txDesc64.link);
+    UNSERIALIZE_SCALAR(txDesc64.bufptr);
+    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
+    UNSERIALIZE_SCALAR(txDesc64.extsts);
+    UNSERIALIZE_SCALAR(rxDesc32.link);
+    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
+    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
+    UNSERIALIZE_SCALAR(rxDesc32.extsts);
+    UNSERIALIZE_SCALAR(txDesc32.link);
+    UNSERIALIZE_SCALAR(txDesc32.bufptr);
+    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
+    UNSERIALIZE_SCALAR(txDesc32.extsts);
     UNSERIALIZE_SCALAR(extstsEnable);
 
     /*
@@ -2894,8 +2948,38 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
 Tick
 NSGigE::cacheAccess(MemReqPtr &req)
 {
+    Addr daddr = req->paddr & 0xfff;
     DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
-            req->paddr, req->paddr - addr);
+            req->paddr, daddr);
+
+    if (!pioDelayWrite || !req->cmd.isWrite())
+        return curTick + pioLatency;
+
+    int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+    std::list<RegWriteData> &wq = writeQueue[cpu];
+    if (wq.empty())
+        panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
+
+    const RegWriteData &data = wq.front();
+    if (data.daddr != daddr)
+        panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
+              cpu, data.daddr, daddr);
+
+    if (daddr == CR) {
+        if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) {
+            txEnable = true;
+            if (txState == txIdle)
+                txKick();
+        }
+
+        if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) {
+            rxEnable = true;
+            if (rxState == rxIdle)
+                rxKick();
+        }
+    }
+
+    wq.pop_front();
     return curTick + pioLatency;
 }
 
@@ -2931,69 +3015,83 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
 
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
 
-    Param<Addr> addr;
     Param<Tick> clock;
-    Param<Tick> tx_delay;
-    Param<Tick> rx_delay;
-    Param<Tick> intr_delay;
+
+    Param<Addr> addr;
     SimObjectParam<MemoryController *> mmu;
     SimObjectParam<PhysicalMemory *> physmem;
-    Param<bool> rx_filter;
-    Param<string> hardware_address;
-    SimObjectParam<Bus*> io_bus;
-    SimObjectParam<Bus*> payload_bus;
+    SimObjectParam<PciConfigAll *> configspace;
+    SimObjectParam<PciConfigData *> configdata;
+    SimObjectParam<Platform *> platform;
+    Param<uint32_t> pci_bus;
+    Param<uint32_t> pci_dev;
+    Param<uint32_t> pci_func;
+
     SimObjectParam<HierParams *> hier;
-    Param<Tick> pio_latency;
+    SimObjectParam<Bus*> pio_bus;
+    SimObjectParam<Bus*> dma_bus;
+    SimObjectParam<Bus*> payload_bus;
     Param<bool> dma_desc_free;
     Param<bool> dma_data_free;
     Param<Tick> dma_read_delay;
     Param<Tick> dma_write_delay;
     Param<Tick> dma_read_factor;
     Param<Tick> dma_write_factor;
-    SimObjectParam<PciConfigAll *> configspace;
-    SimObjectParam<PciConfigData *> configdata;
-    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;
-    Param<uint32_t> m5reg;
     Param<bool> dma_no_allocate;
+    Param<Tick> pio_latency;
+    Param<bool> pio_delay_write;
+    Param<Tick> intr_delay;
+
+    Param<Tick> rx_delay;
+    Param<Tick> tx_delay;
+    Param<uint32_t> rx_fifo_size;
+    Param<uint32_t> tx_fifo_size;
+
+    Param<bool> rx_filter;
+    Param<string> hardware_address;
+    Param<bool> rx_thread;
+    Param<bool> tx_thread;
 
 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
 
 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
 
-    INIT_PARAM(addr, "Device Address"),
     INIT_PARAM(clock, "State machine processor frequency"),
-    INIT_PARAM(tx_delay, "Transmit Delay"),
-    INIT_PARAM(rx_delay, "Receive Delay"),
-    INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
+
+    INIT_PARAM(addr, "Device Address"),
     INIT_PARAM(mmu, "Memory Controller"),
     INIT_PARAM(physmem, "Physical Memory"),
-    INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
-    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
-    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 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),
-    INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
-    INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
-    INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
     INIT_PARAM(configspace, "PCI Configspace"),
     INIT_PARAM(configdata, "PCI Config data"),
     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_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072),
-    INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072),
-    INIT_PARAM(m5reg, "m5 register"),
-    INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true)
+
+    INIT_PARAM(hier, "Hierarchy global variables"),
+    INIT_PARAM(pio_bus, ""),
+    INIT_PARAM(dma_bus, ""),
+    INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"),
+    INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"),
+    INIT_PARAM(dma_data_free, "DMA of Data is free"),
+    INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
+    INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
+    INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
+    INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
+    INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"),
+    INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
+    INIT_PARAM(pio_delay_write, ""),
+    INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
+
+    INIT_PARAM(rx_delay, "Receive Delay"),
+    INIT_PARAM(tx_delay, "Transmit Delay"),
+    INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
+    INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
+
+    INIT_PARAM(rx_filter, "Enable Receive Filter"),
+    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
+    INIT_PARAM(rx_thread, ""),
+    INIT_PARAM(tx_thread, "")
 
 END_INIT_SIM_OBJECT_PARAMS(NSGigE)
 
@@ -3003,7 +3101,11 @@ CREATE_SIM_OBJECT(NSGigE)
     NSGigE::Params *params = new NSGigE::Params;
 
     params->name = getInstanceName();
+
+    params->clock = clock;
+
     params->mmu = mmu;
+    params->pmem = physmem;
     params->configSpace = configspace;
     params->configData = configdata;
     params->plat = platform;
@@ -3011,27 +3113,31 @@ CREATE_SIM_OBJECT(NSGigE)
     params->deviceNum = pci_dev;
     params->functionNum = pci_func;
 
-    params->clock = clock;
-    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->pio_bus = pio_bus;
+    params->header_bus = dma_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->dma_no_allocate = dma_no_allocate;
+    params->pio_latency = pio_latency;
+    params->pio_delay_write = pio_delay_write;
+    params->intr_delay = intr_delay;
+
+    params->rx_delay = rx_delay;
+    params->tx_delay = tx_delay;
+    params->rx_fifo_size = rx_fifo_size;
+    params->tx_fifo_size = tx_fifo_size;
+
     params->rx_filter = rx_filter;
     params->eaddr = hardware_address;
-    params->tx_fifo_size = tx_fifo_size;
-    params->rx_fifo_size = rx_fifo_size;
-    params->m5reg = m5reg;
-    params->dma_no_allocate = dma_no_allocate;
+    params->rx_thread = rx_thread;
+    params->tx_thread = tx_thread;
+
     return new NSGigE(params);
 }