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