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