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