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