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