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