ns_gige.cc revision 11263:8dcc6b40f164
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        Debug::breakpoint();
955        intrTick = curTick();
956    }
957
958    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
959            intrTick);
960
961    if (intrEvent)
962        intrEvent->squash();
963    intrEvent = new IntrEvent(this, true);
964    schedule(intrEvent, intrTick);
965}
966
967void
968NSGigE::cpuInterrupt()
969{
970    assert(intrTick == curTick());
971
972    // Whether or not there's a pending interrupt, we don't care about
973    // it anymore
974    intrEvent = 0;
975    intrTick = 0;
976
977    // Don't send an interrupt if there's already one
978    if (cpuPendingIntr) {
979        DPRINTF(EthernetIntr,
980                "would send an interrupt now, but there's already pending\n");
981    } else {
982        // Send interrupt
983        cpuPendingIntr = true;
984
985        DPRINTF(EthernetIntr, "posting interrupt\n");
986        intrPost();
987    }
988}
989
990void
991NSGigE::cpuIntrClear()
992{
993    if (!cpuPendingIntr)
994        return;
995
996    if (intrEvent) {
997        intrEvent->squash();
998        intrEvent = 0;
999    }
1000
1001    intrTick = 0;
1002
1003    cpuPendingIntr = false;
1004
1005    DPRINTF(EthernetIntr, "clearing interrupt\n");
1006    intrClear();
1007}
1008
1009bool
1010NSGigE::cpuIntrPending() const
1011{ return cpuPendingIntr; }
1012
1013void
1014NSGigE::txReset()
1015{
1016
1017    DPRINTF(Ethernet, "transmit reset\n");
1018
1019    CTDD = false;
1020    txEnable = false;;
1021    txFragPtr = 0;
1022    assert(txDescCnt == 0);
1023    txFifo.clear();
1024    txState = txIdle;
1025    assert(txDmaState == dmaIdle);
1026}
1027
1028void
1029NSGigE::rxReset()
1030{
1031    DPRINTF(Ethernet, "receive reset\n");
1032
1033    CRDD = false;
1034    assert(rxPktBytes == 0);
1035    rxEnable = false;
1036    rxFragPtr = 0;
1037    assert(rxDescCnt == 0);
1038    assert(rxDmaState == dmaIdle);
1039    rxFifo.clear();
1040    rxState = rxIdle;
1041}
1042
1043void
1044NSGigE::regsReset()
1045{
1046    memset(&regs, 0, sizeof(regs));
1047    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1048    regs.mear = 0x12;
1049    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1050                        // fill threshold to 32 bytes
1051    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
1052    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
1053    regs.mibc = MIBC_FRZ;
1054    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
1055    regs.tesr = 0xc000; // TBI capable of both full and half duplex
1056    regs.brar = 0xffffffff;
1057
1058    extstsEnable = false;
1059    acceptBroadcast = false;
1060    acceptMulticast = false;
1061    acceptUnicast = false;
1062    acceptPerfect = false;
1063    acceptArp = false;
1064}
1065
1066bool
1067NSGigE::doRxDmaRead()
1068{
1069    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1070    rxDmaState = dmaReading;
1071
1072    if (dmaPending() || drainState() != DrainState::Running)
1073        rxDmaState = dmaReadWaiting;
1074    else
1075        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1076
1077    return true;
1078}
1079
1080void
1081NSGigE::rxDmaReadDone()
1082{
1083    assert(rxDmaState == dmaReading);
1084    rxDmaState = dmaIdle;
1085
1086    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
1087            rxDmaAddr, rxDmaLen);
1088    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1089
1090    // If the transmit state machine has a pending DMA, let it go first
1091    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1092        txKick();
1093
1094    rxKick();
1095}
1096
1097bool
1098NSGigE::doRxDmaWrite()
1099{
1100    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1101    rxDmaState = dmaWriting;
1102
1103    if (dmaPending() || drainState() != DrainState::Running)
1104        rxDmaState = dmaWriteWaiting;
1105    else
1106        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1107    return true;
1108}
1109
1110void
1111NSGigE::rxDmaWriteDone()
1112{
1113    assert(rxDmaState == dmaWriting);
1114    rxDmaState = dmaIdle;
1115
1116    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1117            rxDmaAddr, rxDmaLen);
1118    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1119
1120    // If the transmit state machine has a pending DMA, let it go first
1121    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1122        txKick();
1123
1124    rxKick();
1125}
1126
1127void
1128NSGigE::rxKick()
1129{
1130    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1131
1132    DPRINTF(EthernetSM,
1133            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1134            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1135
1136    Addr link, bufptr;
1137    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1138    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1139
1140  next:
1141    if (rxKickTick > curTick()) {
1142        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1143                rxKickTick);
1144
1145        goto exit;
1146    }
1147
1148    // Go to the next state machine clock tick.
1149    rxKickTick = clockEdge(Cycles(1));
1150
1151    switch(rxDmaState) {
1152      case dmaReadWaiting:
1153        if (doRxDmaRead())
1154            goto exit;
1155        break;
1156      case dmaWriteWaiting:
1157        if (doRxDmaWrite())
1158            goto exit;
1159        break;
1160      default:
1161        break;
1162    }
1163
1164    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1165    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1166
1167    // see state machine from spec for details
1168    // the way this works is, if you finish work on one state and can
1169    // go directly to another, you do that through jumping to the
1170    // label "next".  however, if you have intermediate work, like DMA
1171    // so that you can't go to the next state yet, you go to exit and
1172    // exit the loop.  however, when the DMA is done it will trigger
1173    // an event and come back to this loop.
1174    switch (rxState) {
1175      case rxIdle:
1176        if (!rxEnable) {
1177            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1178            goto exit;
1179        }
1180
1181        if (CRDD) {
1182            rxState = rxDescRefr;
1183
1184            rxDmaAddr = regs.rxdp & 0x3fffffff;
1185            rxDmaData =
1186                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1187            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1188            rxDmaFree = dmaDescFree;
1189
1190            descDmaReads++;
1191            descDmaRdBytes += rxDmaLen;
1192
1193            if (doRxDmaRead())
1194                goto exit;
1195        } else {
1196            rxState = rxDescRead;
1197
1198            rxDmaAddr = regs.rxdp & 0x3fffffff;
1199            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1200            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1201            rxDmaFree = dmaDescFree;
1202
1203            descDmaReads++;
1204            descDmaRdBytes += rxDmaLen;
1205
1206            if (doRxDmaRead())
1207                goto exit;
1208        }
1209        break;
1210
1211      case rxDescRefr:
1212        if (rxDmaState != dmaIdle)
1213            goto exit;
1214
1215        rxState = rxAdvance;
1216        break;
1217
1218     case rxDescRead:
1219        if (rxDmaState != dmaIdle)
1220            goto exit;
1221
1222        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1223                regs.rxdp & 0x3fffffff);
1224        DPRINTF(EthernetDesc,
1225                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1226                link, bufptr, cmdsts, extsts);
1227
1228        if (cmdsts & CMDSTS_OWN) {
1229            devIntrPost(ISR_RXIDLE);
1230            rxState = rxIdle;
1231            goto exit;
1232        } else {
1233            rxState = rxFifoBlock;
1234            rxFragPtr = bufptr;
1235            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1236        }
1237        break;
1238
1239      case rxFifoBlock:
1240        if (!rxPacket) {
1241            /**
1242             * @todo in reality, we should be able to start processing
1243             * the packet as it arrives, and not have to wait for the
1244             * full packet ot be in the receive fifo.
1245             */
1246            if (rxFifo.empty())
1247                goto exit;
1248
1249            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1250
1251            // If we don't have a packet, grab a new one from the fifo.
1252            rxPacket = rxFifo.front();
1253            rxPktBytes = rxPacket->length;
1254            rxPacketBufPtr = rxPacket->data;
1255
1256#if TRACING_ON
1257            if (DTRACE(Ethernet)) {
1258                IpPtr ip(rxPacket);
1259                if (ip) {
1260                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
1261                    TcpPtr tcp(ip);
1262                    if (tcp) {
1263                        DPRINTF(Ethernet,
1264                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1265                                tcp->sport(), tcp->dport(), tcp->seq(),
1266                                tcp->ack());
1267                    }
1268                }
1269            }
1270#endif
1271
1272            // sanity check - i think the driver behaves like this
1273            assert(rxDescCnt >= rxPktBytes);
1274            rxFifo.pop();
1275        }
1276
1277
1278        // dont' need the && rxDescCnt > 0 if driver sanity check
1279        // above holds
1280        if (rxPktBytes > 0) {
1281            rxState = rxFragWrite;
1282            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1283            // check holds
1284            rxXferLen = rxPktBytes;
1285
1286            rxDmaAddr = rxFragPtr & 0x3fffffff;
1287            rxDmaData = rxPacketBufPtr;
1288            rxDmaLen = rxXferLen;
1289            rxDmaFree = dmaDataFree;
1290
1291            if (doRxDmaWrite())
1292                goto exit;
1293
1294        } else {
1295            rxState = rxDescWrite;
1296
1297            //if (rxPktBytes == 0) {  /* packet is done */
1298            assert(rxPktBytes == 0);
1299            DPRINTF(EthernetSM, "done with receiving packet\n");
1300
1301            cmdsts |= CMDSTS_OWN;
1302            cmdsts &= ~CMDSTS_MORE;
1303            cmdsts |= CMDSTS_OK;
1304            cmdsts &= 0xffff0000;
1305            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1306
1307#if 0
1308            /*
1309             * all the driver uses these are for its own stats keeping
1310             * which we don't care about, aren't necessary for
1311             * functionality and doing this would just slow us down.
1312             * if they end up using this in a later version for
1313             * functional purposes, just undef
1314             */
1315            if (rxFilterEnable) {
1316                cmdsts &= ~CMDSTS_DEST_MASK;
1317                const EthAddr &dst = rxFifoFront()->dst();
1318                if (dst->unicast())
1319                    cmdsts |= CMDSTS_DEST_SELF;
1320                if (dst->multicast())
1321                    cmdsts |= CMDSTS_DEST_MULTI;
1322                if (dst->broadcast())
1323                    cmdsts |= CMDSTS_DEST_MASK;
1324            }
1325#endif
1326
1327            IpPtr ip(rxPacket);
1328            if (extstsEnable && ip) {
1329                extsts |= EXTSTS_IPPKT;
1330                rxIpChecksums++;
1331                if (cksum(ip) != 0) {
1332                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1333                    extsts |= EXTSTS_IPERR;
1334                }
1335                TcpPtr tcp(ip);
1336                UdpPtr udp(ip);
1337                if (tcp) {
1338                    extsts |= EXTSTS_TCPPKT;
1339                    rxTcpChecksums++;
1340                    if (cksum(tcp) != 0) {
1341                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1342                        extsts |= EXTSTS_TCPERR;
1343
1344                    }
1345                } else if (udp) {
1346                    extsts |= EXTSTS_UDPPKT;
1347                    rxUdpChecksums++;
1348                    if (cksum(udp) != 0) {
1349                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1350                        extsts |= EXTSTS_UDPERR;
1351                    }
1352                }
1353            }
1354            rxPacket = 0;
1355
1356            /*
1357             * the driver seems to always receive into desc buffers
1358             * of size 1514, so you never have a pkt that is split
1359             * into multiple descriptors on the receive side, so
1360             * i don't implement that case, hence the assert above.
1361             */
1362
1363            DPRINTF(EthernetDesc,
1364                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
1365                    regs.rxdp & 0x3fffffff);
1366            DPRINTF(EthernetDesc,
1367                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1368                    link, bufptr, cmdsts, extsts);
1369
1370            rxDmaAddr = regs.rxdp & 0x3fffffff;
1371            rxDmaData = &cmdsts;
1372            if (is64bit) {
1373                rxDmaAddr += offsetof(ns_desc64, cmdsts);
1374                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1375            } else {
1376                rxDmaAddr += offsetof(ns_desc32, cmdsts);
1377                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1378            }
1379            rxDmaFree = dmaDescFree;
1380
1381            descDmaWrites++;
1382            descDmaWrBytes += rxDmaLen;
1383
1384            if (doRxDmaWrite())
1385                goto exit;
1386        }
1387        break;
1388
1389      case rxFragWrite:
1390        if (rxDmaState != dmaIdle)
1391            goto exit;
1392
1393        rxPacketBufPtr += rxXferLen;
1394        rxFragPtr += rxXferLen;
1395        rxPktBytes -= rxXferLen;
1396
1397        rxState = rxFifoBlock;
1398        break;
1399
1400      case rxDescWrite:
1401        if (rxDmaState != dmaIdle)
1402            goto exit;
1403
1404        assert(cmdsts & CMDSTS_OWN);
1405
1406        assert(rxPacket == 0);
1407        devIntrPost(ISR_RXOK);
1408
1409        if (cmdsts & CMDSTS_INTR)
1410            devIntrPost(ISR_RXDESC);
1411
1412        if (!rxEnable) {
1413            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1414            rxState = rxIdle;
1415            goto exit;
1416        } else
1417            rxState = rxAdvance;
1418        break;
1419
1420      case rxAdvance:
1421        if (link == 0) {
1422            devIntrPost(ISR_RXIDLE);
1423            rxState = rxIdle;
1424            CRDD = true;
1425            goto exit;
1426        } else {
1427            if (rxDmaState != dmaIdle)
1428                goto exit;
1429            rxState = rxDescRead;
1430            regs.rxdp = link;
1431            CRDD = false;
1432
1433            rxDmaAddr = regs.rxdp & 0x3fffffff;
1434            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1435            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1436            rxDmaFree = dmaDescFree;
1437
1438            if (doRxDmaRead())
1439                goto exit;
1440        }
1441        break;
1442
1443      default:
1444        panic("Invalid rxState!");
1445    }
1446
1447    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1448            NsRxStateStrings[rxState]);
1449    goto next;
1450
1451  exit:
1452    /**
1453     * @todo do we want to schedule a future kick?
1454     */
1455    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1456            NsRxStateStrings[rxState]);
1457
1458    if (!rxKickEvent.scheduled())
1459        schedule(rxKickEvent, rxKickTick);
1460}
1461
1462void
1463NSGigE::transmit()
1464{
1465    if (txFifo.empty()) {
1466        DPRINTF(Ethernet, "nothing to transmit\n");
1467        return;
1468    }
1469
1470    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1471            txFifo.size());
1472    if (interface->sendPacket(txFifo.front())) {
1473#if TRACING_ON
1474        if (DTRACE(Ethernet)) {
1475            IpPtr ip(txFifo.front());
1476            if (ip) {
1477                DPRINTF(Ethernet, "ID is %d\n", ip->id());
1478                TcpPtr tcp(ip);
1479                if (tcp) {
1480                    DPRINTF(Ethernet,
1481                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1482                            tcp->sport(), tcp->dport(), tcp->seq(),
1483                            tcp->ack());
1484                }
1485            }
1486        }
1487#endif
1488
1489        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1490        txBytes += txFifo.front()->length;
1491        txPackets++;
1492
1493        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1494                txFifo.avail());
1495        txFifo.pop();
1496
1497        /*
1498         * normally do a writeback of the descriptor here, and ONLY
1499         * after that is done, send this interrupt.  but since our
1500         * stuff never actually fails, just do this interrupt here,
1501         * otherwise the code has to stray from this nice format.
1502         * besides, it's functionally the same.
1503         */
1504        devIntrPost(ISR_TXOK);
1505    }
1506
1507   if (!txFifo.empty() && !txEvent.scheduled()) {
1508       DPRINTF(Ethernet, "reschedule transmit\n");
1509       schedule(txEvent, curTick() + retryTime);
1510   }
1511}
1512
1513bool
1514NSGigE::doTxDmaRead()
1515{
1516    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1517    txDmaState = dmaReading;
1518
1519    if (dmaPending() || drainState() != DrainState::Running)
1520        txDmaState = dmaReadWaiting;
1521    else
1522        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1523
1524    return true;
1525}
1526
1527void
1528NSGigE::txDmaReadDone()
1529{
1530    assert(txDmaState == dmaReading);
1531    txDmaState = dmaIdle;
1532
1533    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1534            txDmaAddr, txDmaLen);
1535    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1536
1537    // If the receive state machine  has a pending DMA, let it go first
1538    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1539        rxKick();
1540
1541    txKick();
1542}
1543
1544bool
1545NSGigE::doTxDmaWrite()
1546{
1547    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1548    txDmaState = dmaWriting;
1549
1550    if (dmaPending() || drainState() != DrainState::Running)
1551        txDmaState = dmaWriteWaiting;
1552    else
1553        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1554    return true;
1555}
1556
1557void
1558NSGigE::txDmaWriteDone()
1559{
1560    assert(txDmaState == dmaWriting);
1561    txDmaState = dmaIdle;
1562
1563    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1564            txDmaAddr, txDmaLen);
1565    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1566
1567    // If the receive state machine  has a pending DMA, let it go first
1568    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1569        rxKick();
1570
1571    txKick();
1572}
1573
1574void
1575NSGigE::txKick()
1576{
1577    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1578
1579    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1580            NsTxStateStrings[txState], is64bit ? 64 : 32);
1581
1582    Addr link, bufptr;
1583    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1584    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1585
1586  next:
1587    if (txKickTick > curTick()) {
1588        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1589                txKickTick);
1590        goto exit;
1591    }
1592
1593    // Go to the next state machine clock tick.
1594    txKickTick = clockEdge(Cycles(1));
1595
1596    switch(txDmaState) {
1597      case dmaReadWaiting:
1598        if (doTxDmaRead())
1599            goto exit;
1600        break;
1601      case dmaWriteWaiting:
1602        if (doTxDmaWrite())
1603            goto exit;
1604        break;
1605      default:
1606        break;
1607    }
1608
1609    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1610    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1611    switch (txState) {
1612      case txIdle:
1613        if (!txEnable) {
1614            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1615            goto exit;
1616        }
1617
1618        if (CTDD) {
1619            txState = txDescRefr;
1620
1621            txDmaAddr = regs.txdp & 0x3fffffff;
1622            txDmaData =
1623                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1624            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1625            txDmaFree = dmaDescFree;
1626
1627            descDmaReads++;
1628            descDmaRdBytes += txDmaLen;
1629
1630            if (doTxDmaRead())
1631                goto exit;
1632
1633        } else {
1634            txState = txDescRead;
1635
1636            txDmaAddr = regs.txdp & 0x3fffffff;
1637            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1638            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1639            txDmaFree = dmaDescFree;
1640
1641            descDmaReads++;
1642            descDmaRdBytes += txDmaLen;
1643
1644            if (doTxDmaRead())
1645                goto exit;
1646        }
1647        break;
1648
1649      case txDescRefr:
1650        if (txDmaState != dmaIdle)
1651            goto exit;
1652
1653        txState = txAdvance;
1654        break;
1655
1656      case txDescRead:
1657        if (txDmaState != dmaIdle)
1658            goto exit;
1659
1660        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1661                regs.txdp & 0x3fffffff);
1662        DPRINTF(EthernetDesc,
1663                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1664                link, bufptr, cmdsts, extsts);
1665
1666        if (cmdsts & CMDSTS_OWN) {
1667            txState = txFifoBlock;
1668            txFragPtr = bufptr;
1669            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1670        } else {
1671            devIntrPost(ISR_TXIDLE);
1672            txState = txIdle;
1673            goto exit;
1674        }
1675        break;
1676
1677      case txFifoBlock:
1678        if (!txPacket) {
1679            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1680            txPacket = make_shared<EthPacketData>(16384);
1681            txPacketBufPtr = txPacket->data;
1682        }
1683
1684        if (txDescCnt == 0) {
1685            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1686            if (cmdsts & CMDSTS_MORE) {
1687                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1688                txState = txDescWrite;
1689
1690                cmdsts &= ~CMDSTS_OWN;
1691
1692                txDmaAddr = regs.txdp & 0x3fffffff;
1693                txDmaData = &cmdsts;
1694                if (is64bit) {
1695                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1696                    txDmaLen = sizeof(txDesc64.cmdsts);
1697                } else {
1698                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1699                    txDmaLen = sizeof(txDesc32.cmdsts);
1700                }
1701                txDmaFree = dmaDescFree;
1702
1703                if (doTxDmaWrite())
1704                    goto exit;
1705
1706            } else { /* this packet is totally done */
1707                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1708                /* deal with the the packet that just finished */
1709                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1710                    IpPtr ip(txPacket);
1711                    if (extsts & EXTSTS_UDPPKT) {
1712                        UdpPtr udp(ip);
1713                        if (udp) {
1714                            udp->sum(0);
1715                            udp->sum(cksum(udp));
1716                            txUdpChecksums++;
1717                        } else {
1718                            Debug::breakpoint();
1719                            warn_once("UDPPKT set, but not UDP!\n");
1720                        }
1721                    } else if (extsts & EXTSTS_TCPPKT) {
1722                        TcpPtr tcp(ip);
1723                        if (tcp) {
1724                            tcp->sum(0);
1725                            tcp->sum(cksum(tcp));
1726                            txTcpChecksums++;
1727                        } else {
1728                            Debug::breakpoint();
1729                            warn_once("TCPPKT set, but not UDP!\n");
1730                        }
1731                    }
1732                    if (extsts & EXTSTS_IPPKT) {
1733                        if (ip) {
1734                            ip->sum(0);
1735                            ip->sum(cksum(ip));
1736                            txIpChecksums++;
1737                        } else {
1738                            Debug::breakpoint();
1739                            warn_once("IPPKT set, but not UDP!\n");
1740                        }
1741                    }
1742                }
1743
1744                txPacket->length = txPacketBufPtr - txPacket->data;
1745                // this is just because the receive can't handle a
1746                // packet bigger want to make sure
1747                if (txPacket->length > 1514)
1748                    panic("transmit packet too large, %s > 1514\n",
1749                          txPacket->length);
1750
1751#ifndef NDEBUG
1752                bool success =
1753#endif
1754                    txFifo.push(txPacket);
1755                assert(success);
1756
1757                /*
1758                 * this following section is not tqo spec, but
1759                 * functionally shouldn't be any different.  normally,
1760                 * the chip will wait til the transmit has occurred
1761                 * before writing back the descriptor because it has
1762                 * to wait to see that it was successfully transmitted
1763                 * to decide whether to set CMDSTS_OK or not.
1764                 * however, in the simulator since it is always
1765                 * successfully transmitted, and writing it exactly to
1766                 * spec would complicate the code, we just do it here
1767                 */
1768
1769                cmdsts &= ~CMDSTS_OWN;
1770                cmdsts |= CMDSTS_OK;
1771
1772                DPRINTF(EthernetDesc,
1773                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1774                        cmdsts, extsts);
1775
1776                txDmaFree = dmaDescFree;
1777                txDmaAddr = regs.txdp & 0x3fffffff;
1778                txDmaData = &cmdsts;
1779                if (is64bit) {
1780                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1781                    txDmaLen =
1782                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1783                } else {
1784                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1785                    txDmaLen =
1786                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1787                }
1788
1789                descDmaWrites++;
1790                descDmaWrBytes += txDmaLen;
1791
1792                transmit();
1793                txPacket = 0;
1794
1795                if (!txEnable) {
1796                    DPRINTF(EthernetSM, "halting TX state machine\n");
1797                    txState = txIdle;
1798                    goto exit;
1799                } else
1800                    txState = txAdvance;
1801
1802                if (doTxDmaWrite())
1803                    goto exit;
1804            }
1805        } else {
1806            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1807            if (!txFifo.full()) {
1808                txState = txFragRead;
1809
1810                /*
1811                 * The number of bytes transferred is either whatever
1812                 * is left in the descriptor (txDescCnt), or if there
1813                 * is not enough room in the fifo, just whatever room
1814                 * is left in the fifo
1815                 */
1816                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1817
1818                txDmaAddr = txFragPtr & 0x3fffffff;
1819                txDmaData = txPacketBufPtr;
1820                txDmaLen = txXferLen;
1821                txDmaFree = dmaDataFree;
1822
1823                if (doTxDmaRead())
1824                    goto exit;
1825            } else {
1826                txState = txFifoBlock;
1827                transmit();
1828
1829                goto exit;
1830            }
1831
1832        }
1833        break;
1834
1835      case txFragRead:
1836        if (txDmaState != dmaIdle)
1837            goto exit;
1838
1839        txPacketBufPtr += txXferLen;
1840        txFragPtr += txXferLen;
1841        txDescCnt -= txXferLen;
1842        txFifo.reserve(txXferLen);
1843
1844        txState = txFifoBlock;
1845        break;
1846
1847      case txDescWrite:
1848        if (txDmaState != dmaIdle)
1849            goto exit;
1850
1851        if (cmdsts & CMDSTS_INTR)
1852            devIntrPost(ISR_TXDESC);
1853
1854        if (!txEnable) {
1855            DPRINTF(EthernetSM, "halting TX state machine\n");
1856            txState = txIdle;
1857            goto exit;
1858        } else
1859            txState = txAdvance;
1860        break;
1861
1862      case txAdvance:
1863        if (link == 0) {
1864            devIntrPost(ISR_TXIDLE);
1865            txState = txIdle;
1866            goto exit;
1867        } else {
1868            if (txDmaState != dmaIdle)
1869                goto exit;
1870            txState = txDescRead;
1871            regs.txdp = link;
1872            CTDD = false;
1873
1874            txDmaAddr = link & 0x3fffffff;
1875            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1876            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1877            txDmaFree = dmaDescFree;
1878
1879            if (doTxDmaRead())
1880                goto exit;
1881        }
1882        break;
1883
1884      default:
1885        panic("invalid state");
1886    }
1887
1888    DPRINTF(EthernetSM, "entering next txState=%s\n",
1889            NsTxStateStrings[txState]);
1890    goto next;
1891
1892  exit:
1893    /**
1894     * @todo do we want to schedule a future kick?
1895     */
1896    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1897            NsTxStateStrings[txState]);
1898
1899    if (!txKickEvent.scheduled())
1900        schedule(txKickEvent, txKickTick);
1901}
1902
1903/**
1904 * Advance the EEPROM state machine
1905 * Called on rising edge of EEPROM clock bit in MEAR
1906 */
1907void
1908NSGigE::eepromKick()
1909{
1910    switch (eepromState) {
1911
1912      case eepromStart:
1913
1914        // Wait for start bit
1915        if (regs.mear & MEAR_EEDI) {
1916            // Set up to get 2 opcode bits
1917            eepromState = eepromGetOpcode;
1918            eepromBitsToRx = 2;
1919            eepromOpcode = 0;
1920        }
1921        break;
1922
1923      case eepromGetOpcode:
1924        eepromOpcode <<= 1;
1925        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1926        --eepromBitsToRx;
1927
1928        // Done getting opcode
1929        if (eepromBitsToRx == 0) {
1930            if (eepromOpcode != EEPROM_READ)
1931                panic("only EEPROM reads are implemented!");
1932
1933            // Set up to get address
1934            eepromState = eepromGetAddress;
1935            eepromBitsToRx = 6;
1936            eepromAddress = 0;
1937        }
1938        break;
1939
1940      case eepromGetAddress:
1941        eepromAddress <<= 1;
1942        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1943        --eepromBitsToRx;
1944
1945        // Done getting address
1946        if (eepromBitsToRx == 0) {
1947
1948            if (eepromAddress >= EEPROM_SIZE)
1949                panic("EEPROM read access out of range!");
1950
1951            switch (eepromAddress) {
1952
1953              case EEPROM_PMATCH2_ADDR:
1954                eepromData = rom.perfectMatch[5];
1955                eepromData <<= 8;
1956                eepromData += rom.perfectMatch[4];
1957                break;
1958
1959              case EEPROM_PMATCH1_ADDR:
1960                eepromData = rom.perfectMatch[3];
1961                eepromData <<= 8;
1962                eepromData += rom.perfectMatch[2];
1963                break;
1964
1965              case EEPROM_PMATCH0_ADDR:
1966                eepromData = rom.perfectMatch[1];
1967                eepromData <<= 8;
1968                eepromData += rom.perfectMatch[0];
1969                break;
1970
1971              default:
1972                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1973            }
1974            // Set up to read data
1975            eepromState = eepromRead;
1976            eepromBitsToRx = 16;
1977
1978            // Clear data in bit
1979            regs.mear &= ~MEAR_EEDI;
1980        }
1981        break;
1982
1983      case eepromRead:
1984        // Clear Data Out bit
1985        regs.mear &= ~MEAR_EEDO;
1986        // Set bit to value of current EEPROM bit
1987        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1988
1989        eepromData <<= 1;
1990        --eepromBitsToRx;
1991
1992        // All done
1993        if (eepromBitsToRx == 0) {
1994            eepromState = eepromStart;
1995        }
1996        break;
1997
1998      default:
1999        panic("invalid EEPROM state");
2000    }
2001
2002}
2003
2004void
2005NSGigE::transferDone()
2006{
2007    if (txFifo.empty()) {
2008        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2009        return;
2010    }
2011
2012    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2013
2014    reschedule(txEvent, clockEdge(Cycles(1)), true);
2015}
2016
2017bool
2018NSGigE::rxFilter(const EthPacketPtr &packet)
2019{
2020    EthPtr eth = packet;
2021    bool drop = true;
2022    string type;
2023
2024    const EthAddr &dst = eth->dst();
2025    if (dst.unicast()) {
2026        // If we're accepting all unicast addresses
2027        if (acceptUnicast)
2028            drop = false;
2029
2030        // If we make a perfect match
2031        if (acceptPerfect && dst == rom.perfectMatch)
2032            drop = false;
2033
2034        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2035            drop = false;
2036
2037    } else if (dst.broadcast()) {
2038        // if we're accepting broadcasts
2039        if (acceptBroadcast)
2040            drop = false;
2041
2042    } else if (dst.multicast()) {
2043        // if we're accepting all multicasts
2044        if (acceptMulticast)
2045            drop = false;
2046
2047        // Multicast hashing faked - all packets accepted
2048        if (multicastHashEnable)
2049            drop = false;
2050    }
2051
2052    if (drop) {
2053        DPRINTF(Ethernet, "rxFilter drop\n");
2054        DDUMP(EthernetData, packet->data, packet->length);
2055    }
2056
2057    return drop;
2058}
2059
2060bool
2061NSGigE::recvPacket(EthPacketPtr packet)
2062{
2063    rxBytes += packet->length;
2064    rxPackets++;
2065
2066    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2067            rxFifo.avail());
2068
2069    if (!rxEnable) {
2070        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2071        return true;
2072    }
2073
2074    if (!rxFilterEnable) {
2075        DPRINTF(Ethernet,
2076            "receive packet filtering disabled . . . packet dropped\n");
2077        return true;
2078    }
2079
2080    if (rxFilter(packet)) {
2081        DPRINTF(Ethernet, "packet filtered...dropped\n");
2082        return true;
2083    }
2084
2085    if (rxFifo.avail() < packet->length) {
2086#if TRACING_ON
2087        IpPtr ip(packet);
2088        TcpPtr tcp(ip);
2089        if (ip) {
2090            DPRINTF(Ethernet,
2091                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
2092                    ip->id());
2093            if (tcp) {
2094                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2095            }
2096        }
2097#endif
2098        droppedPackets++;
2099        devIntrPost(ISR_RXORN);
2100        return false;
2101    }
2102
2103    rxFifo.push(packet);
2104
2105    rxKick();
2106    return true;
2107}
2108
2109
2110void
2111NSGigE::drainResume()
2112{
2113    Drainable::drainResume();
2114
2115    // During drain we could have left the state machines in a waiting state and
2116    // they wouldn't get out until some other event occured to kick them.
2117    // This way they'll get out immediately
2118    txKick();
2119    rxKick();
2120}
2121
2122
2123//=====================================================================
2124//
2125//
2126void
2127NSGigE::serialize(CheckpointOut &cp) const
2128{
2129    // Serialize the PciDevice base class
2130    PciDevice::serialize(cp);
2131
2132    /*
2133     * Finalize any DMA events now.
2134     */
2135    // @todo will mem system save pending dma?
2136
2137    /*
2138     * Serialize the device registers
2139     */
2140    SERIALIZE_SCALAR(regs.command);
2141    SERIALIZE_SCALAR(regs.config);
2142    SERIALIZE_SCALAR(regs.mear);
2143    SERIALIZE_SCALAR(regs.ptscr);
2144    SERIALIZE_SCALAR(regs.isr);
2145    SERIALIZE_SCALAR(regs.imr);
2146    SERIALIZE_SCALAR(regs.ier);
2147    SERIALIZE_SCALAR(regs.ihr);
2148    SERIALIZE_SCALAR(regs.txdp);
2149    SERIALIZE_SCALAR(regs.txdp_hi);
2150    SERIALIZE_SCALAR(regs.txcfg);
2151    SERIALIZE_SCALAR(regs.gpior);
2152    SERIALIZE_SCALAR(regs.rxdp);
2153    SERIALIZE_SCALAR(regs.rxdp_hi);
2154    SERIALIZE_SCALAR(regs.rxcfg);
2155    SERIALIZE_SCALAR(regs.pqcr);
2156    SERIALIZE_SCALAR(regs.wcsr);
2157    SERIALIZE_SCALAR(regs.pcr);
2158    SERIALIZE_SCALAR(regs.rfcr);
2159    SERIALIZE_SCALAR(regs.rfdr);
2160    SERIALIZE_SCALAR(regs.brar);
2161    SERIALIZE_SCALAR(regs.brdr);
2162    SERIALIZE_SCALAR(regs.srr);
2163    SERIALIZE_SCALAR(regs.mibc);
2164    SERIALIZE_SCALAR(regs.vrcr);
2165    SERIALIZE_SCALAR(regs.vtcr);
2166    SERIALIZE_SCALAR(regs.vdr);
2167    SERIALIZE_SCALAR(regs.ccsr);
2168    SERIALIZE_SCALAR(regs.tbicr);
2169    SERIALIZE_SCALAR(regs.tbisr);
2170    SERIALIZE_SCALAR(regs.tanar);
2171    SERIALIZE_SCALAR(regs.tanlpar);
2172    SERIALIZE_SCALAR(regs.taner);
2173    SERIALIZE_SCALAR(regs.tesr);
2174
2175    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2176    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2177
2178    SERIALIZE_SCALAR(ioEnable);
2179
2180    /*
2181     * Serialize the data Fifos
2182     */
2183    rxFifo.serialize("rxFifo", cp);
2184    txFifo.serialize("txFifo", cp);
2185
2186    /*
2187     * Serialize the various helper variables
2188     */
2189    bool txPacketExists = txPacket != nullptr;
2190    SERIALIZE_SCALAR(txPacketExists);
2191    if (txPacketExists) {
2192        txPacket->length = txPacketBufPtr - txPacket->data;
2193        txPacket->serialize("txPacket", cp);
2194        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2195        SERIALIZE_SCALAR(txPktBufPtr);
2196    }
2197
2198    bool rxPacketExists = rxPacket != nullptr;
2199    SERIALIZE_SCALAR(rxPacketExists);
2200    if (rxPacketExists) {
2201        rxPacket->serialize("rxPacket", cp);
2202        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2203        SERIALIZE_SCALAR(rxPktBufPtr);
2204    }
2205
2206    SERIALIZE_SCALAR(txXferLen);
2207    SERIALIZE_SCALAR(rxXferLen);
2208
2209    /*
2210     * Serialize Cached Descriptors
2211     */
2212    SERIALIZE_SCALAR(rxDesc64.link);
2213    SERIALIZE_SCALAR(rxDesc64.bufptr);
2214    SERIALIZE_SCALAR(rxDesc64.cmdsts);
2215    SERIALIZE_SCALAR(rxDesc64.extsts);
2216    SERIALIZE_SCALAR(txDesc64.link);
2217    SERIALIZE_SCALAR(txDesc64.bufptr);
2218    SERIALIZE_SCALAR(txDesc64.cmdsts);
2219    SERIALIZE_SCALAR(txDesc64.extsts);
2220    SERIALIZE_SCALAR(rxDesc32.link);
2221    SERIALIZE_SCALAR(rxDesc32.bufptr);
2222    SERIALIZE_SCALAR(rxDesc32.cmdsts);
2223    SERIALIZE_SCALAR(rxDesc32.extsts);
2224    SERIALIZE_SCALAR(txDesc32.link);
2225    SERIALIZE_SCALAR(txDesc32.bufptr);
2226    SERIALIZE_SCALAR(txDesc32.cmdsts);
2227    SERIALIZE_SCALAR(txDesc32.extsts);
2228    SERIALIZE_SCALAR(extstsEnable);
2229
2230    /*
2231     * Serialize tx state machine
2232     */
2233    int txState = this->txState;
2234    SERIALIZE_SCALAR(txState);
2235    SERIALIZE_SCALAR(txEnable);
2236    SERIALIZE_SCALAR(CTDD);
2237    SERIALIZE_SCALAR(txFragPtr);
2238    SERIALIZE_SCALAR(txDescCnt);
2239    int txDmaState = this->txDmaState;
2240    SERIALIZE_SCALAR(txDmaState);
2241    SERIALIZE_SCALAR(txKickTick);
2242
2243    /*
2244     * Serialize rx state machine
2245     */
2246    int rxState = this->rxState;
2247    SERIALIZE_SCALAR(rxState);
2248    SERIALIZE_SCALAR(rxEnable);
2249    SERIALIZE_SCALAR(CRDD);
2250    SERIALIZE_SCALAR(rxPktBytes);
2251    SERIALIZE_SCALAR(rxFragPtr);
2252    SERIALIZE_SCALAR(rxDescCnt);
2253    int rxDmaState = this->rxDmaState;
2254    SERIALIZE_SCALAR(rxDmaState);
2255    SERIALIZE_SCALAR(rxKickTick);
2256
2257    /*
2258     * Serialize EEPROM state machine
2259     */
2260    int eepromState = this->eepromState;
2261    SERIALIZE_SCALAR(eepromState);
2262    SERIALIZE_SCALAR(eepromClk);
2263    SERIALIZE_SCALAR(eepromBitsToRx);
2264    SERIALIZE_SCALAR(eepromOpcode);
2265    SERIALIZE_SCALAR(eepromAddress);
2266    SERIALIZE_SCALAR(eepromData);
2267
2268    /*
2269     * If there's a pending transmit, store the time so we can
2270     * reschedule it later
2271     */
2272    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2273    SERIALIZE_SCALAR(transmitTick);
2274
2275    /*
2276     * receive address filter settings
2277     */
2278    SERIALIZE_SCALAR(rxFilterEnable);
2279    SERIALIZE_SCALAR(acceptBroadcast);
2280    SERIALIZE_SCALAR(acceptMulticast);
2281    SERIALIZE_SCALAR(acceptUnicast);
2282    SERIALIZE_SCALAR(acceptPerfect);
2283    SERIALIZE_SCALAR(acceptArp);
2284    SERIALIZE_SCALAR(multicastHashEnable);
2285
2286    /*
2287     * Keep track of pending interrupt status.
2288     */
2289    SERIALIZE_SCALAR(intrTick);
2290    SERIALIZE_SCALAR(cpuPendingIntr);
2291    Tick intrEventTick = 0;
2292    if (intrEvent)
2293        intrEventTick = intrEvent->when();
2294    SERIALIZE_SCALAR(intrEventTick);
2295
2296}
2297
2298void
2299NSGigE::unserialize(CheckpointIn &cp)
2300{
2301    // Unserialize the PciDevice base class
2302    PciDevice::unserialize(cp);
2303
2304    UNSERIALIZE_SCALAR(regs.command);
2305    UNSERIALIZE_SCALAR(regs.config);
2306    UNSERIALIZE_SCALAR(regs.mear);
2307    UNSERIALIZE_SCALAR(regs.ptscr);
2308    UNSERIALIZE_SCALAR(regs.isr);
2309    UNSERIALIZE_SCALAR(regs.imr);
2310    UNSERIALIZE_SCALAR(regs.ier);
2311    UNSERIALIZE_SCALAR(regs.ihr);
2312    UNSERIALIZE_SCALAR(regs.txdp);
2313    UNSERIALIZE_SCALAR(regs.txdp_hi);
2314    UNSERIALIZE_SCALAR(regs.txcfg);
2315    UNSERIALIZE_SCALAR(regs.gpior);
2316    UNSERIALIZE_SCALAR(regs.rxdp);
2317    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2318    UNSERIALIZE_SCALAR(regs.rxcfg);
2319    UNSERIALIZE_SCALAR(regs.pqcr);
2320    UNSERIALIZE_SCALAR(regs.wcsr);
2321    UNSERIALIZE_SCALAR(regs.pcr);
2322    UNSERIALIZE_SCALAR(regs.rfcr);
2323    UNSERIALIZE_SCALAR(regs.rfdr);
2324    UNSERIALIZE_SCALAR(regs.brar);
2325    UNSERIALIZE_SCALAR(regs.brdr);
2326    UNSERIALIZE_SCALAR(regs.srr);
2327    UNSERIALIZE_SCALAR(regs.mibc);
2328    UNSERIALIZE_SCALAR(regs.vrcr);
2329    UNSERIALIZE_SCALAR(regs.vtcr);
2330    UNSERIALIZE_SCALAR(regs.vdr);
2331    UNSERIALIZE_SCALAR(regs.ccsr);
2332    UNSERIALIZE_SCALAR(regs.tbicr);
2333    UNSERIALIZE_SCALAR(regs.tbisr);
2334    UNSERIALIZE_SCALAR(regs.tanar);
2335    UNSERIALIZE_SCALAR(regs.tanlpar);
2336    UNSERIALIZE_SCALAR(regs.taner);
2337    UNSERIALIZE_SCALAR(regs.tesr);
2338
2339    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2340    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2341
2342    UNSERIALIZE_SCALAR(ioEnable);
2343
2344    /*
2345     * unserialize the data fifos
2346     */
2347    rxFifo.unserialize("rxFifo", cp);
2348    txFifo.unserialize("txFifo", cp);
2349
2350    /*
2351     * unserialize the various helper variables
2352     */
2353    bool txPacketExists;
2354    UNSERIALIZE_SCALAR(txPacketExists);
2355    if (txPacketExists) {
2356        txPacket = make_shared<EthPacketData>(16384);
2357        txPacket->unserialize("txPacket", cp);
2358        uint32_t txPktBufPtr;
2359        UNSERIALIZE_SCALAR(txPktBufPtr);
2360        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2361    } else
2362        txPacket = 0;
2363
2364    bool rxPacketExists;
2365    UNSERIALIZE_SCALAR(rxPacketExists);
2366    rxPacket = 0;
2367    if (rxPacketExists) {
2368        rxPacket = make_shared<EthPacketData>(16384);
2369        rxPacket->unserialize("rxPacket", cp);
2370        uint32_t rxPktBufPtr;
2371        UNSERIALIZE_SCALAR(rxPktBufPtr);
2372        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2373    } else
2374        rxPacket = 0;
2375
2376    UNSERIALIZE_SCALAR(txXferLen);
2377    UNSERIALIZE_SCALAR(rxXferLen);
2378
2379    /*
2380     * Unserialize Cached Descriptors
2381     */
2382    UNSERIALIZE_SCALAR(rxDesc64.link);
2383    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2384    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2385    UNSERIALIZE_SCALAR(rxDesc64.extsts);
2386    UNSERIALIZE_SCALAR(txDesc64.link);
2387    UNSERIALIZE_SCALAR(txDesc64.bufptr);
2388    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2389    UNSERIALIZE_SCALAR(txDesc64.extsts);
2390    UNSERIALIZE_SCALAR(rxDesc32.link);
2391    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2392    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2393    UNSERIALIZE_SCALAR(rxDesc32.extsts);
2394    UNSERIALIZE_SCALAR(txDesc32.link);
2395    UNSERIALIZE_SCALAR(txDesc32.bufptr);
2396    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2397    UNSERIALIZE_SCALAR(txDesc32.extsts);
2398    UNSERIALIZE_SCALAR(extstsEnable);
2399
2400    /*
2401     * unserialize tx state machine
2402     */
2403    int txState;
2404    UNSERIALIZE_SCALAR(txState);
2405    this->txState = (TxState) txState;
2406    UNSERIALIZE_SCALAR(txEnable);
2407    UNSERIALIZE_SCALAR(CTDD);
2408    UNSERIALIZE_SCALAR(txFragPtr);
2409    UNSERIALIZE_SCALAR(txDescCnt);
2410    int txDmaState;
2411    UNSERIALIZE_SCALAR(txDmaState);
2412    this->txDmaState = (DmaState) txDmaState;
2413    UNSERIALIZE_SCALAR(txKickTick);
2414    if (txKickTick)
2415        schedule(txKickEvent, txKickTick);
2416
2417    /*
2418     * unserialize rx state machine
2419     */
2420    int rxState;
2421    UNSERIALIZE_SCALAR(rxState);
2422    this->rxState = (RxState) rxState;
2423    UNSERIALIZE_SCALAR(rxEnable);
2424    UNSERIALIZE_SCALAR(CRDD);
2425    UNSERIALIZE_SCALAR(rxPktBytes);
2426    UNSERIALIZE_SCALAR(rxFragPtr);
2427    UNSERIALIZE_SCALAR(rxDescCnt);
2428    int rxDmaState;
2429    UNSERIALIZE_SCALAR(rxDmaState);
2430    this->rxDmaState = (DmaState) rxDmaState;
2431    UNSERIALIZE_SCALAR(rxKickTick);
2432    if (rxKickTick)
2433        schedule(rxKickEvent, rxKickTick);
2434
2435    /*
2436     * Unserialize EEPROM state machine
2437     */
2438    int eepromState;
2439    UNSERIALIZE_SCALAR(eepromState);
2440    this->eepromState = (EEPROMState) eepromState;
2441    UNSERIALIZE_SCALAR(eepromClk);
2442    UNSERIALIZE_SCALAR(eepromBitsToRx);
2443    UNSERIALIZE_SCALAR(eepromOpcode);
2444    UNSERIALIZE_SCALAR(eepromAddress);
2445    UNSERIALIZE_SCALAR(eepromData);
2446
2447    /*
2448     * If there's a pending transmit, reschedule it now
2449     */
2450    Tick transmitTick;
2451    UNSERIALIZE_SCALAR(transmitTick);
2452    if (transmitTick)
2453        schedule(txEvent, curTick() + transmitTick);
2454
2455    /*
2456     * unserialize receive address filter settings
2457     */
2458    UNSERIALIZE_SCALAR(rxFilterEnable);
2459    UNSERIALIZE_SCALAR(acceptBroadcast);
2460    UNSERIALIZE_SCALAR(acceptMulticast);
2461    UNSERIALIZE_SCALAR(acceptUnicast);
2462    UNSERIALIZE_SCALAR(acceptPerfect);
2463    UNSERIALIZE_SCALAR(acceptArp);
2464    UNSERIALIZE_SCALAR(multicastHashEnable);
2465
2466    /*
2467     * Keep track of pending interrupt status.
2468     */
2469    UNSERIALIZE_SCALAR(intrTick);
2470    UNSERIALIZE_SCALAR(cpuPendingIntr);
2471    Tick intrEventTick;
2472    UNSERIALIZE_SCALAR(intrEventTick);
2473    if (intrEventTick) {
2474        intrEvent = new IntrEvent(this, true);
2475        schedule(intrEvent, intrEventTick);
2476    }
2477}
2478
2479NSGigE *
2480NSGigEParams::create()
2481{
2482    return new NSGigE(this);
2483}
2484