ns_gige.cc revision 961
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                if (doTxDmaWrite())
1893                    goto exit;
1894
1895                transmit();
1896
1897                txPacket = 0;
1898
1899                if (txHalt) {
1900                    DPRINTF(EthernetSM, "halting TX state machine\n");
1901                    txState = txIdle;
1902                    txHalt = false;
1903                } else
1904                    txState = txAdvance;
1905            }
1906        } else {
1907            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1908            txState = txFragRead;
1909
1910            /* The number of bytes transferred is either whatever is left
1911               in the descriptor (txDescCnt), or if there is not enough
1912               room in the fifo, just whatever room is left in the fifo
1913            */
1914            txXferLen = min<uint32_t>(txDescCnt, txFifoAvail);
1915
1916            txDmaAddr = txFragPtr & 0x3fffffff;
1917            txDmaData = txPacketBufPtr;
1918            txDmaLen = txXferLen;
1919            txDmaFree = dmaDataFree;
1920
1921            if (doTxDmaRead())
1922                goto exit;
1923        }
1924        break;
1925
1926      case txFragRead:
1927        if (txDmaState != dmaIdle)
1928            goto exit;
1929
1930        txPacketBufPtr += txXferLen;
1931        txFragPtr += txXferLen;
1932        txDescCnt -= txXferLen;
1933        txFifoAvail -= txXferLen;
1934
1935        txState = txFifoBlock;
1936        break;
1937
1938      case txDescWrite:
1939        if (txDmaState != dmaIdle)
1940            goto exit;
1941
1942        if (txDescCache.cmdsts & CMDSTS_INTR) {
1943            devIntrPost(ISR_TXDESC);
1944        }
1945
1946        txState = txAdvance;
1947        break;
1948
1949      case txAdvance:
1950        if (txDescCache.link == 0) {
1951            txState = txIdle;
1952        } else {
1953            txState = txDescRead;
1954            regs.txdp = txDescCache.link;
1955            CTDD = false;
1956
1957            txDmaAddr = txDescCache.link & 0x3fffffff;
1958            txDmaData = &txDescCache;
1959            txDmaLen = sizeof(ns_desc);
1960            txDmaFree = dmaDescFree;
1961
1962            if (doTxDmaRead())
1963                goto exit;
1964        }
1965        break;
1966
1967      default:
1968        panic("invalid state");
1969    }
1970
1971    DPRINTF(EthernetSM, "entering next tx state=%s\n",
1972            NsTxStateStrings[txState]);
1973
1974    if (txState == txIdle) {
1975        regs.command &= ~CR_TXE;
1976        devIntrPost(ISR_TXIDLE);
1977        return;
1978    }
1979
1980    goto next;
1981
1982  exit:
1983    /**
1984     * @todo do we want to schedule a future kick?
1985     */
1986    DPRINTF(EthernetSM, "tx state machine exited state=%s\n",
1987            NsTxStateStrings[txState]);
1988}
1989
1990void
1991NSGigE::transferDone()
1992{
1993    if (txFifo.empty())
1994        return;
1995
1996    if (txEvent.scheduled())
1997        txEvent.reschedule(curTick + 1);
1998    else
1999        txEvent.schedule(curTick + 1);
2000}
2001
2002bool
2003NSGigE::rxFilter(PacketPtr packet)
2004{
2005    bool drop = true;
2006    string type;
2007
2008    if (packet->IsUnicast()) {
2009        type = "unicast";
2010
2011        // If we're accepting all unicast addresses
2012        if (acceptUnicast)
2013            drop = false;
2014
2015        // If we make a perfect match
2016        if ((acceptPerfect)
2017            && (memcmp(rom.perfectMatch, packet->data, sizeof(rom.perfectMatch)) == 0))
2018            drop = false;
2019
2020        eth_header *eth = (eth_header *) packet->data;
2021        if ((acceptArp) && (eth->type == 0x608))
2022            drop = false;
2023
2024    } else if (packet->IsBroadcast()) {
2025        type = "broadcast";
2026
2027        // if we're accepting broadcasts
2028        if (acceptBroadcast)
2029            drop = false;
2030
2031    } else if (packet->IsMulticast()) {
2032        type = "multicast";
2033
2034        // if we're accepting all multicasts
2035        if (acceptMulticast)
2036            drop = false;
2037
2038    } else {
2039        type = "unknown";
2040
2041        // oh well, punt on this one
2042    }
2043
2044    if (drop) {
2045        DPRINTF(Ethernet, "rxFilter drop\n");
2046        DDUMP(EthernetData, packet->data, packet->length);
2047    }
2048
2049    return drop;
2050}
2051
2052bool
2053NSGigE::recvPacket(PacketPtr packet)
2054{
2055    rxBytes += packet->length;
2056    rxPackets++;
2057
2058    DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail = %d\n", MAX_RX_FIFO_SIZE - rxFifoCnt);
2059
2060    if (rxState == rxIdle) {
2061        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2062        interface->recvDone();
2063        return true;
2064    }
2065
2066    if (rxFilterEnable && rxFilter(packet)) {
2067        DPRINTF(Ethernet, "packet filtered...dropped\n");
2068        interface->recvDone();
2069        return true;
2070    }
2071
2072    if ((rxFifoCnt + packet->length) >= MAX_RX_FIFO_SIZE) {
2073        DPRINTF(Ethernet,
2074                "packet will not fit in receive buffer...packet dropped\n");
2075        devIntrPost(ISR_RXORN);
2076        return false;
2077    }
2078
2079    rxFifo.push_back(packet);
2080    rxFifoCnt += packet->length;
2081    interface->recvDone();
2082
2083    rxKick();
2084    return true;
2085}
2086
2087/**
2088 * does a udp checksum.  if gen is true, then it generates it and puts it in the right place
2089 * else, it just checks what it calculates against the value in the header in packet
2090 */
2091bool
2092NSGigE::udpChecksum(PacketPtr packet, bool gen)
2093{
2094    ip_header *ip = packet->getIpHdr();
2095    udp_header *hdr = packet->getUdpHdr(ip);
2096
2097    pseudo_header *pseudo = new pseudo_header;
2098
2099    pseudo->src_ip_addr = ip->src_ip_addr;
2100    pseudo->dest_ip_addr = ip->dest_ip_addr;
2101    pseudo->protocol = ip->protocol;
2102    pseudo->len = hdr->len;
2103
2104    uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2105                                  (uint32_t) hdr->len);
2106
2107    delete pseudo;
2108    if (gen)
2109        hdr->chksum = cksum;
2110    else
2111        if (cksum != 0)
2112            return false;
2113
2114    return true;
2115}
2116
2117bool
2118NSGigE::tcpChecksum(PacketPtr packet, bool gen)
2119{
2120    ip_header *ip = packet->getIpHdr();
2121    tcp_header *hdr = packet->getTcpHdr(ip);
2122
2123    uint16_t cksum;
2124    pseudo_header *pseudo = new pseudo_header;
2125    if (!gen) {
2126        pseudo->src_ip_addr = ip->src_ip_addr;
2127        pseudo->dest_ip_addr = ip->dest_ip_addr;
2128        pseudo->protocol = reverseEnd16(ip->protocol);
2129        pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - (ip->vers_len & 0xf)*4);
2130
2131        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2132                                  (uint32_t) reverseEnd16(pseudo->len));
2133    } else {
2134        pseudo->src_ip_addr = 0;
2135        pseudo->dest_ip_addr = 0;
2136        pseudo->protocol = hdr->chksum;
2137        pseudo->len = 0;
2138        hdr->chksum = 0;
2139        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2140                             (uint32_t) (reverseEnd16(ip->dgram_len) - (ip->vers_len & 0xf)*4));
2141    }
2142
2143    delete pseudo;
2144    if (gen)
2145        hdr->chksum = cksum;
2146    else
2147        if (cksum != 0)
2148            return false;
2149
2150    return true;
2151}
2152
2153bool
2154NSGigE::ipChecksum(PacketPtr packet, bool gen)
2155{
2156    ip_header *hdr = packet->getIpHdr();
2157
2158    uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, (hdr->vers_len & 0xf)*4);
2159
2160    if (gen) {
2161        DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum);
2162        hdr->hdr_chksum = cksum;
2163    }
2164    else
2165        if (cksum != 0)
2166            return false;
2167
2168    return true;
2169}
2170
2171uint16_t
2172NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
2173{
2174    uint32_t sum = 0;
2175
2176    uint16_t last_pad = 0;
2177    if (len & 1) {
2178        last_pad = buf[len/2] & 0xff;
2179        len--;
2180        sum += last_pad;
2181    }
2182
2183    if (pseudo) {
2184        sum = pseudo[0] + pseudo[1] + pseudo[2] +
2185            pseudo[3] + pseudo[4] + pseudo[5];
2186    }
2187
2188    for (int i=0; i < (len/2); ++i) {
2189        sum += buf[i];
2190    }
2191
2192    while (sum >> 16)
2193        sum = (sum >> 16) + (sum & 0xffff);
2194
2195    return ~sum;
2196}
2197
2198//=====================================================================
2199//
2200//
2201void
2202NSGigE::serialize(ostream &os)
2203{
2204    // Serialize the PciDev base class
2205    PciDev::serialize(os);
2206
2207    /*
2208     * Finalize any DMA events now.
2209     */
2210    if (rxDmaReadEvent.scheduled())
2211        rxDmaReadCopy();
2212    if (rxDmaWriteEvent.scheduled())
2213        rxDmaWriteCopy();
2214    if (txDmaReadEvent.scheduled())
2215        txDmaReadCopy();
2216    if (txDmaWriteEvent.scheduled())
2217        txDmaWriteCopy();
2218
2219    /*
2220     * Serialize the device registers
2221     */
2222    SERIALIZE_SCALAR(regs.command);
2223    SERIALIZE_SCALAR(regs.config);
2224    SERIALIZE_SCALAR(regs.mear);
2225    SERIALIZE_SCALAR(regs.ptscr);
2226    SERIALIZE_SCALAR(regs.isr);
2227    SERIALIZE_SCALAR(regs.imr);
2228    SERIALIZE_SCALAR(regs.ier);
2229    SERIALIZE_SCALAR(regs.ihr);
2230    SERIALIZE_SCALAR(regs.txdp);
2231    SERIALIZE_SCALAR(regs.txdp_hi);
2232    SERIALIZE_SCALAR(regs.txcfg);
2233    SERIALIZE_SCALAR(regs.gpior);
2234    SERIALIZE_SCALAR(regs.rxdp);
2235    SERIALIZE_SCALAR(regs.rxdp_hi);
2236    SERIALIZE_SCALAR(regs.rxcfg);
2237    SERIALIZE_SCALAR(regs.pqcr);
2238    SERIALIZE_SCALAR(regs.wcsr);
2239    SERIALIZE_SCALAR(regs.pcr);
2240    SERIALIZE_SCALAR(regs.rfcr);
2241    SERIALIZE_SCALAR(regs.rfdr);
2242    SERIALIZE_SCALAR(regs.srr);
2243    SERIALIZE_SCALAR(regs.mibc);
2244    SERIALIZE_SCALAR(regs.vrcr);
2245    SERIALIZE_SCALAR(regs.vtcr);
2246    SERIALIZE_SCALAR(regs.vdr);
2247    SERIALIZE_SCALAR(regs.ccsr);
2248    SERIALIZE_SCALAR(regs.tbicr);
2249    SERIALIZE_SCALAR(regs.tbisr);
2250    SERIALIZE_SCALAR(regs.tanar);
2251    SERIALIZE_SCALAR(regs.tanlpar);
2252    SERIALIZE_SCALAR(regs.taner);
2253    SERIALIZE_SCALAR(regs.tesr);
2254
2255    SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
2256
2257    SERIALIZE_SCALAR(ioEnable);
2258
2259    /*
2260     * Serialize the data Fifos
2261     */
2262    int txNumPkts = txFifo.size();
2263    SERIALIZE_SCALAR(txNumPkts);
2264    int i = 0;
2265    pktiter_t end = txFifo.end();
2266    for (pktiter_t p = txFifo.begin(); p != end; ++p) {
2267        nameOut(os, csprintf("%s.txFifo%d", name(), i++));
2268        (*p)->serialize(os);
2269    }
2270
2271    int rxNumPkts = rxFifo.size();
2272    SERIALIZE_SCALAR(rxNumPkts);
2273    i = 0;
2274    end = rxFifo.end();
2275    for (pktiter_t p = rxFifo.begin(); p != end; ++p) {
2276        nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
2277        (*p)->serialize(os);
2278    }
2279
2280    /*
2281     * Serialize the various helper variables
2282     */
2283    bool txPacketExists = txPacket;
2284    SERIALIZE_SCALAR(txPacketExists);
2285    if (txPacketExists) {
2286        nameOut(os, csprintf("%s.txPacket", name()));
2287        txPacket->serialize(os);
2288        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2289        SERIALIZE_SCALAR(txPktBufPtr);
2290    }
2291
2292    bool rxPacketExists = rxPacket;
2293    SERIALIZE_SCALAR(rxPacketExists);
2294    if (rxPacketExists) {
2295        nameOut(os, csprintf("%s.rxPacket", name()));
2296        rxPacket->serialize(os);
2297        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2298        SERIALIZE_SCALAR(rxPktBufPtr);
2299    }
2300
2301    SERIALIZE_SCALAR(txXferLen);
2302    SERIALIZE_SCALAR(rxXferLen);
2303
2304    /*
2305     * Serialize DescCaches
2306     */
2307    SERIALIZE_SCALAR(txDescCache.link);
2308    SERIALIZE_SCALAR(txDescCache.bufptr);
2309    SERIALIZE_SCALAR(txDescCache.cmdsts);
2310    SERIALIZE_SCALAR(txDescCache.extsts);
2311    SERIALIZE_SCALAR(rxDescCache.link);
2312    SERIALIZE_SCALAR(rxDescCache.bufptr);
2313    SERIALIZE_SCALAR(rxDescCache.cmdsts);
2314    SERIALIZE_SCALAR(rxDescCache.extsts);
2315
2316    /*
2317     * Serialize tx state machine
2318     */
2319    int txState = this->txState;
2320    SERIALIZE_SCALAR(txState);
2321    SERIALIZE_SCALAR(CTDD);
2322    SERIALIZE_SCALAR(txFifoAvail);
2323    SERIALIZE_SCALAR(txHalt);
2324    SERIALIZE_SCALAR(txFragPtr);
2325    SERIALIZE_SCALAR(txDescCnt);
2326    int txDmaState = this->txDmaState;
2327    SERIALIZE_SCALAR(txDmaState);
2328
2329    /*
2330     * Serialize rx state machine
2331     */
2332    int rxState = this->rxState;
2333    SERIALIZE_SCALAR(rxState);
2334    SERIALIZE_SCALAR(CRDD);
2335    SERIALIZE_SCALAR(rxPktBytes);
2336    SERIALIZE_SCALAR(rxFifoCnt);
2337    SERIALIZE_SCALAR(rxHalt);
2338    SERIALIZE_SCALAR(rxDescCnt);
2339    int rxDmaState = this->rxDmaState;
2340    SERIALIZE_SCALAR(rxDmaState);
2341
2342    SERIALIZE_SCALAR(extstsEnable);
2343
2344    /*
2345     * If there's a pending transmit, store the time so we can
2346     * reschedule it later
2347     */
2348    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2349    SERIALIZE_SCALAR(transmitTick);
2350
2351    /*
2352     * receive address filter settings
2353     */
2354    SERIALIZE_SCALAR(rxFilterEnable);
2355    SERIALIZE_SCALAR(acceptBroadcast);
2356    SERIALIZE_SCALAR(acceptMulticast);
2357    SERIALIZE_SCALAR(acceptUnicast);
2358    SERIALIZE_SCALAR(acceptPerfect);
2359    SERIALIZE_SCALAR(acceptArp);
2360
2361    /*
2362     * Keep track of pending interrupt status.
2363     */
2364    SERIALIZE_SCALAR(intrTick);
2365    SERIALIZE_SCALAR(cpuPendingIntr);
2366    Tick intrEventTick = 0;
2367    if (intrEvent)
2368        intrEventTick = intrEvent->when();
2369    SERIALIZE_SCALAR(intrEventTick);
2370
2371}
2372
2373void
2374NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2375{
2376    // Unserialize the PciDev base class
2377    PciDev::unserialize(cp, section);
2378
2379    UNSERIALIZE_SCALAR(regs.command);
2380    UNSERIALIZE_SCALAR(regs.config);
2381    UNSERIALIZE_SCALAR(regs.mear);
2382    UNSERIALIZE_SCALAR(regs.ptscr);
2383    UNSERIALIZE_SCALAR(regs.isr);
2384    UNSERIALIZE_SCALAR(regs.imr);
2385    UNSERIALIZE_SCALAR(regs.ier);
2386    UNSERIALIZE_SCALAR(regs.ihr);
2387    UNSERIALIZE_SCALAR(regs.txdp);
2388    UNSERIALIZE_SCALAR(regs.txdp_hi);
2389    UNSERIALIZE_SCALAR(regs.txcfg);
2390    UNSERIALIZE_SCALAR(regs.gpior);
2391    UNSERIALIZE_SCALAR(regs.rxdp);
2392    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2393    UNSERIALIZE_SCALAR(regs.rxcfg);
2394    UNSERIALIZE_SCALAR(regs.pqcr);
2395    UNSERIALIZE_SCALAR(regs.wcsr);
2396    UNSERIALIZE_SCALAR(regs.pcr);
2397    UNSERIALIZE_SCALAR(regs.rfcr);
2398    UNSERIALIZE_SCALAR(regs.rfdr);
2399    UNSERIALIZE_SCALAR(regs.srr);
2400    UNSERIALIZE_SCALAR(regs.mibc);
2401    UNSERIALIZE_SCALAR(regs.vrcr);
2402    UNSERIALIZE_SCALAR(regs.vtcr);
2403    UNSERIALIZE_SCALAR(regs.vdr);
2404    UNSERIALIZE_SCALAR(regs.ccsr);
2405    UNSERIALIZE_SCALAR(regs.tbicr);
2406    UNSERIALIZE_SCALAR(regs.tbisr);
2407    UNSERIALIZE_SCALAR(regs.tanar);
2408    UNSERIALIZE_SCALAR(regs.tanlpar);
2409    UNSERIALIZE_SCALAR(regs.taner);
2410    UNSERIALIZE_SCALAR(regs.tesr);
2411
2412    UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
2413
2414    UNSERIALIZE_SCALAR(ioEnable);
2415
2416    /*
2417     * unserialize the data fifos
2418     */
2419    int txNumPkts;
2420    UNSERIALIZE_SCALAR(txNumPkts);
2421    int i;
2422    for (i = 0; i < txNumPkts; ++i) {
2423        PacketPtr p = new EtherPacket;
2424        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
2425        txFifo.push_back(p);
2426    }
2427
2428    int rxNumPkts;
2429    UNSERIALIZE_SCALAR(rxNumPkts);
2430    for (i = 0; i < rxNumPkts; ++i) {
2431        PacketPtr p = new EtherPacket;
2432        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
2433        rxFifo.push_back(p);
2434    }
2435
2436    /*
2437     * unserialize the various helper variables
2438     */
2439    bool txPacketExists;
2440    UNSERIALIZE_SCALAR(txPacketExists);
2441    if (txPacketExists) {
2442        txPacket = new EtherPacket;
2443        txPacket->unserialize(cp, csprintf("%s.txPacket", section));
2444        uint32_t txPktBufPtr;
2445        UNSERIALIZE_SCALAR(txPktBufPtr);
2446        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2447    } else
2448        txPacket = 0;
2449
2450    bool rxPacketExists;
2451    UNSERIALIZE_SCALAR(rxPacketExists);
2452    rxPacket = 0;
2453    if (rxPacketExists) {
2454        rxPacket = new EtherPacket;
2455        rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
2456        uint32_t rxPktBufPtr;
2457        UNSERIALIZE_SCALAR(rxPktBufPtr);
2458        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2459    } else
2460        rxPacket = 0;
2461
2462    UNSERIALIZE_SCALAR(txXferLen);
2463    UNSERIALIZE_SCALAR(rxXferLen);
2464
2465    /*
2466     * Unserialize DescCaches
2467     */
2468    UNSERIALIZE_SCALAR(txDescCache.link);
2469    UNSERIALIZE_SCALAR(txDescCache.bufptr);
2470    UNSERIALIZE_SCALAR(txDescCache.cmdsts);
2471    UNSERIALIZE_SCALAR(txDescCache.extsts);
2472    UNSERIALIZE_SCALAR(rxDescCache.link);
2473    UNSERIALIZE_SCALAR(rxDescCache.bufptr);
2474    UNSERIALIZE_SCALAR(rxDescCache.cmdsts);
2475    UNSERIALIZE_SCALAR(rxDescCache.extsts);
2476
2477    /*
2478     * unserialize tx state machine
2479     */
2480    int txState;
2481    UNSERIALIZE_SCALAR(txState);
2482    this->txState = (TxState) txState;
2483    UNSERIALIZE_SCALAR(CTDD);
2484    UNSERIALIZE_SCALAR(txFifoAvail);
2485    UNSERIALIZE_SCALAR(txHalt);
2486    UNSERIALIZE_SCALAR(txFragPtr);
2487    UNSERIALIZE_SCALAR(txDescCnt);
2488    int txDmaState;
2489    UNSERIALIZE_SCALAR(txDmaState);
2490    this->txDmaState = (DmaState) txDmaState;
2491
2492    /*
2493     * unserialize rx state machine
2494     */
2495    int rxState;
2496    UNSERIALIZE_SCALAR(rxState);
2497    this->rxState = (RxState) rxState;
2498    UNSERIALIZE_SCALAR(CRDD);
2499    UNSERIALIZE_SCALAR(rxPktBytes);
2500    UNSERIALIZE_SCALAR(rxFifoCnt);
2501    UNSERIALIZE_SCALAR(rxHalt);
2502    UNSERIALIZE_SCALAR(rxDescCnt);
2503    int rxDmaState;
2504    UNSERIALIZE_SCALAR(rxDmaState);
2505    this->rxDmaState = (DmaState) rxDmaState;
2506
2507    UNSERIALIZE_SCALAR(extstsEnable);
2508
2509     /*
2510     * If there's a pending transmit, reschedule it now
2511     */
2512    Tick transmitTick;
2513    UNSERIALIZE_SCALAR(transmitTick);
2514    if (transmitTick)
2515        txEvent.schedule(curTick + transmitTick);
2516
2517    /*
2518     * unserialize receive address filter settings
2519     */
2520    UNSERIALIZE_SCALAR(rxFilterEnable);
2521    UNSERIALIZE_SCALAR(acceptBroadcast);
2522    UNSERIALIZE_SCALAR(acceptMulticast);
2523    UNSERIALIZE_SCALAR(acceptUnicast);
2524    UNSERIALIZE_SCALAR(acceptPerfect);
2525    UNSERIALIZE_SCALAR(acceptArp);
2526
2527    /*
2528     * Keep track of pending interrupt status.
2529     */
2530    UNSERIALIZE_SCALAR(intrTick);
2531    UNSERIALIZE_SCALAR(cpuPendingIntr);
2532    Tick intrEventTick;
2533    UNSERIALIZE_SCALAR(intrEventTick);
2534    if (intrEventTick) {
2535        intrEvent = new IntrEvent(this, true);
2536        intrEvent->schedule(intrEventTick);
2537    }
2538
2539    /*
2540     * re-add addrRanges to bus bridges
2541     */
2542    if (pioInterface) {
2543        pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
2544        pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
2545    }
2546}
2547
2548Tick
2549NSGigE::cacheAccess(MemReqPtr &req)
2550{
2551    DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
2552            req->paddr, req->paddr - addr);
2553    return curTick + pioLatency;
2554}
2555//=====================================================================
2556
2557
2558//********** helper functions******************************************
2559
2560uint16_t reverseEnd16(uint16_t num)
2561{
2562    uint16_t reverse = (num & 0xff)<<8;
2563    reverse += ((num & 0xff00) >> 8);
2564    return reverse;
2565}
2566
2567uint32_t reverseEnd32(uint32_t num)
2568{
2569    uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16;
2570    reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8));
2571    return reverse;
2572}
2573
2574
2575
2576//=====================================================================
2577
2578BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2579
2580    SimObjectParam<EtherInt *> peer;
2581    SimObjectParam<NSGigE *> device;
2582
2583END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2584
2585BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2586
2587    INIT_PARAM_DFLT(peer, "peer interface", NULL),
2588    INIT_PARAM(device, "Ethernet device of this interface")
2589
2590END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2591
2592CREATE_SIM_OBJECT(NSGigEInt)
2593{
2594    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
2595
2596    EtherInt *p = (EtherInt *)peer;
2597    if (p) {
2598        dev_int->setPeer(p);
2599        p->setPeer(dev_int);
2600    }
2601
2602    return dev_int;
2603}
2604
2605REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
2606
2607
2608BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2609
2610    Param<Tick> tx_delay;
2611    Param<Tick> rx_delay;
2612    SimObjectParam<IntrControl *> intr_ctrl;
2613    Param<Tick> intr_delay;
2614    SimObjectParam<MemoryController *> mmu;
2615    SimObjectParam<PhysicalMemory *> physmem;
2616    Param<bool> rx_filter;
2617    Param<string> hardware_address;
2618    SimObjectParam<Bus*> header_bus;
2619    SimObjectParam<Bus*> payload_bus;
2620    SimObjectParam<HierParams *> hier;
2621    Param<Tick> pio_latency;
2622    Param<bool> dma_desc_free;
2623    Param<bool> dma_data_free;
2624    Param<Tick> dma_read_delay;
2625    Param<Tick> dma_write_delay;
2626    Param<Tick> dma_read_factor;
2627    Param<Tick> dma_write_factor;
2628    SimObjectParam<PciConfigAll *> configspace;
2629    SimObjectParam<PciConfigData *> configdata;
2630    SimObjectParam<Tsunami *> tsunami;
2631    Param<uint32_t> pci_bus;
2632    Param<uint32_t> pci_dev;
2633    Param<uint32_t> pci_func;
2634
2635END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2636
2637BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
2638
2639    INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
2640    INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
2641    INIT_PARAM(intr_ctrl, "Interrupt Controller"),
2642    INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
2643    INIT_PARAM(mmu, "Memory Controller"),
2644    INIT_PARAM(physmem, "Physical Memory"),
2645    INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
2646    INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
2647                    "00:99:00:00:00:01"),
2648    INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
2649    INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
2650    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
2651    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
2652    INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false),
2653    INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false),
2654    INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
2655    INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
2656    INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
2657    INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
2658    INIT_PARAM(configspace, "PCI Configspace"),
2659    INIT_PARAM(configdata, "PCI Config data"),
2660    INIT_PARAM(tsunami, "Tsunami"),
2661    INIT_PARAM(pci_bus, "PCI bus"),
2662    INIT_PARAM(pci_dev, "PCI device number"),
2663    INIT_PARAM(pci_func, "PCI function code")
2664
2665END_INIT_SIM_OBJECT_PARAMS(NSGigE)
2666
2667
2668CREATE_SIM_OBJECT(NSGigE)
2669{
2670    int eaddr[6];
2671    sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
2672           &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
2673
2674    return new NSGigE(getInstanceName(), intr_ctrl, intr_delay,
2675                      physmem, tx_delay, rx_delay, mmu, hier, header_bus,
2676                      payload_bus, pio_latency, dma_desc_free, dma_data_free,
2677                      dma_read_delay, dma_write_delay, dma_read_factor,
2678                      dma_write_factor, configspace, configdata,
2679                      tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr);
2680}
2681
2682REGISTER_SIM_OBJECT("NSGigE", NSGigE)
2683