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