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