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