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