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