ns_gige.cc revision 11701:5e7599457b97
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 *          Lisa Hsu
30 */
31
32/** @file
33 * Device module for modelling the National Semiconductor
34 * DP83820 ethernet controller.  Does not support priority queueing
35 */
36
37#include "dev/net/ns_gige.hh"
38
39#include <deque>
40#include <memory>
41#include <string>
42
43#include "base/debug.hh"
44#include "base/inet.hh"
45#include "base/types.hh"
46#include "config/the_isa.hh"
47#include "debug/EthernetAll.hh"
48#include "dev/net/etherlink.hh"
49#include "mem/packet.hh"
50#include "mem/packet_access.hh"
51#include "params/NSGigE.hh"
52#include "sim/system.hh"
53
54// clang complains about std::set being overloaded with Packet::set if
55// we open up the entire namespace std
56using std::make_shared;
57using std::min;
58using std::ostream;
59using std::string;
60
61const char *NsRxStateStrings[] =
62{
63    "rxIdle",
64    "rxDescRefr",
65    "rxDescRead",
66    "rxFifoBlock",
67    "rxFragWrite",
68    "rxDescWrite",
69    "rxAdvance"
70};
71
72const char *NsTxStateStrings[] =
73{
74    "txIdle",
75    "txDescRefr",
76    "txDescRead",
77    "txFifoBlock",
78    "txFragRead",
79    "txDescWrite",
80    "txAdvance"
81};
82
83const char *NsDmaState[] =
84{
85    "dmaIdle",
86    "dmaReading",
87    "dmaWriting",
88    "dmaReadWaiting",
89    "dmaWriteWaiting"
90};
91
92using namespace Net;
93using namespace TheISA;
94
95///////////////////////////////////////////////////////////////////////
96//
97// NSGigE PCI Device
98//
99NSGigE::NSGigE(Params *p)
100    : EtherDevBase(p), ioEnable(false),
101      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
102      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
103      txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
104      txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
105      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
106      rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
107      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
108      eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
109      eepromOpcode(0), eepromAddress(0), eepromData(0),
110      dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
111      dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
112      rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
113      txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
114      rxDmaReadEvent(this), rxDmaWriteEvent(this),
115      txDmaReadEvent(this), txDmaWriteEvent(this),
116      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
117      txDelay(p->tx_delay), rxDelay(p->rx_delay),
118      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
119      txEvent(this), rxFilterEnable(p->rx_filter),
120      acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
121      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
122      intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
123      intrEvent(0), interface(0)
124{
125
126
127    interface = new NSGigEInt(name() + ".int0", this);
128
129    regsReset();
130    memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
131
132    memset(&rxDesc32, 0, sizeof(rxDesc32));
133    memset(&txDesc32, 0, sizeof(txDesc32));
134    memset(&rxDesc64, 0, sizeof(rxDesc64));
135    memset(&txDesc64, 0, sizeof(txDesc64));
136}
137
138NSGigE::~NSGigE()
139{
140    delete interface;
141}
142
143/**
144 * This is to write to the PCI general configuration registers
145 */
146Tick
147NSGigE::writeConfig(PacketPtr pkt)
148{
149    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
150    if (offset < PCI_DEVICE_SPECIFIC)
151        PciDevice::writeConfig(pkt);
152    else
153        panic("Device specific PCI config space not implemented!\n");
154
155    switch (offset) {
156        // seems to work fine without all these PCI settings, but i
157        // put in the IO to double check, an assertion will fail if we
158        // need to properly implement it
159      case PCI_COMMAND:
160        if (config.data[offset] & PCI_CMD_IOSE)
161            ioEnable = true;
162        else
163            ioEnable = false;
164        break;
165    }
166
167    return configDelay;
168}
169
170EtherInt*
171NSGigE::getEthPort(const std::string &if_name, int idx)
172{
173    if (if_name == "interface") {
174       if (interface->getPeer())
175           panic("interface already connected to\n");
176       return interface;
177    }
178    return NULL;
179}
180
181/**
182 * This reads the device registers, which are detailed in the NS83820
183 * spec sheet
184 */
185Tick
186NSGigE::read(PacketPtr pkt)
187{
188    assert(ioEnable);
189
190    //The mask is to give you only the offset into the device register file
191    Addr daddr = pkt->getAddr() & 0xfff;
192    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
193            daddr, pkt->getAddr(), pkt->getSize());
194
195
196    // there are some reserved registers, you can see ns_gige_reg.h and
197    // the spec sheet for details
198    if (daddr > LAST && daddr <=  RESERVED) {
199        panic("Accessing reserved register");
200    } else if (daddr > RESERVED && daddr <= 0x3FC) {
201        return readConfig(pkt);
202    } else if (daddr >= MIB_START && daddr <= MIB_END) {
203        // don't implement all the MIB's.  hopefully the kernel
204        // doesn't actually DEPEND upon their values
205        // MIB are just hardware stats keepers
206        pkt->set<uint32_t>(0);
207        pkt->makeAtomicResponse();
208        return pioDelay;
209    } else if (daddr > 0x3FC)
210        panic("Something is messed up!\n");
211
212    assert(pkt->getSize() == sizeof(uint32_t));
213        uint32_t &reg = *pkt->getPtr<uint32_t>();
214        uint16_t rfaddr;
215
216        switch (daddr) {
217          case CR:
218            reg = regs.command;
219            //these are supposed to be cleared on a read
220            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
221            break;
222
223          case CFGR:
224            reg = regs.config;
225            break;
226
227          case MEAR:
228            reg = regs.mear;
229            break;
230
231          case PTSCR:
232            reg = regs.ptscr;
233            break;
234
235          case ISR:
236            reg = regs.isr;
237            devIntrClear(ISR_ALL);
238            break;
239
240          case IMR:
241            reg = regs.imr;
242            break;
243
244          case IER:
245            reg = regs.ier;
246            break;
247
248          case IHR:
249            reg = regs.ihr;
250            break;
251
252          case TXDP:
253            reg = regs.txdp;
254            break;
255
256          case TXDP_HI:
257            reg = regs.txdp_hi;
258            break;
259
260          case TX_CFG:
261            reg = regs.txcfg;
262            break;
263
264          case GPIOR:
265            reg = regs.gpior;
266            break;
267
268          case RXDP:
269            reg = regs.rxdp;
270            break;
271
272          case RXDP_HI:
273            reg = regs.rxdp_hi;
274            break;
275
276          case RX_CFG:
277            reg = regs.rxcfg;
278            break;
279
280          case PQCR:
281            reg = regs.pqcr;
282            break;
283
284          case WCSR:
285            reg = regs.wcsr;
286            break;
287
288          case PCR:
289            reg = regs.pcr;
290            break;
291
292            // see the spec sheet for how RFCR and RFDR work
293            // basically, you write to RFCR to tell the machine
294            // what you want to do next, then you act upon RFDR,
295            // and the device will be prepared b/c of what you
296            // wrote to RFCR
297          case RFCR:
298            reg = regs.rfcr;
299            break;
300
301          case RFDR:
302            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
303            switch (rfaddr) {
304              // Read from perfect match ROM octets
305              case 0x000:
306                reg = rom.perfectMatch[1];
307                reg = reg << 8;
308                reg += rom.perfectMatch[0];
309                break;
310              case 0x002:
311                reg = rom.perfectMatch[3] << 8;
312                reg += rom.perfectMatch[2];
313                break;
314              case 0x004:
315                reg = rom.perfectMatch[5] << 8;
316                reg += rom.perfectMatch[4];
317                break;
318              default:
319                // Read filter hash table
320                if (rfaddr >= FHASH_ADDR &&
321                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
322
323                    // Only word-aligned reads supported
324                    if (rfaddr % 2)
325                        panic("unaligned read from filter hash table!");
326
327                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
328                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
329                    break;
330                }
331
332                panic("reading RFDR for something other than pattern"
333                      " matching or hashing! %#x\n", rfaddr);
334            }
335            break;
336
337          case SRR:
338            reg = regs.srr;
339            break;
340
341          case MIBC:
342            reg = regs.mibc;
343            reg &= ~(MIBC_MIBS | MIBC_ACLR);
344            break;
345
346          case VRCR:
347            reg = regs.vrcr;
348            break;
349
350          case VTCR:
351            reg = regs.vtcr;
352            break;
353
354          case VDR:
355            reg = regs.vdr;
356            break;
357
358          case CCSR:
359            reg = regs.ccsr;
360            break;
361
362          case TBICR:
363            reg = regs.tbicr;
364            break;
365
366          case TBISR:
367            reg = regs.tbisr;
368            break;
369
370          case TANAR:
371            reg = regs.tanar;
372            break;
373
374          case TANLPAR:
375            reg = regs.tanlpar;
376            break;
377
378          case TANER:
379            reg = regs.taner;
380            break;
381
382          case TESR:
383            reg = regs.tesr;
384            break;
385
386          case M5REG:
387            reg = 0;
388            if (params()->rx_thread)
389                reg |= M5REG_RX_THREAD;
390            if (params()->tx_thread)
391                reg |= M5REG_TX_THREAD;
392            if (params()->rss)
393                reg |= M5REG_RSS;
394            break;
395
396          default:
397            panic("reading unimplemented register: addr=%#x", daddr);
398        }
399
400        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
401                daddr, reg, reg);
402
403    pkt->makeAtomicResponse();
404    return pioDelay;
405}
406
407Tick
408NSGigE::write(PacketPtr pkt)
409{
410    assert(ioEnable);
411
412    Addr daddr = pkt->getAddr() & 0xfff;
413    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
414            daddr, pkt->getAddr(), pkt->getSize());
415
416    if (daddr > LAST && daddr <=  RESERVED) {
417        panic("Accessing reserved register");
418    } else if (daddr > RESERVED && daddr <= 0x3FC) {
419        return writeConfig(pkt);
420    } else if (daddr > 0x3FC)
421        panic("Something is messed up!\n");
422
423    if (pkt->getSize() == sizeof(uint32_t)) {
424        uint32_t reg = pkt->get<uint32_t>();
425        uint16_t rfaddr;
426
427        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
428
429        switch (daddr) {
430          case CR:
431            regs.command = reg;
432            if (reg & CR_TXD) {
433                txEnable = false;
434            } else if (reg & CR_TXE) {
435                txEnable = true;
436
437                // the kernel is enabling the transmit machine
438                if (txState == txIdle)
439                    txKick();
440            }
441
442            if (reg & CR_RXD) {
443                rxEnable = false;
444            } else if (reg & CR_RXE) {
445                rxEnable = true;
446
447                if (rxState == rxIdle)
448                    rxKick();
449            }
450
451            if (reg & CR_TXR)
452                txReset();
453
454            if (reg & CR_RXR)
455                rxReset();
456
457            if (reg & CR_SWI)
458                devIntrPost(ISR_SWI);
459
460            if (reg & CR_RST) {
461                txReset();
462                rxReset();
463
464                regsReset();
465            }
466            break;
467
468          case CFGR:
469            if (reg & CFGR_LNKSTS ||
470                reg & CFGR_SPDSTS ||
471                reg & CFGR_DUPSTS ||
472                reg & CFGR_RESERVED ||
473                reg & CFGR_T64ADDR ||
474                reg & CFGR_PCI64_DET) {
475                // First clear all writable bits
476                regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
477                    CFGR_RESERVED | CFGR_T64ADDR |
478                    CFGR_PCI64_DET;
479                // Now set the appropriate writable bits
480                regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
481                                       CFGR_RESERVED | CFGR_T64ADDR |
482                                       CFGR_PCI64_DET);
483            }
484
485// all these #if 0's are because i don't THINK the kernel needs to
486// have these implemented. if there is a problem relating to one of
487// these, you may need to add functionality in.
488
489// grouped together and #if 0'ed to avoid empty if body and make clang happy
490#if 0
491            if (reg & CFGR_TBI_EN) ;
492            if (reg & CFGR_MODE_1000) ;
493
494            if (reg & CFGR_PINT_DUPSTS ||
495                reg & CFGR_PINT_LNKSTS ||
496                reg & CFGR_PINT_SPDSTS)
497                ;
498
499            if (reg & CFGR_TMRTEST) ;
500            if (reg & CFGR_MRM_DIS) ;
501            if (reg & CFGR_MWI_DIS) ;
502
503            if (reg & CFGR_DATA64_EN) ;
504            if (reg & CFGR_M64ADDR) ;
505            if (reg & CFGR_PHY_RST) ;
506            if (reg & CFGR_PHY_DIS) ;
507
508            if (reg & CFGR_REQALG) ;
509            if (reg & CFGR_SB) ;
510            if (reg & CFGR_POW) ;
511            if (reg & CFGR_EXD) ;
512            if (reg & CFGR_PESEL) ;
513            if (reg & CFGR_BROM_DIS) ;
514            if (reg & CFGR_EXT_125) ;
515            if (reg & CFGR_BEM) ;
516
517            if (reg & CFGR_T64ADDR) ;
518            // panic("CFGR_T64ADDR is read only register!\n");
519#endif
520            if (reg & CFGR_AUTO_1000)
521                panic("CFGR_AUTO_1000 not implemented!\n");
522
523            if (reg & CFGR_PCI64_DET)
524                panic("CFGR_PCI64_DET is read only register!\n");
525
526            if (reg & CFGR_EXTSTS_EN)
527                extstsEnable = true;
528            else
529                extstsEnable = false;
530            break;
531
532          case MEAR:
533            // Clear writable bits
534            regs.mear &= MEAR_EEDO;
535            // Set appropriate writable bits
536            regs.mear |= reg & ~MEAR_EEDO;
537
538            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
539            // even though it could get it through RFDR
540            if (reg & MEAR_EESEL) {
541                // Rising edge of clock
542                if (reg & MEAR_EECLK && !eepromClk)
543                    eepromKick();
544            }
545            else {
546                eepromState = eepromStart;
547                regs.mear &= ~MEAR_EEDI;
548            }
549
550            eepromClk = reg & MEAR_EECLK;
551
552            // since phy is completely faked, MEAR_MD* don't matter
553
554// grouped together and #if 0'ed to avoid empty if body and make clang happy
555#if 0
556            if (reg & MEAR_MDIO) ;
557            if (reg & MEAR_MDDIR) ;
558            if (reg & MEAR_MDC) ;
559#endif
560            break;
561
562          case PTSCR:
563            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
564            // these control BISTs for various parts of chip - we
565            // don't care or do just fake that the BIST is done
566            if (reg & PTSCR_RBIST_EN)
567                regs.ptscr |= PTSCR_RBIST_DONE;
568            if (reg & PTSCR_EEBIST_EN)
569                regs.ptscr &= ~PTSCR_EEBIST_EN;
570            if (reg & PTSCR_EELOAD_EN)
571                regs.ptscr &= ~PTSCR_EELOAD_EN;
572            break;
573
574          case ISR: /* writing to the ISR has no effect */
575            panic("ISR is a read only register!\n");
576
577          case IMR:
578            regs.imr = reg;
579            devIntrChangeMask();
580            break;
581
582          case IER:
583            regs.ier = reg;
584            break;
585
586          case IHR:
587            regs.ihr = reg;
588            /* not going to implement real interrupt holdoff */
589            break;
590
591          case TXDP:
592            regs.txdp = (reg & 0xFFFFFFFC);
593            assert(txState == txIdle);
594            CTDD = false;
595            break;
596
597          case TXDP_HI:
598            regs.txdp_hi = reg;
599            break;
600
601          case TX_CFG:
602            regs.txcfg = reg;
603#if 0
604            if (reg & TX_CFG_CSI) ;
605            if (reg & TX_CFG_HBI) ;
606            if (reg & TX_CFG_MLB) ;
607            if (reg & TX_CFG_ATP) ;
608            if (reg & TX_CFG_ECRETRY) {
609                /*
610                 * this could easily be implemented, but considering
611                 * the network is just a fake pipe, wouldn't make
612                 * sense to do this
613                 */
614            }
615
616            if (reg & TX_CFG_BRST_DIS) ;
617#endif
618
619#if 0
620            /* we handle our own DMA, ignore the kernel's exhortations */
621            if (reg & TX_CFG_MXDMA) ;
622#endif
623
624            // also, we currently don't care about fill/drain
625            // thresholds though this may change in the future with
626            // more realistic networks or a driver which changes it
627            // according to feedback
628
629            break;
630
631          case GPIOR:
632            // Only write writable bits
633            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
634                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
635            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
636                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
637            /* these just control general purpose i/o pins, don't matter */
638            break;
639
640          case RXDP:
641            regs.rxdp = reg;
642            CRDD = false;
643            break;
644
645          case RXDP_HI:
646            regs.rxdp_hi = reg;
647            break;
648
649          case RX_CFG:
650            regs.rxcfg = reg;
651#if 0
652            if (reg & RX_CFG_AEP) ;
653            if (reg & RX_CFG_ARP) ;
654            if (reg & RX_CFG_STRIPCRC) ;
655            if (reg & RX_CFG_RX_RD) ;
656            if (reg & RX_CFG_ALP) ;
657            if (reg & RX_CFG_AIRL) ;
658
659            /* we handle our own DMA, ignore what kernel says about it */
660            if (reg & RX_CFG_MXDMA) ;
661
662            //also, we currently don't care about fill/drain thresholds
663            //though this may change in the future with more realistic
664            //networks or a driver which changes it according to feedback
665            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
666#endif
667            break;
668
669          case PQCR:
670            /* there is no priority queueing used in the linux 2.6 driver */
671            regs.pqcr = reg;
672            break;
673
674          case WCSR:
675            /* not going to implement wake on LAN */
676            regs.wcsr = reg;
677            break;
678
679          case PCR:
680            /* not going to implement pause control */
681            regs.pcr = reg;
682            break;
683
684          case RFCR:
685            regs.rfcr = reg;
686
687            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
688            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
689            acceptMulticast = (reg & RFCR_AAM) ? true : false;
690            acceptUnicast = (reg & RFCR_AAU) ? true : false;
691            acceptPerfect = (reg & RFCR_APM) ? true : false;
692            acceptArp = (reg & RFCR_AARP) ? true : false;
693            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
694
695#if 0
696            if (reg & RFCR_APAT)
697                panic("RFCR_APAT not implemented!\n");
698#endif
699            if (reg & RFCR_UHEN)
700                panic("Unicast hash filtering not used by drivers!\n");
701
702            if (reg & RFCR_ULM)
703                panic("RFCR_ULM not implemented!\n");
704
705            break;
706
707          case RFDR:
708            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
709            switch (rfaddr) {
710              case 0x000:
711                rom.perfectMatch[0] = (uint8_t)reg;
712                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
713                break;
714              case 0x002:
715                rom.perfectMatch[2] = (uint8_t)reg;
716                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
717                break;
718              case 0x004:
719                rom.perfectMatch[4] = (uint8_t)reg;
720                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
721                break;
722              default:
723
724                if (rfaddr >= FHASH_ADDR &&
725                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
726
727                    // Only word-aligned writes supported
728                    if (rfaddr % 2)
729                        panic("unaligned write to filter hash table!");
730
731                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
732                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
733                        = (uint8_t)(reg >> 8);
734                    break;
735                }
736                panic("writing RFDR for something other than pattern matching "
737                    "or hashing! %#x\n", rfaddr);
738            }
739
740          case BRAR:
741            regs.brar = reg;
742            break;
743
744          case BRDR:
745            panic("the driver never uses BRDR, something is wrong!\n");
746
747          case SRR:
748            panic("SRR is read only register!\n");
749
750          case MIBC:
751            panic("the driver never uses MIBC, something is wrong!\n");
752
753          case VRCR:
754            regs.vrcr = reg;
755            break;
756
757          case VTCR:
758            regs.vtcr = reg;
759            break;
760
761          case VDR:
762            panic("the driver never uses VDR, something is wrong!\n");
763
764          case CCSR:
765            /* not going to implement clockrun stuff */
766            regs.ccsr = reg;
767            break;
768
769          case TBICR:
770            regs.tbicr = reg;
771            if (reg & TBICR_MR_LOOPBACK)
772                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
773
774            if (reg & TBICR_MR_AN_ENABLE) {
775                regs.tanlpar = regs.tanar;
776                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
777            }
778
779#if 0
780            if (reg & TBICR_MR_RESTART_AN) ;
781#endif
782
783            break;
784
785          case TBISR:
786            panic("TBISR is read only register!\n");
787
788          case TANAR:
789            // Only write the writable bits
790            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
791            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
792
793            // Pause capability unimplemented
794#if 0
795            if (reg & TANAR_PS2) ;
796            if (reg & TANAR_PS1) ;
797#endif
798
799            break;
800
801          case TANLPAR:
802            panic("this should only be written to by the fake phy!\n");
803
804          case TANER:
805            panic("TANER is read only register!\n");
806
807          case TESR:
808            regs.tesr = reg;
809            break;
810
811          default:
812            panic("invalid register access daddr=%#x", daddr);
813        }
814    } else {
815        panic("Invalid Request Size");
816    }
817    pkt->makeAtomicResponse();
818    return pioDelay;
819}
820
821void
822NSGigE::devIntrPost(uint32_t interrupts)
823{
824    if (interrupts & ISR_RESERVE)
825        panic("Cannot set a reserved interrupt");
826
827    if (interrupts & ISR_NOIMPL)
828        warn("interrupt not implemented %#x\n", interrupts);
829
830    interrupts &= ISR_IMPL;
831    regs.isr |= interrupts;
832
833    if (interrupts & regs.imr) {
834        if (interrupts & ISR_SWI) {
835            totalSwi++;
836        }
837        if (interrupts & ISR_RXIDLE) {
838            totalRxIdle++;
839        }
840        if (interrupts & ISR_RXOK) {
841            totalRxOk++;
842        }
843        if (interrupts & ISR_RXDESC) {
844            totalRxDesc++;
845        }
846        if (interrupts & ISR_TXOK) {
847            totalTxOk++;
848        }
849        if (interrupts & ISR_TXIDLE) {
850            totalTxIdle++;
851        }
852        if (interrupts & ISR_TXDESC) {
853            totalTxDesc++;
854        }
855        if (interrupts & ISR_RXORN) {
856            totalRxOrn++;
857        }
858    }
859
860    DPRINTF(EthernetIntr,
861            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
862            interrupts, regs.isr, regs.imr);
863
864    if ((regs.isr & regs.imr)) {
865        Tick when = curTick();
866        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
867            when += intrDelay;
868        postedInterrupts++;
869        cpuIntrPost(when);
870    }
871}
872
873/* writing this interrupt counting stats inside this means that this function
874   is now limited to being used to clear all interrupts upon the kernel
875   reading isr and servicing.  just telling you in case you were thinking
876   of expanding use.
877*/
878void
879NSGigE::devIntrClear(uint32_t interrupts)
880{
881    if (interrupts & ISR_RESERVE)
882        panic("Cannot clear a reserved interrupt");
883
884    if (regs.isr & regs.imr & ISR_SWI) {
885        postedSwi++;
886    }
887    if (regs.isr & regs.imr & ISR_RXIDLE) {
888        postedRxIdle++;
889    }
890    if (regs.isr & regs.imr & ISR_RXOK) {
891        postedRxOk++;
892    }
893    if (regs.isr & regs.imr & ISR_RXDESC) {
894            postedRxDesc++;
895    }
896    if (regs.isr & regs.imr & ISR_TXOK) {
897        postedTxOk++;
898    }
899    if (regs.isr & regs.imr & ISR_TXIDLE) {
900        postedTxIdle++;
901    }
902    if (regs.isr & regs.imr & ISR_TXDESC) {
903        postedTxDesc++;
904    }
905    if (regs.isr & regs.imr & ISR_RXORN) {
906        postedRxOrn++;
907    }
908
909    interrupts &= ~ISR_NOIMPL;
910    regs.isr &= ~interrupts;
911
912    DPRINTF(EthernetIntr,
913            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
914            interrupts, regs.isr, regs.imr);
915
916    if (!(regs.isr & regs.imr))
917        cpuIntrClear();
918}
919
920void
921NSGigE::devIntrChangeMask()
922{
923    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
924            regs.isr, regs.imr, regs.isr & regs.imr);
925
926    if (regs.isr & regs.imr)
927        cpuIntrPost(curTick());
928    else
929        cpuIntrClear();
930}
931
932void
933NSGigE::cpuIntrPost(Tick when)
934{
935    // If the interrupt you want to post is later than an interrupt
936    // already scheduled, just let it post in the coming one and don't
937    // schedule another.
938    // HOWEVER, must be sure that the scheduled intrTick is in the
939    // future (this was formerly the source of a bug)
940    /**
941     * @todo this warning should be removed and the intrTick code should
942     * be fixed.
943     */
944    assert(when >= curTick());
945    assert(intrTick >= curTick() || intrTick == 0);
946    if (when > intrTick && intrTick != 0) {
947        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
948                intrTick);
949        return;
950    }
951
952    intrTick = when;
953    if (intrTick < curTick()) {
954        intrTick = curTick();
955    }
956
957    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
958            intrTick);
959
960    if (intrEvent)
961        intrEvent->squash();
962    intrEvent = new IntrEvent(this, true);
963    schedule(intrEvent, intrTick);
964}
965
966void
967NSGigE::cpuInterrupt()
968{
969    assert(intrTick == curTick());
970
971    // Whether or not there's a pending interrupt, we don't care about
972    // it anymore
973    intrEvent = 0;
974    intrTick = 0;
975
976    // Don't send an interrupt if there's already one
977    if (cpuPendingIntr) {
978        DPRINTF(EthernetIntr,
979                "would send an interrupt now, but there's already pending\n");
980    } else {
981        // Send interrupt
982        cpuPendingIntr = true;
983
984        DPRINTF(EthernetIntr, "posting interrupt\n");
985        intrPost();
986    }
987}
988
989void
990NSGigE::cpuIntrClear()
991{
992    if (!cpuPendingIntr)
993        return;
994
995    if (intrEvent) {
996        intrEvent->squash();
997        intrEvent = 0;
998    }
999
1000    intrTick = 0;
1001
1002    cpuPendingIntr = false;
1003
1004    DPRINTF(EthernetIntr, "clearing interrupt\n");
1005    intrClear();
1006}
1007
1008bool
1009NSGigE::cpuIntrPending() const
1010{ return cpuPendingIntr; }
1011
1012void
1013NSGigE::txReset()
1014{
1015
1016    DPRINTF(Ethernet, "transmit reset\n");
1017
1018    CTDD = false;
1019    txEnable = false;;
1020    txFragPtr = 0;
1021    assert(txDescCnt == 0);
1022    txFifo.clear();
1023    txState = txIdle;
1024    assert(txDmaState == dmaIdle);
1025}
1026
1027void
1028NSGigE::rxReset()
1029{
1030    DPRINTF(Ethernet, "receive reset\n");
1031
1032    CRDD = false;
1033    assert(rxPktBytes == 0);
1034    rxEnable = false;
1035    rxFragPtr = 0;
1036    assert(rxDescCnt == 0);
1037    assert(rxDmaState == dmaIdle);
1038    rxFifo.clear();
1039    rxState = rxIdle;
1040}
1041
1042void
1043NSGigE::regsReset()
1044{
1045    memset(&regs, 0, sizeof(regs));
1046    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1047    regs.mear = 0x12;
1048    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1049                        // fill threshold to 32 bytes
1050    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
1051    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
1052    regs.mibc = MIBC_FRZ;
1053    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
1054    regs.tesr = 0xc000; // TBI capable of both full and half duplex
1055    regs.brar = 0xffffffff;
1056
1057    extstsEnable = false;
1058    acceptBroadcast = false;
1059    acceptMulticast = false;
1060    acceptUnicast = false;
1061    acceptPerfect = false;
1062    acceptArp = false;
1063}
1064
1065bool
1066NSGigE::doRxDmaRead()
1067{
1068    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1069    rxDmaState = dmaReading;
1070
1071    if (dmaPending() || drainState() != DrainState::Running)
1072        rxDmaState = dmaReadWaiting;
1073    else
1074        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1075
1076    return true;
1077}
1078
1079void
1080NSGigE::rxDmaReadDone()
1081{
1082    assert(rxDmaState == dmaReading);
1083    rxDmaState = dmaIdle;
1084
1085    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
1086            rxDmaAddr, rxDmaLen);
1087    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1088
1089    // If the transmit state machine has a pending DMA, let it go first
1090    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1091        txKick();
1092
1093    rxKick();
1094}
1095
1096bool
1097NSGigE::doRxDmaWrite()
1098{
1099    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1100    rxDmaState = dmaWriting;
1101
1102    if (dmaPending() || drainState() != DrainState::Running)
1103        rxDmaState = dmaWriteWaiting;
1104    else
1105        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1106    return true;
1107}
1108
1109void
1110NSGigE::rxDmaWriteDone()
1111{
1112    assert(rxDmaState == dmaWriting);
1113    rxDmaState = dmaIdle;
1114
1115    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1116            rxDmaAddr, rxDmaLen);
1117    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1118
1119    // If the transmit state machine has a pending DMA, let it go first
1120    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1121        txKick();
1122
1123    rxKick();
1124}
1125
1126void
1127NSGigE::rxKick()
1128{
1129    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1130
1131    DPRINTF(EthernetSM,
1132            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1133            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1134
1135    Addr link, bufptr;
1136    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1137    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1138
1139  next:
1140    if (rxKickTick > curTick()) {
1141        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1142                rxKickTick);
1143
1144        goto exit;
1145    }
1146
1147    // Go to the next state machine clock tick.
1148    rxKickTick = clockEdge(Cycles(1));
1149
1150    switch(rxDmaState) {
1151      case dmaReadWaiting:
1152        if (doRxDmaRead())
1153            goto exit;
1154        break;
1155      case dmaWriteWaiting:
1156        if (doRxDmaWrite())
1157            goto exit;
1158        break;
1159      default:
1160        break;
1161    }
1162
1163    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1164    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1165
1166    // see state machine from spec for details
1167    // the way this works is, if you finish work on one state and can
1168    // go directly to another, you do that through jumping to the
1169    // label "next".  however, if you have intermediate work, like DMA
1170    // so that you can't go to the next state yet, you go to exit and
1171    // exit the loop.  however, when the DMA is done it will trigger
1172    // an event and come back to this loop.
1173    switch (rxState) {
1174      case rxIdle:
1175        if (!rxEnable) {
1176            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1177            goto exit;
1178        }
1179
1180        if (CRDD) {
1181            rxState = rxDescRefr;
1182
1183            rxDmaAddr = regs.rxdp & 0x3fffffff;
1184            rxDmaData =
1185                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1186            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1187            rxDmaFree = dmaDescFree;
1188
1189            descDmaReads++;
1190            descDmaRdBytes += rxDmaLen;
1191
1192            if (doRxDmaRead())
1193                goto exit;
1194        } else {
1195            rxState = rxDescRead;
1196
1197            rxDmaAddr = regs.rxdp & 0x3fffffff;
1198            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1199            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1200            rxDmaFree = dmaDescFree;
1201
1202            descDmaReads++;
1203            descDmaRdBytes += rxDmaLen;
1204
1205            if (doRxDmaRead())
1206                goto exit;
1207        }
1208        break;
1209
1210      case rxDescRefr:
1211        if (rxDmaState != dmaIdle)
1212            goto exit;
1213
1214        rxState = rxAdvance;
1215        break;
1216
1217     case rxDescRead:
1218        if (rxDmaState != dmaIdle)
1219            goto exit;
1220
1221        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1222                regs.rxdp & 0x3fffffff);
1223        DPRINTF(EthernetDesc,
1224                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1225                link, bufptr, cmdsts, extsts);
1226
1227        if (cmdsts & CMDSTS_OWN) {
1228            devIntrPost(ISR_RXIDLE);
1229            rxState = rxIdle;
1230            goto exit;
1231        } else {
1232            rxState = rxFifoBlock;
1233            rxFragPtr = bufptr;
1234            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1235        }
1236        break;
1237
1238      case rxFifoBlock:
1239        if (!rxPacket) {
1240            /**
1241             * @todo in reality, we should be able to start processing
1242             * the packet as it arrives, and not have to wait for the
1243             * full packet ot be in the receive fifo.
1244             */
1245            if (rxFifo.empty())
1246                goto exit;
1247
1248            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1249
1250            // If we don't have a packet, grab a new one from the fifo.
1251            rxPacket = rxFifo.front();
1252            rxPktBytes = rxPacket->length;
1253            rxPacketBufPtr = rxPacket->data;
1254
1255#if TRACING_ON
1256            if (DTRACE(Ethernet)) {
1257                IpPtr ip(rxPacket);
1258                if (ip) {
1259                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
1260                    TcpPtr tcp(ip);
1261                    if (tcp) {
1262                        DPRINTF(Ethernet,
1263                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1264                                tcp->sport(), tcp->dport(), tcp->seq(),
1265                                tcp->ack());
1266                    }
1267                }
1268            }
1269#endif
1270
1271            // sanity check - i think the driver behaves like this
1272            assert(rxDescCnt >= rxPktBytes);
1273            rxFifo.pop();
1274        }
1275
1276
1277        // dont' need the && rxDescCnt > 0 if driver sanity check
1278        // above holds
1279        if (rxPktBytes > 0) {
1280            rxState = rxFragWrite;
1281            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1282            // check holds
1283            rxXferLen = rxPktBytes;
1284
1285            rxDmaAddr = rxFragPtr & 0x3fffffff;
1286            rxDmaData = rxPacketBufPtr;
1287            rxDmaLen = rxXferLen;
1288            rxDmaFree = dmaDataFree;
1289
1290            if (doRxDmaWrite())
1291                goto exit;
1292
1293        } else {
1294            rxState = rxDescWrite;
1295
1296            //if (rxPktBytes == 0) {  /* packet is done */
1297            assert(rxPktBytes == 0);
1298            DPRINTF(EthernetSM, "done with receiving packet\n");
1299
1300            cmdsts |= CMDSTS_OWN;
1301            cmdsts &= ~CMDSTS_MORE;
1302            cmdsts |= CMDSTS_OK;
1303            cmdsts &= 0xffff0000;
1304            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1305
1306#if 0
1307            /*
1308             * all the driver uses these are for its own stats keeping
1309             * which we don't care about, aren't necessary for
1310             * functionality and doing this would just slow us down.
1311             * if they end up using this in a later version for
1312             * functional purposes, just undef
1313             */
1314            if (rxFilterEnable) {
1315                cmdsts &= ~CMDSTS_DEST_MASK;
1316                const EthAddr &dst = rxFifoFront()->dst();
1317                if (dst->unicast())
1318                    cmdsts |= CMDSTS_DEST_SELF;
1319                if (dst->multicast())
1320                    cmdsts |= CMDSTS_DEST_MULTI;
1321                if (dst->broadcast())
1322                    cmdsts |= CMDSTS_DEST_MASK;
1323            }
1324#endif
1325
1326            IpPtr ip(rxPacket);
1327            if (extstsEnable && ip) {
1328                extsts |= EXTSTS_IPPKT;
1329                rxIpChecksums++;
1330                if (cksum(ip) != 0) {
1331                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1332                    extsts |= EXTSTS_IPERR;
1333                }
1334                TcpPtr tcp(ip);
1335                UdpPtr udp(ip);
1336                if (tcp) {
1337                    extsts |= EXTSTS_TCPPKT;
1338                    rxTcpChecksums++;
1339                    if (cksum(tcp) != 0) {
1340                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1341                        extsts |= EXTSTS_TCPERR;
1342
1343                    }
1344                } else if (udp) {
1345                    extsts |= EXTSTS_UDPPKT;
1346                    rxUdpChecksums++;
1347                    if (cksum(udp) != 0) {
1348                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1349                        extsts |= EXTSTS_UDPERR;
1350                    }
1351                }
1352            }
1353            rxPacket = 0;
1354
1355            /*
1356             * the driver seems to always receive into desc buffers
1357             * of size 1514, so you never have a pkt that is split
1358             * into multiple descriptors on the receive side, so
1359             * i don't implement that case, hence the assert above.
1360             */
1361
1362            DPRINTF(EthernetDesc,
1363                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
1364                    regs.rxdp & 0x3fffffff);
1365            DPRINTF(EthernetDesc,
1366                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1367                    link, bufptr, cmdsts, extsts);
1368
1369            rxDmaAddr = regs.rxdp & 0x3fffffff;
1370            rxDmaData = &cmdsts;
1371            if (is64bit) {
1372                rxDmaAddr += offsetof(ns_desc64, cmdsts);
1373                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1374            } else {
1375                rxDmaAddr += offsetof(ns_desc32, cmdsts);
1376                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1377            }
1378            rxDmaFree = dmaDescFree;
1379
1380            descDmaWrites++;
1381            descDmaWrBytes += rxDmaLen;
1382
1383            if (doRxDmaWrite())
1384                goto exit;
1385        }
1386        break;
1387
1388      case rxFragWrite:
1389        if (rxDmaState != dmaIdle)
1390            goto exit;
1391
1392        rxPacketBufPtr += rxXferLen;
1393        rxFragPtr += rxXferLen;
1394        rxPktBytes -= rxXferLen;
1395
1396        rxState = rxFifoBlock;
1397        break;
1398
1399      case rxDescWrite:
1400        if (rxDmaState != dmaIdle)
1401            goto exit;
1402
1403        assert(cmdsts & CMDSTS_OWN);
1404
1405        assert(rxPacket == 0);
1406        devIntrPost(ISR_RXOK);
1407
1408        if (cmdsts & CMDSTS_INTR)
1409            devIntrPost(ISR_RXDESC);
1410
1411        if (!rxEnable) {
1412            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1413            rxState = rxIdle;
1414            goto exit;
1415        } else
1416            rxState = rxAdvance;
1417        break;
1418
1419      case rxAdvance:
1420        if (link == 0) {
1421            devIntrPost(ISR_RXIDLE);
1422            rxState = rxIdle;
1423            CRDD = true;
1424            goto exit;
1425        } else {
1426            if (rxDmaState != dmaIdle)
1427                goto exit;
1428            rxState = rxDescRead;
1429            regs.rxdp = link;
1430            CRDD = false;
1431
1432            rxDmaAddr = regs.rxdp & 0x3fffffff;
1433            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1434            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1435            rxDmaFree = dmaDescFree;
1436
1437            if (doRxDmaRead())
1438                goto exit;
1439        }
1440        break;
1441
1442      default:
1443        panic("Invalid rxState!");
1444    }
1445
1446    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1447            NsRxStateStrings[rxState]);
1448    goto next;
1449
1450  exit:
1451    /**
1452     * @todo do we want to schedule a future kick?
1453     */
1454    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1455            NsRxStateStrings[rxState]);
1456
1457    if (!rxKickEvent.scheduled())
1458        schedule(rxKickEvent, rxKickTick);
1459}
1460
1461void
1462NSGigE::transmit()
1463{
1464    if (txFifo.empty()) {
1465        DPRINTF(Ethernet, "nothing to transmit\n");
1466        return;
1467    }
1468
1469    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1470            txFifo.size());
1471    if (interface->sendPacket(txFifo.front())) {
1472#if TRACING_ON
1473        if (DTRACE(Ethernet)) {
1474            IpPtr ip(txFifo.front());
1475            if (ip) {
1476                DPRINTF(Ethernet, "ID is %d\n", ip->id());
1477                TcpPtr tcp(ip);
1478                if (tcp) {
1479                    DPRINTF(Ethernet,
1480                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1481                            tcp->sport(), tcp->dport(), tcp->seq(),
1482                            tcp->ack());
1483                }
1484            }
1485        }
1486#endif
1487
1488        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1489        txBytes += txFifo.front()->length;
1490        txPackets++;
1491
1492        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1493                txFifo.avail());
1494        txFifo.pop();
1495
1496        /*
1497         * normally do a writeback of the descriptor here, and ONLY
1498         * after that is done, send this interrupt.  but since our
1499         * stuff never actually fails, just do this interrupt here,
1500         * otherwise the code has to stray from this nice format.
1501         * besides, it's functionally the same.
1502         */
1503        devIntrPost(ISR_TXOK);
1504    }
1505
1506   if (!txFifo.empty() && !txEvent.scheduled()) {
1507       DPRINTF(Ethernet, "reschedule transmit\n");
1508       schedule(txEvent, curTick() + retryTime);
1509   }
1510}
1511
1512bool
1513NSGigE::doTxDmaRead()
1514{
1515    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1516    txDmaState = dmaReading;
1517
1518    if (dmaPending() || drainState() != DrainState::Running)
1519        txDmaState = dmaReadWaiting;
1520    else
1521        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1522
1523    return true;
1524}
1525
1526void
1527NSGigE::txDmaReadDone()
1528{
1529    assert(txDmaState == dmaReading);
1530    txDmaState = dmaIdle;
1531
1532    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1533            txDmaAddr, txDmaLen);
1534    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1535
1536    // If the receive state machine  has a pending DMA, let it go first
1537    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1538        rxKick();
1539
1540    txKick();
1541}
1542
1543bool
1544NSGigE::doTxDmaWrite()
1545{
1546    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1547    txDmaState = dmaWriting;
1548
1549    if (dmaPending() || drainState() != DrainState::Running)
1550        txDmaState = dmaWriteWaiting;
1551    else
1552        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1553    return true;
1554}
1555
1556void
1557NSGigE::txDmaWriteDone()
1558{
1559    assert(txDmaState == dmaWriting);
1560    txDmaState = dmaIdle;
1561
1562    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1563            txDmaAddr, txDmaLen);
1564    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1565
1566    // If the receive state machine  has a pending DMA, let it go first
1567    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1568        rxKick();
1569
1570    txKick();
1571}
1572
1573void
1574NSGigE::txKick()
1575{
1576    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1577
1578    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1579            NsTxStateStrings[txState], is64bit ? 64 : 32);
1580
1581    Addr link, bufptr;
1582    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1583    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1584
1585  next:
1586    if (txKickTick > curTick()) {
1587        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1588                txKickTick);
1589        goto exit;
1590    }
1591
1592    // Go to the next state machine clock tick.
1593    txKickTick = clockEdge(Cycles(1));
1594
1595    switch(txDmaState) {
1596      case dmaReadWaiting:
1597        if (doTxDmaRead())
1598            goto exit;
1599        break;
1600      case dmaWriteWaiting:
1601        if (doTxDmaWrite())
1602            goto exit;
1603        break;
1604      default:
1605        break;
1606    }
1607
1608    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1609    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1610    switch (txState) {
1611      case txIdle:
1612        if (!txEnable) {
1613            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1614            goto exit;
1615        }
1616
1617        if (CTDD) {
1618            txState = txDescRefr;
1619
1620            txDmaAddr = regs.txdp & 0x3fffffff;
1621            txDmaData =
1622                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1623            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1624            txDmaFree = dmaDescFree;
1625
1626            descDmaReads++;
1627            descDmaRdBytes += txDmaLen;
1628
1629            if (doTxDmaRead())
1630                goto exit;
1631
1632        } else {
1633            txState = txDescRead;
1634
1635            txDmaAddr = regs.txdp & 0x3fffffff;
1636            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1637            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1638            txDmaFree = dmaDescFree;
1639
1640            descDmaReads++;
1641            descDmaRdBytes += txDmaLen;
1642
1643            if (doTxDmaRead())
1644                goto exit;
1645        }
1646        break;
1647
1648      case txDescRefr:
1649        if (txDmaState != dmaIdle)
1650            goto exit;
1651
1652        txState = txAdvance;
1653        break;
1654
1655      case txDescRead:
1656        if (txDmaState != dmaIdle)
1657            goto exit;
1658
1659        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1660                regs.txdp & 0x3fffffff);
1661        DPRINTF(EthernetDesc,
1662                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1663                link, bufptr, cmdsts, extsts);
1664
1665        if (cmdsts & CMDSTS_OWN) {
1666            txState = txFifoBlock;
1667            txFragPtr = bufptr;
1668            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1669        } else {
1670            devIntrPost(ISR_TXIDLE);
1671            txState = txIdle;
1672            goto exit;
1673        }
1674        break;
1675
1676      case txFifoBlock:
1677        if (!txPacket) {
1678            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1679            txPacket = make_shared<EthPacketData>(16384);
1680            txPacketBufPtr = txPacket->data;
1681        }
1682
1683        if (txDescCnt == 0) {
1684            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1685            if (cmdsts & CMDSTS_MORE) {
1686                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1687                txState = txDescWrite;
1688
1689                cmdsts &= ~CMDSTS_OWN;
1690
1691                txDmaAddr = regs.txdp & 0x3fffffff;
1692                txDmaData = &cmdsts;
1693                if (is64bit) {
1694                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1695                    txDmaLen = sizeof(txDesc64.cmdsts);
1696                } else {
1697                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1698                    txDmaLen = sizeof(txDesc32.cmdsts);
1699                }
1700                txDmaFree = dmaDescFree;
1701
1702                if (doTxDmaWrite())
1703                    goto exit;
1704
1705            } else { /* this packet is totally done */
1706                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1707                /* deal with the the packet that just finished */
1708                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1709                    IpPtr ip(txPacket);
1710                    if (extsts & EXTSTS_UDPPKT) {
1711                        UdpPtr udp(ip);
1712                        if (udp) {
1713                            udp->sum(0);
1714                            udp->sum(cksum(udp));
1715                            txUdpChecksums++;
1716                        } else {
1717                            Debug::breakpoint();
1718                            warn_once("UDPPKT set, but not UDP!\n");
1719                        }
1720                    } else if (extsts & EXTSTS_TCPPKT) {
1721                        TcpPtr tcp(ip);
1722                        if (tcp) {
1723                            tcp->sum(0);
1724                            tcp->sum(cksum(tcp));
1725                            txTcpChecksums++;
1726                        } else {
1727                            warn_once("TCPPKT set, but not UDP!\n");
1728                        }
1729                    }
1730                    if (extsts & EXTSTS_IPPKT) {
1731                        if (ip) {
1732                            ip->sum(0);
1733                            ip->sum(cksum(ip));
1734                            txIpChecksums++;
1735                        } else {
1736                            warn_once("IPPKT set, but not UDP!\n");
1737                        }
1738                    }
1739                }
1740
1741                txPacket->simLength = txPacketBufPtr - txPacket->data;
1742                txPacket->length = txPacketBufPtr - txPacket->data;
1743                // this is just because the receive can't handle a
1744                // packet bigger want to make sure
1745                if (txPacket->length > 1514)
1746                    panic("transmit packet too large, %s > 1514\n",
1747                          txPacket->length);
1748
1749#ifndef NDEBUG
1750                bool success =
1751#endif
1752                    txFifo.push(txPacket);
1753                assert(success);
1754
1755                /*
1756                 * this following section is not tqo spec, but
1757                 * functionally shouldn't be any different.  normally,
1758                 * the chip will wait til the transmit has occurred
1759                 * before writing back the descriptor because it has
1760                 * to wait to see that it was successfully transmitted
1761                 * to decide whether to set CMDSTS_OK or not.
1762                 * however, in the simulator since it is always
1763                 * successfully transmitted, and writing it exactly to
1764                 * spec would complicate the code, we just do it here
1765                 */
1766
1767                cmdsts &= ~CMDSTS_OWN;
1768                cmdsts |= CMDSTS_OK;
1769
1770                DPRINTF(EthernetDesc,
1771                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1772                        cmdsts, extsts);
1773
1774                txDmaFree = dmaDescFree;
1775                txDmaAddr = regs.txdp & 0x3fffffff;
1776                txDmaData = &cmdsts;
1777                if (is64bit) {
1778                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1779                    txDmaLen =
1780                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1781                } else {
1782                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1783                    txDmaLen =
1784                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1785                }
1786
1787                descDmaWrites++;
1788                descDmaWrBytes += txDmaLen;
1789
1790                transmit();
1791                txPacket = 0;
1792
1793                if (!txEnable) {
1794                    DPRINTF(EthernetSM, "halting TX state machine\n");
1795                    txState = txIdle;
1796                    goto exit;
1797                } else
1798                    txState = txAdvance;
1799
1800                if (doTxDmaWrite())
1801                    goto exit;
1802            }
1803        } else {
1804            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1805            if (!txFifo.full()) {
1806                txState = txFragRead;
1807
1808                /*
1809                 * The number of bytes transferred is either whatever
1810                 * is left in the descriptor (txDescCnt), or if there
1811                 * is not enough room in the fifo, just whatever room
1812                 * is left in the fifo
1813                 */
1814                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1815
1816                txDmaAddr = txFragPtr & 0x3fffffff;
1817                txDmaData = txPacketBufPtr;
1818                txDmaLen = txXferLen;
1819                txDmaFree = dmaDataFree;
1820
1821                if (doTxDmaRead())
1822                    goto exit;
1823            } else {
1824                txState = txFifoBlock;
1825                transmit();
1826
1827                goto exit;
1828            }
1829
1830        }
1831        break;
1832
1833      case txFragRead:
1834        if (txDmaState != dmaIdle)
1835            goto exit;
1836
1837        txPacketBufPtr += txXferLen;
1838        txFragPtr += txXferLen;
1839        txDescCnt -= txXferLen;
1840        txFifo.reserve(txXferLen);
1841
1842        txState = txFifoBlock;
1843        break;
1844
1845      case txDescWrite:
1846        if (txDmaState != dmaIdle)
1847            goto exit;
1848
1849        if (cmdsts & CMDSTS_INTR)
1850            devIntrPost(ISR_TXDESC);
1851
1852        if (!txEnable) {
1853            DPRINTF(EthernetSM, "halting TX state machine\n");
1854            txState = txIdle;
1855            goto exit;
1856        } else
1857            txState = txAdvance;
1858        break;
1859
1860      case txAdvance:
1861        if (link == 0) {
1862            devIntrPost(ISR_TXIDLE);
1863            txState = txIdle;
1864            goto exit;
1865        } else {
1866            if (txDmaState != dmaIdle)
1867                goto exit;
1868            txState = txDescRead;
1869            regs.txdp = link;
1870            CTDD = false;
1871
1872            txDmaAddr = link & 0x3fffffff;
1873            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1874            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1875            txDmaFree = dmaDescFree;
1876
1877            if (doTxDmaRead())
1878                goto exit;
1879        }
1880        break;
1881
1882      default:
1883        panic("invalid state");
1884    }
1885
1886    DPRINTF(EthernetSM, "entering next txState=%s\n",
1887            NsTxStateStrings[txState]);
1888    goto next;
1889
1890  exit:
1891    /**
1892     * @todo do we want to schedule a future kick?
1893     */
1894    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1895            NsTxStateStrings[txState]);
1896
1897    if (!txKickEvent.scheduled())
1898        schedule(txKickEvent, txKickTick);
1899}
1900
1901/**
1902 * Advance the EEPROM state machine
1903 * Called on rising edge of EEPROM clock bit in MEAR
1904 */
1905void
1906NSGigE::eepromKick()
1907{
1908    switch (eepromState) {
1909
1910      case eepromStart:
1911
1912        // Wait for start bit
1913        if (regs.mear & MEAR_EEDI) {
1914            // Set up to get 2 opcode bits
1915            eepromState = eepromGetOpcode;
1916            eepromBitsToRx = 2;
1917            eepromOpcode = 0;
1918        }
1919        break;
1920
1921      case eepromGetOpcode:
1922        eepromOpcode <<= 1;
1923        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1924        --eepromBitsToRx;
1925
1926        // Done getting opcode
1927        if (eepromBitsToRx == 0) {
1928            if (eepromOpcode != EEPROM_READ)
1929                panic("only EEPROM reads are implemented!");
1930
1931            // Set up to get address
1932            eepromState = eepromGetAddress;
1933            eepromBitsToRx = 6;
1934            eepromAddress = 0;
1935        }
1936        break;
1937
1938      case eepromGetAddress:
1939        eepromAddress <<= 1;
1940        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1941        --eepromBitsToRx;
1942
1943        // Done getting address
1944        if (eepromBitsToRx == 0) {
1945
1946            if (eepromAddress >= EEPROM_SIZE)
1947                panic("EEPROM read access out of range!");
1948
1949            switch (eepromAddress) {
1950
1951              case EEPROM_PMATCH2_ADDR:
1952                eepromData = rom.perfectMatch[5];
1953                eepromData <<= 8;
1954                eepromData += rom.perfectMatch[4];
1955                break;
1956
1957              case EEPROM_PMATCH1_ADDR:
1958                eepromData = rom.perfectMatch[3];
1959                eepromData <<= 8;
1960                eepromData += rom.perfectMatch[2];
1961                break;
1962
1963              case EEPROM_PMATCH0_ADDR:
1964                eepromData = rom.perfectMatch[1];
1965                eepromData <<= 8;
1966                eepromData += rom.perfectMatch[0];
1967                break;
1968
1969              default:
1970                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1971            }
1972            // Set up to read data
1973            eepromState = eepromRead;
1974            eepromBitsToRx = 16;
1975
1976            // Clear data in bit
1977            regs.mear &= ~MEAR_EEDI;
1978        }
1979        break;
1980
1981      case eepromRead:
1982        // Clear Data Out bit
1983        regs.mear &= ~MEAR_EEDO;
1984        // Set bit to value of current EEPROM bit
1985        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1986
1987        eepromData <<= 1;
1988        --eepromBitsToRx;
1989
1990        // All done
1991        if (eepromBitsToRx == 0) {
1992            eepromState = eepromStart;
1993        }
1994        break;
1995
1996      default:
1997        panic("invalid EEPROM state");
1998    }
1999
2000}
2001
2002void
2003NSGigE::transferDone()
2004{
2005    if (txFifo.empty()) {
2006        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2007        return;
2008    }
2009
2010    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2011
2012    reschedule(txEvent, clockEdge(Cycles(1)), true);
2013}
2014
2015bool
2016NSGigE::rxFilter(const EthPacketPtr &packet)
2017{
2018    EthPtr eth = packet;
2019    bool drop = true;
2020    string type;
2021
2022    const EthAddr &dst = eth->dst();
2023    if (dst.unicast()) {
2024        // If we're accepting all unicast addresses
2025        if (acceptUnicast)
2026            drop = false;
2027
2028        // If we make a perfect match
2029        if (acceptPerfect && dst == rom.perfectMatch)
2030            drop = false;
2031
2032        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2033            drop = false;
2034
2035    } else if (dst.broadcast()) {
2036        // if we're accepting broadcasts
2037        if (acceptBroadcast)
2038            drop = false;
2039
2040    } else if (dst.multicast()) {
2041        // if we're accepting all multicasts
2042        if (acceptMulticast)
2043            drop = false;
2044
2045        // Multicast hashing faked - all packets accepted
2046        if (multicastHashEnable)
2047            drop = false;
2048    }
2049
2050    if (drop) {
2051        DPRINTF(Ethernet, "rxFilter drop\n");
2052        DDUMP(EthernetData, packet->data, packet->length);
2053    }
2054
2055    return drop;
2056}
2057
2058bool
2059NSGigE::recvPacket(EthPacketPtr packet)
2060{
2061    rxBytes += packet->length;
2062    rxPackets++;
2063
2064    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2065            rxFifo.avail());
2066
2067    if (!rxEnable) {
2068        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2069        return true;
2070    }
2071
2072    if (!rxFilterEnable) {
2073        DPRINTF(Ethernet,
2074            "receive packet filtering disabled . . . packet dropped\n");
2075        return true;
2076    }
2077
2078    if (rxFilter(packet)) {
2079        DPRINTF(Ethernet, "packet filtered...dropped\n");
2080        return true;
2081    }
2082
2083    if (rxFifo.avail() < packet->length) {
2084#if TRACING_ON
2085        IpPtr ip(packet);
2086        TcpPtr tcp(ip);
2087        if (ip) {
2088            DPRINTF(Ethernet,
2089                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
2090                    ip->id());
2091            if (tcp) {
2092                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2093            }
2094        }
2095#endif
2096        droppedPackets++;
2097        devIntrPost(ISR_RXORN);
2098        return false;
2099    }
2100
2101    rxFifo.push(packet);
2102
2103    rxKick();
2104    return true;
2105}
2106
2107
2108void
2109NSGigE::drainResume()
2110{
2111    Drainable::drainResume();
2112
2113    // During drain we could have left the state machines in a waiting state and
2114    // they wouldn't get out until some other event occured to kick them.
2115    // This way they'll get out immediately
2116    txKick();
2117    rxKick();
2118}
2119
2120
2121//=====================================================================
2122//
2123//
2124void
2125NSGigE::serialize(CheckpointOut &cp) const
2126{
2127    // Serialize the PciDevice base class
2128    PciDevice::serialize(cp);
2129
2130    /*
2131     * Finalize any DMA events now.
2132     */
2133    // @todo will mem system save pending dma?
2134
2135    /*
2136     * Serialize the device registers
2137     */
2138    SERIALIZE_SCALAR(regs.command);
2139    SERIALIZE_SCALAR(regs.config);
2140    SERIALIZE_SCALAR(regs.mear);
2141    SERIALIZE_SCALAR(regs.ptscr);
2142    SERIALIZE_SCALAR(regs.isr);
2143    SERIALIZE_SCALAR(regs.imr);
2144    SERIALIZE_SCALAR(regs.ier);
2145    SERIALIZE_SCALAR(regs.ihr);
2146    SERIALIZE_SCALAR(regs.txdp);
2147    SERIALIZE_SCALAR(regs.txdp_hi);
2148    SERIALIZE_SCALAR(regs.txcfg);
2149    SERIALIZE_SCALAR(regs.gpior);
2150    SERIALIZE_SCALAR(regs.rxdp);
2151    SERIALIZE_SCALAR(regs.rxdp_hi);
2152    SERIALIZE_SCALAR(regs.rxcfg);
2153    SERIALIZE_SCALAR(regs.pqcr);
2154    SERIALIZE_SCALAR(regs.wcsr);
2155    SERIALIZE_SCALAR(regs.pcr);
2156    SERIALIZE_SCALAR(regs.rfcr);
2157    SERIALIZE_SCALAR(regs.rfdr);
2158    SERIALIZE_SCALAR(regs.brar);
2159    SERIALIZE_SCALAR(regs.brdr);
2160    SERIALIZE_SCALAR(regs.srr);
2161    SERIALIZE_SCALAR(regs.mibc);
2162    SERIALIZE_SCALAR(regs.vrcr);
2163    SERIALIZE_SCALAR(regs.vtcr);
2164    SERIALIZE_SCALAR(regs.vdr);
2165    SERIALIZE_SCALAR(regs.ccsr);
2166    SERIALIZE_SCALAR(regs.tbicr);
2167    SERIALIZE_SCALAR(regs.tbisr);
2168    SERIALIZE_SCALAR(regs.tanar);
2169    SERIALIZE_SCALAR(regs.tanlpar);
2170    SERIALIZE_SCALAR(regs.taner);
2171    SERIALIZE_SCALAR(regs.tesr);
2172
2173    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2174    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2175
2176    SERIALIZE_SCALAR(ioEnable);
2177
2178    /*
2179     * Serialize the data Fifos
2180     */
2181    rxFifo.serialize("rxFifo", cp);
2182    txFifo.serialize("txFifo", cp);
2183
2184    /*
2185     * Serialize the various helper variables
2186     */
2187    bool txPacketExists = txPacket != nullptr;
2188    SERIALIZE_SCALAR(txPacketExists);
2189    if (txPacketExists) {
2190        txPacket->simLength = txPacketBufPtr - txPacket->data;
2191        txPacket->length = txPacketBufPtr - txPacket->data;
2192        txPacket->serialize("txPacket", cp);
2193        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2194        SERIALIZE_SCALAR(txPktBufPtr);
2195    }
2196
2197    bool rxPacketExists = rxPacket != nullptr;
2198    SERIALIZE_SCALAR(rxPacketExists);
2199    if (rxPacketExists) {
2200        rxPacket->serialize("rxPacket", cp);
2201        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2202        SERIALIZE_SCALAR(rxPktBufPtr);
2203    }
2204
2205    SERIALIZE_SCALAR(txXferLen);
2206    SERIALIZE_SCALAR(rxXferLen);
2207
2208    /*
2209     * Serialize Cached Descriptors
2210     */
2211    SERIALIZE_SCALAR(rxDesc64.link);
2212    SERIALIZE_SCALAR(rxDesc64.bufptr);
2213    SERIALIZE_SCALAR(rxDesc64.cmdsts);
2214    SERIALIZE_SCALAR(rxDesc64.extsts);
2215    SERIALIZE_SCALAR(txDesc64.link);
2216    SERIALIZE_SCALAR(txDesc64.bufptr);
2217    SERIALIZE_SCALAR(txDesc64.cmdsts);
2218    SERIALIZE_SCALAR(txDesc64.extsts);
2219    SERIALIZE_SCALAR(rxDesc32.link);
2220    SERIALIZE_SCALAR(rxDesc32.bufptr);
2221    SERIALIZE_SCALAR(rxDesc32.cmdsts);
2222    SERIALIZE_SCALAR(rxDesc32.extsts);
2223    SERIALIZE_SCALAR(txDesc32.link);
2224    SERIALIZE_SCALAR(txDesc32.bufptr);
2225    SERIALIZE_SCALAR(txDesc32.cmdsts);
2226    SERIALIZE_SCALAR(txDesc32.extsts);
2227    SERIALIZE_SCALAR(extstsEnable);
2228
2229    /*
2230     * Serialize tx state machine
2231     */
2232    int txState = this->txState;
2233    SERIALIZE_SCALAR(txState);
2234    SERIALIZE_SCALAR(txEnable);
2235    SERIALIZE_SCALAR(CTDD);
2236    SERIALIZE_SCALAR(txFragPtr);
2237    SERIALIZE_SCALAR(txDescCnt);
2238    int txDmaState = this->txDmaState;
2239    SERIALIZE_SCALAR(txDmaState);
2240    SERIALIZE_SCALAR(txKickTick);
2241
2242    /*
2243     * Serialize rx state machine
2244     */
2245    int rxState = this->rxState;
2246    SERIALIZE_SCALAR(rxState);
2247    SERIALIZE_SCALAR(rxEnable);
2248    SERIALIZE_SCALAR(CRDD);
2249    SERIALIZE_SCALAR(rxPktBytes);
2250    SERIALIZE_SCALAR(rxFragPtr);
2251    SERIALIZE_SCALAR(rxDescCnt);
2252    int rxDmaState = this->rxDmaState;
2253    SERIALIZE_SCALAR(rxDmaState);
2254    SERIALIZE_SCALAR(rxKickTick);
2255
2256    /*
2257     * Serialize EEPROM state machine
2258     */
2259    int eepromState = this->eepromState;
2260    SERIALIZE_SCALAR(eepromState);
2261    SERIALIZE_SCALAR(eepromClk);
2262    SERIALIZE_SCALAR(eepromBitsToRx);
2263    SERIALIZE_SCALAR(eepromOpcode);
2264    SERIALIZE_SCALAR(eepromAddress);
2265    SERIALIZE_SCALAR(eepromData);
2266
2267    /*
2268     * If there's a pending transmit, store the time so we can
2269     * reschedule it later
2270     */
2271    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2272    SERIALIZE_SCALAR(transmitTick);
2273
2274    /*
2275     * receive address filter settings
2276     */
2277    SERIALIZE_SCALAR(rxFilterEnable);
2278    SERIALIZE_SCALAR(acceptBroadcast);
2279    SERIALIZE_SCALAR(acceptMulticast);
2280    SERIALIZE_SCALAR(acceptUnicast);
2281    SERIALIZE_SCALAR(acceptPerfect);
2282    SERIALIZE_SCALAR(acceptArp);
2283    SERIALIZE_SCALAR(multicastHashEnable);
2284
2285    /*
2286     * Keep track of pending interrupt status.
2287     */
2288    SERIALIZE_SCALAR(intrTick);
2289    SERIALIZE_SCALAR(cpuPendingIntr);
2290    Tick intrEventTick = 0;
2291    if (intrEvent)
2292        intrEventTick = intrEvent->when();
2293    SERIALIZE_SCALAR(intrEventTick);
2294
2295}
2296
2297void
2298NSGigE::unserialize(CheckpointIn &cp)
2299{
2300    // Unserialize the PciDevice base class
2301    PciDevice::unserialize(cp);
2302
2303    UNSERIALIZE_SCALAR(regs.command);
2304    UNSERIALIZE_SCALAR(regs.config);
2305    UNSERIALIZE_SCALAR(regs.mear);
2306    UNSERIALIZE_SCALAR(regs.ptscr);
2307    UNSERIALIZE_SCALAR(regs.isr);
2308    UNSERIALIZE_SCALAR(regs.imr);
2309    UNSERIALIZE_SCALAR(regs.ier);
2310    UNSERIALIZE_SCALAR(regs.ihr);
2311    UNSERIALIZE_SCALAR(regs.txdp);
2312    UNSERIALIZE_SCALAR(regs.txdp_hi);
2313    UNSERIALIZE_SCALAR(regs.txcfg);
2314    UNSERIALIZE_SCALAR(regs.gpior);
2315    UNSERIALIZE_SCALAR(regs.rxdp);
2316    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2317    UNSERIALIZE_SCALAR(regs.rxcfg);
2318    UNSERIALIZE_SCALAR(regs.pqcr);
2319    UNSERIALIZE_SCALAR(regs.wcsr);
2320    UNSERIALIZE_SCALAR(regs.pcr);
2321    UNSERIALIZE_SCALAR(regs.rfcr);
2322    UNSERIALIZE_SCALAR(regs.rfdr);
2323    UNSERIALIZE_SCALAR(regs.brar);
2324    UNSERIALIZE_SCALAR(regs.brdr);
2325    UNSERIALIZE_SCALAR(regs.srr);
2326    UNSERIALIZE_SCALAR(regs.mibc);
2327    UNSERIALIZE_SCALAR(regs.vrcr);
2328    UNSERIALIZE_SCALAR(regs.vtcr);
2329    UNSERIALIZE_SCALAR(regs.vdr);
2330    UNSERIALIZE_SCALAR(regs.ccsr);
2331    UNSERIALIZE_SCALAR(regs.tbicr);
2332    UNSERIALIZE_SCALAR(regs.tbisr);
2333    UNSERIALIZE_SCALAR(regs.tanar);
2334    UNSERIALIZE_SCALAR(regs.tanlpar);
2335    UNSERIALIZE_SCALAR(regs.taner);
2336    UNSERIALIZE_SCALAR(regs.tesr);
2337
2338    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2339    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2340
2341    UNSERIALIZE_SCALAR(ioEnable);
2342
2343    /*
2344     * unserialize the data fifos
2345     */
2346    rxFifo.unserialize("rxFifo", cp);
2347    txFifo.unserialize("txFifo", cp);
2348
2349    /*
2350     * unserialize the various helper variables
2351     */
2352    bool txPacketExists;
2353    UNSERIALIZE_SCALAR(txPacketExists);
2354    if (txPacketExists) {
2355        txPacket = make_shared<EthPacketData>();
2356        txPacket->unserialize("txPacket", cp);
2357        uint32_t txPktBufPtr;
2358        UNSERIALIZE_SCALAR(txPktBufPtr);
2359        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2360    } else
2361        txPacket = 0;
2362
2363    bool rxPacketExists;
2364    UNSERIALIZE_SCALAR(rxPacketExists);
2365    rxPacket = 0;
2366    if (rxPacketExists) {
2367        rxPacket = make_shared<EthPacketData>();
2368        rxPacket->unserialize("rxPacket", cp);
2369        uint32_t rxPktBufPtr;
2370        UNSERIALIZE_SCALAR(rxPktBufPtr);
2371        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2372    } else
2373        rxPacket = 0;
2374
2375    UNSERIALIZE_SCALAR(txXferLen);
2376    UNSERIALIZE_SCALAR(rxXferLen);
2377
2378    /*
2379     * Unserialize Cached Descriptors
2380     */
2381    UNSERIALIZE_SCALAR(rxDesc64.link);
2382    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2383    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2384    UNSERIALIZE_SCALAR(rxDesc64.extsts);
2385    UNSERIALIZE_SCALAR(txDesc64.link);
2386    UNSERIALIZE_SCALAR(txDesc64.bufptr);
2387    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2388    UNSERIALIZE_SCALAR(txDesc64.extsts);
2389    UNSERIALIZE_SCALAR(rxDesc32.link);
2390    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2391    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2392    UNSERIALIZE_SCALAR(rxDesc32.extsts);
2393    UNSERIALIZE_SCALAR(txDesc32.link);
2394    UNSERIALIZE_SCALAR(txDesc32.bufptr);
2395    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2396    UNSERIALIZE_SCALAR(txDesc32.extsts);
2397    UNSERIALIZE_SCALAR(extstsEnable);
2398
2399    /*
2400     * unserialize tx state machine
2401     */
2402    int txState;
2403    UNSERIALIZE_SCALAR(txState);
2404    this->txState = (TxState) txState;
2405    UNSERIALIZE_SCALAR(txEnable);
2406    UNSERIALIZE_SCALAR(CTDD);
2407    UNSERIALIZE_SCALAR(txFragPtr);
2408    UNSERIALIZE_SCALAR(txDescCnt);
2409    int txDmaState;
2410    UNSERIALIZE_SCALAR(txDmaState);
2411    this->txDmaState = (DmaState) txDmaState;
2412    UNSERIALIZE_SCALAR(txKickTick);
2413    if (txKickTick)
2414        schedule(txKickEvent, txKickTick);
2415
2416    /*
2417     * unserialize rx state machine
2418     */
2419    int rxState;
2420    UNSERIALIZE_SCALAR(rxState);
2421    this->rxState = (RxState) rxState;
2422    UNSERIALIZE_SCALAR(rxEnable);
2423    UNSERIALIZE_SCALAR(CRDD);
2424    UNSERIALIZE_SCALAR(rxPktBytes);
2425    UNSERIALIZE_SCALAR(rxFragPtr);
2426    UNSERIALIZE_SCALAR(rxDescCnt);
2427    int rxDmaState;
2428    UNSERIALIZE_SCALAR(rxDmaState);
2429    this->rxDmaState = (DmaState) rxDmaState;
2430    UNSERIALIZE_SCALAR(rxKickTick);
2431    if (rxKickTick)
2432        schedule(rxKickEvent, rxKickTick);
2433
2434    /*
2435     * Unserialize EEPROM state machine
2436     */
2437    int eepromState;
2438    UNSERIALIZE_SCALAR(eepromState);
2439    this->eepromState = (EEPROMState) eepromState;
2440    UNSERIALIZE_SCALAR(eepromClk);
2441    UNSERIALIZE_SCALAR(eepromBitsToRx);
2442    UNSERIALIZE_SCALAR(eepromOpcode);
2443    UNSERIALIZE_SCALAR(eepromAddress);
2444    UNSERIALIZE_SCALAR(eepromData);
2445
2446    /*
2447     * If there's a pending transmit, reschedule it now
2448     */
2449    Tick transmitTick;
2450    UNSERIALIZE_SCALAR(transmitTick);
2451    if (transmitTick)
2452        schedule(txEvent, curTick() + transmitTick);
2453
2454    /*
2455     * unserialize receive address filter settings
2456     */
2457    UNSERIALIZE_SCALAR(rxFilterEnable);
2458    UNSERIALIZE_SCALAR(acceptBroadcast);
2459    UNSERIALIZE_SCALAR(acceptMulticast);
2460    UNSERIALIZE_SCALAR(acceptUnicast);
2461    UNSERIALIZE_SCALAR(acceptPerfect);
2462    UNSERIALIZE_SCALAR(acceptArp);
2463    UNSERIALIZE_SCALAR(multicastHashEnable);
2464
2465    /*
2466     * Keep track of pending interrupt status.
2467     */
2468    UNSERIALIZE_SCALAR(intrTick);
2469    UNSERIALIZE_SCALAR(cpuPendingIntr);
2470    Tick intrEventTick;
2471    UNSERIALIZE_SCALAR(intrEventTick);
2472    if (intrEventTick) {
2473        intrEvent = new IntrEvent(this, true);
2474        schedule(intrEvent, intrEventTick);
2475    }
2476}
2477
2478NSGigE *
2479NSGigEParams::create()
2480{
2481    return new NSGigE(this);
2482}
2483