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