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