sinic.cc revision 1997
1/*
2 * Copyright (c) 2004-2005 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#include <cstdio>
30#include <deque>
31#include <string>
32
33#include "base/inet.hh"
34#include "cpu/exec_context.hh"
35#include "cpu/intr_control.hh"
36#include "dev/etherlink.hh"
37#include "dev/sinic.hh"
38#include "dev/pciconfigall.hh"
39#include "mem/bus/bus.hh"
40#include "mem/bus/dma_interface.hh"
41#include "mem/bus/pio_interface.hh"
42#include "mem/bus/pio_interface_impl.hh"
43#include "mem/functional/memory_control.hh"
44#include "mem/functional/physical.hh"
45#include "sim/builder.hh"
46#include "sim/debug.hh"
47#include "sim/eventq.hh"
48#include "sim/host.hh"
49#include "sim/stats.hh"
50#include "targetarch/vtophys.hh"
51
52using namespace Net;
53
54namespace Sinic {
55
56const char *RxStateStrings[] =
57{
58    "rxIdle",
59    "rxFifoBlock",
60    "rxBeginCopy",
61    "rxCopy",
62    "rxCopyDone"
63};
64
65const char *TxStateStrings[] =
66{
67    "txIdle",
68    "txFifoBlock",
69    "txBeginCopy",
70    "txCopy",
71    "txCopyDone"
72};
73
74
75///////////////////////////////////////////////////////////////////////
76//
77// Sinic PCI Device
78//
79Base::Base(Params *p)
80    : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
81      intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
82      cpuPendingIntr(false), intrEvent(0), interface(NULL)
83{
84}
85
86Device::Device(Params *p)
87    : Base(p), plat(p->plat), physmem(p->physmem),
88      rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
89      rxKickTick(0), txKickTick(0),
90      txEvent(this), rxDmaEvent(this), txDmaEvent(this),
91      dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
92      dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
93{
94    reset();
95
96    if (p->pio_bus) {
97        pioInterface = newPioInterface(p->name + ".pio", p->hier, p->pio_bus,
98                                       this, &Device::cacheAccess);
99        pioLatency = p->pio_latency * p->pio_bus->clockRate;
100    }
101
102    if (p->header_bus) {
103        if (p->payload_bus)
104            dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
105                                                 p->header_bus,
106                                                 p->payload_bus, 1,
107                                                 p->dma_no_allocate);
108        else
109            dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
110                                                 p->header_bus,
111                                                 p->header_bus, 1,
112                                                 p->dma_no_allocate);
113    } else if (p->payload_bus)
114        panic("must define a header bus if defining a payload bus");
115
116    pioDelayWrite = p->pio_delay_write && pioInterface;
117}
118
119Device::~Device()
120{}
121
122void
123Device::regStats()
124{
125    rxBytes
126        .name(name() + ".rxBytes")
127        .desc("Bytes Received")
128        .prereq(rxBytes)
129        ;
130
131    rxBandwidth
132        .name(name() + ".rxBandwidth")
133        .desc("Receive Bandwidth (bits/s)")
134        .precision(0)
135        .prereq(rxBytes)
136        ;
137
138    rxPackets
139        .name(name() + ".rxPackets")
140        .desc("Number of Packets Received")
141        .prereq(rxBytes)
142        ;
143
144    rxPacketRate
145        .name(name() + ".rxPPS")
146        .desc("Packet Reception Rate (packets/s)")
147        .precision(0)
148        .prereq(rxBytes)
149        ;
150
151    rxIpPackets
152        .name(name() + ".rxIpPackets")
153        .desc("Number of IP Packets Received")
154        .prereq(rxBytes)
155        ;
156
157    rxTcpPackets
158        .name(name() + ".rxTcpPackets")
159        .desc("Number of Packets Received")
160        .prereq(rxBytes)
161        ;
162
163    rxUdpPackets
164        .name(name() + ".rxUdpPackets")
165        .desc("Number of UDP Packets Received")
166        .prereq(rxBytes)
167        ;
168
169    rxIpChecksums
170        .name(name() + ".rxIpChecksums")
171        .desc("Number of rx IP Checksums done by device")
172        .precision(0)
173        .prereq(rxBytes)
174        ;
175
176    rxTcpChecksums
177        .name(name() + ".rxTcpChecksums")
178        .desc("Number of rx TCP Checksums done by device")
179        .precision(0)
180        .prereq(rxBytes)
181        ;
182
183    rxUdpChecksums
184        .name(name() + ".rxUdpChecksums")
185        .desc("Number of rx UDP Checksums done by device")
186        .precision(0)
187        .prereq(rxBytes)
188        ;
189
190    totBandwidth
191        .name(name() + ".totBandwidth")
192        .desc("Total Bandwidth (bits/s)")
193        .precision(0)
194        .prereq(totBytes)
195        ;
196
197    totPackets
198        .name(name() + ".totPackets")
199        .desc("Total Packets")
200        .precision(0)
201        .prereq(totBytes)
202        ;
203
204    totBytes
205        .name(name() + ".totBytes")
206        .desc("Total Bytes")
207        .precision(0)
208        .prereq(totBytes)
209        ;
210
211    totPacketRate
212        .name(name() + ".totPPS")
213        .desc("Total Tranmission Rate (packets/s)")
214        .precision(0)
215        .prereq(totBytes)
216        ;
217
218    txBytes
219        .name(name() + ".txBytes")
220        .desc("Bytes Transmitted")
221        .prereq(txBytes)
222        ;
223
224    txBandwidth
225        .name(name() + ".txBandwidth")
226        .desc("Transmit Bandwidth (bits/s)")
227        .precision(0)
228        .prereq(txBytes)
229        ;
230
231    txPackets
232        .name(name() + ".txPackets")
233        .desc("Number of Packets Transmitted")
234        .prereq(txBytes)
235        ;
236
237    txPacketRate
238        .name(name() + ".txPPS")
239        .desc("Packet Tranmission Rate (packets/s)")
240        .precision(0)
241        .prereq(txBytes)
242        ;
243
244    txIpPackets
245        .name(name() + ".txIpPackets")
246        .desc("Number of IP Packets Transmitted")
247        .prereq(txBytes)
248        ;
249
250    txTcpPackets
251        .name(name() + ".txTcpPackets")
252        .desc("Number of TCP Packets Transmitted")
253        .prereq(txBytes)
254        ;
255
256    txUdpPackets
257        .name(name() + ".txUdpPackets")
258        .desc("Number of Packets Transmitted")
259        .prereq(txBytes)
260        ;
261
262    txIpChecksums
263        .name(name() + ".txIpChecksums")
264        .desc("Number of tx IP Checksums done by device")
265        .precision(0)
266        .prereq(txBytes)
267        ;
268
269    txTcpChecksums
270        .name(name() + ".txTcpChecksums")
271        .desc("Number of tx TCP Checksums done by device")
272        .precision(0)
273        .prereq(txBytes)
274        ;
275
276    txUdpChecksums
277        .name(name() + ".txUdpChecksums")
278        .desc("Number of tx UDP Checksums done by device")
279        .precision(0)
280        .prereq(txBytes)
281        ;
282
283    txBandwidth = txBytes * Stats::constant(8) / simSeconds;
284    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
285    totBandwidth = txBandwidth + rxBandwidth;
286    totBytes = txBytes + rxBytes;
287    totPackets = txPackets + rxPackets;
288    txPacketRate = txPackets / simSeconds;
289    rxPacketRate = rxPackets / simSeconds;
290}
291
292/**
293 * This is to write to the PCI general configuration registers
294 */
295void
296Device::writeConfig(int offset, int size, const uint8_t *data)
297{
298    switch (offset) {
299      case PCI0_BASE_ADDR0:
300        // Need to catch writes to BARs to update the PIO interface
301        PciDev::writeConfig(offset, size, data);
302        if (BARAddrs[0] != 0) {
303            if (pioInterface)
304                pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
305
306            BARAddrs[0] &= EV5::PAddrUncachedMask;
307        }
308        break;
309
310      default:
311        PciDev::writeConfig(offset, size, data);
312    }
313}
314
315void
316Device::prepareIO(int cpu)
317{
318    if (cpu >= writeQueue.size())
319        writeQueue.resize(cpu + 1);
320}
321
322void
323Device::prepareRead(int cpu)
324{
325    using namespace Regs;
326
327    // update rx registers
328    regs.RxDone = set_RxDone_Packets(regs.RxDone, rxFifo.packets());
329    regs.RxWait = regs.RxDone;
330
331    // update tx regsiters
332    regs.TxDone = set_TxDone_Packets(regs.TxDone, txFifo.packets());
333    regs.TxDone = set_TxDone_Full(regs.TxDone,
334                                  txFifo.avail() < regs.TxMaxCopy);
335    regs.TxDone = set_TxDone_Low(regs.TxDone,
336                                 txFifo.size() < regs.TxFifoMark);
337    regs.TxWait = regs.TxDone;
338}
339
340void
341Device::prepareWrite(int cpu)
342{
343    prepareIO(cpu);
344}
345
346/**
347 * I/O read of device register
348 */
349Fault
350Device::read(MemReqPtr &req, uint8_t *data)
351{
352    assert(config.command & PCI_CMD_MSE);
353    Fault fault = readBar(req, data);
354
355    if (fault == Machine_Check_Fault) {
356        panic("address does not map to a BAR pa=%#x va=%#x size=%d",
357              req->paddr, req->vaddr, req->size);
358
359        return Machine_Check_Fault;
360    }
361
362    return fault;
363}
364
365Fault
366Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
367{
368    int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
369
370    if (!regValid(daddr))
371        panic("invalid register: da=%#x pa=%#x va=%#x size=%d",
372              daddr, req->paddr, req->vaddr, req->size);
373
374    const Regs::Info &info = regInfo(daddr);
375    if (!info.read)
376        panic("reading write only register: %s: da=%#x pa=%#x va=%#x size=%d",
377              info.name, daddr, req->paddr, req->vaddr, req->size);
378
379    if (req->size != info.size)
380        panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
381              info.name, daddr, req->paddr, req->vaddr, req->size);
382
383    prepareRead(cpu);
384
385    uint64_t value = 0;
386    if (req->size == 4) {
387        uint32_t &reg = *(uint32_t *)data;
388        reg = regData32(daddr);
389        value = reg;
390    }
391
392    if (req->size == 8) {
393        uint64_t &reg = *(uint64_t *)data;
394        reg = regData64(daddr);
395        value = reg;
396    }
397
398    DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d val=%#x\n",
399            info.name, daddr, req->paddr, req->vaddr, req->size, value);
400
401    // reading the interrupt status register has the side effect of
402    // clearing it
403    if (daddr == Regs::IntrStatus)
404        devIntrClear();
405
406    return No_Fault;
407}
408
409/**
410 * IPR read of device register
411 */
412Fault
413Device::iprRead(Addr daddr, int cpu, uint64_t &result)
414{
415    if (!regValid(daddr))
416        panic("invalid address: da=%#x", daddr);
417
418    const Regs::Info &info = regInfo(daddr);
419    if (!info.read)
420        panic("reading write only register %s: da=%#x", info.name, daddr);
421
422    DPRINTF(EthernetPIO, "read reg=%s da=%#x\n", info.name, daddr);
423
424    prepareRead(cpu);
425
426    if (info.size == 4)
427        result = regData32(daddr);
428
429    if (info.size == 8)
430        result = regData64(daddr);
431
432    DPRINTF(EthernetPIO, "IPR read reg=%s da=%#x val=%#x\n",
433            info.name, result);
434
435    return No_Fault;
436}
437
438/**
439 * I/O write of device register
440 */
441Fault
442Device::write(MemReqPtr &req, const uint8_t *data)
443{
444    assert(config.command & PCI_CMD_MSE);
445    Fault fault = writeBar(req, data);
446
447    if (fault == Machine_Check_Fault) {
448        panic("address does not map to a BAR pa=%#x va=%#x size=%d",
449              req->paddr, req->vaddr, req->size);
450
451        return Machine_Check_Fault;
452    }
453
454    return fault;
455}
456
457Fault
458Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
459{
460    int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
461
462    if (!regValid(daddr))
463        panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
464              daddr, req->paddr, req->vaddr, req->size);
465
466    const Regs::Info &info = regInfo(daddr);
467    if (!info.write)
468        panic("writing read only register %s: da=%#x", info.name, daddr);
469
470    if (req->size != info.size)
471        panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
472              info.name, daddr, req->paddr, req->vaddr, req->size);
473
474    uint32_t reg32 = *(uint32_t *)data;
475    uint64_t reg64 = *(uint64_t *)data;
476
477    DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
478            info.name, info.size == 4 ? reg32 : reg64, daddr, req->paddr,
479            req->vaddr, req->size);
480
481    if (pioDelayWrite)
482        writeQueue[cpu].push_back(RegWriteData(daddr, reg64));
483
484    if (!pioDelayWrite || !info.delay_write)
485        regWrite(daddr, cpu, data);
486
487    return No_Fault;
488}
489
490void
491Device::regWrite(Addr daddr, int cpu, const uint8_t *data)
492{
493    uint32_t reg32 = *(uint32_t *)data;
494    uint64_t reg64 = *(uint64_t *)data;
495
496    switch (daddr) {
497      case Regs::Config:
498        changeConfig(reg32);
499        break;
500
501      case Regs::Command:
502        command(reg32);
503        break;
504
505      case Regs::IntrStatus:
506        devIntrClear(regs.IntrStatus & reg32);
507        break;
508
509      case Regs::IntrMask:
510        devIntrChangeMask(reg32);
511        break;
512
513      case Regs::RxData:
514        if (rxState != rxIdle)
515            panic("receive machine busy with another request! rxState=%s",
516                  RxStateStrings[rxState]);
517
518        regs.RxDone = Regs::RxDone_Busy;
519        regs.RxData = reg64;
520        if (rxEnable) {
521            rxState = rxFifoBlock;
522            rxKick();
523        }
524        break;
525
526      case Regs::TxData:
527        if (txState != txIdle)
528            panic("transmit machine busy with another request! txState=%s",
529                  TxStateStrings[txState]);
530
531        regs.TxDone = Regs::TxDone_Busy;
532        regs.TxData = reg64;
533        if (txEnable) {
534            txState = txFifoBlock;
535            txKick();
536        }
537        break;
538    }
539}
540
541void
542Device::devIntrPost(uint32_t interrupts)
543{
544    if ((interrupts & Regs::Intr_Res))
545        panic("Cannot set a reserved interrupt");
546
547    regs.IntrStatus |= interrupts;
548
549    DPRINTF(EthernetIntr,
550            "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
551            interrupts, regs.IntrStatus, regs.IntrMask);
552
553    interrupts = regs.IntrStatus & regs.IntrMask;
554
555    // Intr_RxHigh is special, we only signal it if we've emptied the fifo
556    // and then filled it above the high watermark
557    if (rxEmpty)
558        rxEmpty = false;
559    else
560        interrupts &= ~Regs::Intr_RxHigh;
561
562    // Intr_TxLow is special, we only signal it if we've filled up the fifo
563    // and then dropped below the low watermark
564    if (txFull)
565        txFull = false;
566    else
567        interrupts &= ~Regs::Intr_TxLow;
568
569    if (interrupts) {
570        Tick when = curTick;
571        if ((interrupts & Regs::Intr_NoDelay) == 0)
572            when += intrDelay;
573        cpuIntrPost(when);
574    }
575}
576
577void
578Device::devIntrClear(uint32_t interrupts)
579{
580    if ((interrupts & Regs::Intr_Res))
581        panic("Cannot clear a reserved interrupt");
582
583    regs.IntrStatus &= ~interrupts;
584
585    DPRINTF(EthernetIntr,
586            "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
587            interrupts, regs.IntrStatus, regs.IntrMask);
588
589    if (!(regs.IntrStatus & regs.IntrMask))
590        cpuIntrClear();
591}
592
593void
594Device::devIntrChangeMask(uint32_t newmask)
595{
596    if (regs.IntrMask == newmask)
597        return;
598
599    regs.IntrMask = newmask;
600
601    DPRINTF(EthernetIntr,
602            "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
603            regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
604
605    if (regs.IntrStatus & regs.IntrMask)
606        cpuIntrPost(curTick);
607    else
608        cpuIntrClear();
609}
610
611void
612Base::cpuIntrPost(Tick when)
613{
614    // If the interrupt you want to post is later than an interrupt
615    // already scheduled, just let it post in the coming one and don't
616    // schedule another.
617    // HOWEVER, must be sure that the scheduled intrTick is in the
618    // future (this was formerly the source of a bug)
619    /**
620     * @todo this warning should be removed and the intrTick code should
621     * be fixed.
622     */
623    assert(when >= curTick);
624    assert(intrTick >= curTick || intrTick == 0);
625    if (!cpuIntrEnable) {
626        DPRINTF(EthernetIntr, "interrupts not enabled.\n",
627                intrTick);
628        return;
629    }
630
631    if (when > intrTick && intrTick != 0) {
632        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
633                intrTick);
634        return;
635    }
636
637    intrTick = when;
638    if (intrTick < curTick) {
639        debug_break();
640        intrTick = curTick;
641    }
642
643    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
644            intrTick);
645
646    if (intrEvent)
647        intrEvent->squash();
648    intrEvent = new IntrEvent(this, true);
649    intrEvent->schedule(intrTick);
650}
651
652void
653Base::cpuInterrupt()
654{
655    assert(intrTick == curTick);
656
657    // Whether or not there's a pending interrupt, we don't care about
658    // it anymore
659    intrEvent = 0;
660    intrTick = 0;
661
662    // Don't send an interrupt if there's already one
663    if (cpuPendingIntr) {
664        DPRINTF(EthernetIntr,
665                "would send an interrupt now, but there's already pending\n");
666    } else {
667        // Send interrupt
668        cpuPendingIntr = true;
669
670        DPRINTF(EthernetIntr, "posting interrupt\n");
671        intrPost();
672    }
673}
674
675void
676Base::cpuIntrClear()
677{
678    if (!cpuPendingIntr)
679        return;
680
681    if (intrEvent) {
682        intrEvent->squash();
683        intrEvent = 0;
684    }
685
686    intrTick = 0;
687
688    cpuPendingIntr = false;
689
690    DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
691    intrClear();
692}
693
694bool
695Base::cpuIntrPending() const
696{ return cpuPendingIntr; }
697
698void
699Device::changeConfig(uint32_t newconf)
700{
701    uint32_t changed = regs.Config ^ newconf;
702    if (!changed)
703        return;
704
705    regs.Config = newconf;
706
707    if ((changed & Regs::Config_IntEn)) {
708        cpuIntrEnable = regs.Config & Regs::Config_IntEn;
709        if (cpuIntrEnable) {
710            if (regs.IntrStatus & regs.IntrMask)
711                cpuIntrPost(curTick);
712        } else {
713            cpuIntrClear();
714        }
715    }
716
717    if ((changed & Regs::Config_TxEn)) {
718        txEnable = regs.Config & Regs::Config_TxEn;
719        if (txEnable)
720            txKick();
721    }
722
723    if ((changed & Regs::Config_RxEn)) {
724        rxEnable = regs.Config & Regs::Config_RxEn;
725        if (rxEnable)
726            rxKick();
727    }
728}
729
730void
731Device::command(uint32_t command)
732{
733    if (command & Regs::Command_Reset)
734        reset();
735}
736
737void
738Device::reset()
739{
740    using namespace Regs;
741
742    memset(&regs, 0, sizeof(regs));
743
744    regs.Config = 0;
745    if (params()->dedicated)
746        regs.Config |= Config_Thread;
747    regs.IntrMask = Intr_RxHigh | Intr_RxDMA | Intr_TxLow;
748    regs.RxMaxCopy = params()->rx_max_copy;
749    regs.TxMaxCopy = params()->tx_max_copy;
750    regs.RxMaxIntr = params()->rx_max_intr;
751    regs.RxFifoSize = params()->rx_fifo_size;
752    regs.TxFifoSize = params()->tx_fifo_size;
753    regs.RxFifoMark = params()->rx_fifo_threshold;
754    regs.TxFifoMark = params()->tx_fifo_threshold;
755    regs.HwAddr = params()->eaddr;
756
757    rxState = rxIdle;
758    txState = txIdle;
759
760    rxFifo.clear();
761    txFifo.clear();
762    rxEmpty = false;
763    txFull = false;
764}
765
766void
767Device::rxDmaCopy()
768{
769    assert(rxState == rxCopy);
770    rxState = rxCopyDone;
771    physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
772    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
773            rxDmaAddr, rxDmaLen);
774    DDUMP(EthernetData, rxDmaData, rxDmaLen);
775}
776
777void
778Device::rxDmaDone()
779{
780    rxDmaCopy();
781
782    // If the transmit state machine  has a pending DMA, let it go first
783    if (txState == txBeginCopy)
784        txKick();
785
786    rxKick();
787}
788
789void
790Device::rxKick()
791{
792    DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n",
793            RxStateStrings[rxState], rxFifo.size());
794
795    if (rxKickTick > curTick) {
796        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
797                rxKickTick);
798        return;
799    }
800
801  next:
802    switch (rxState) {
803      case rxIdle:
804        goto exit;
805
806      case rxFifoBlock:
807        if (rxPacket) {
808            rxState = rxBeginCopy;
809            break;
810        }
811
812        if (rxFifo.empty()) {
813            DPRINTF(EthernetSM, "receive waiting for data.  Nothing to do.\n");
814            goto exit;
815        }
816
817        // Grab a new packet from the fifo.
818        rxPacket = rxFifo.front();
819        rxPacketBufPtr = rxPacket->data;
820        rxPktBytes = rxPacket->length;
821        assert(rxPktBytes);
822
823        rxDoneData = 0;
824        /* scope for variables */ {
825            IpPtr ip(rxPacket);
826            if (ip) {
827                rxDoneData |= Regs::RxDone_IpPacket;
828                rxIpChecksums++;
829                if (cksum(ip) != 0) {
830                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
831                    rxDoneData |= Regs::RxDone_IpError;
832                }
833                TcpPtr tcp(ip);
834                UdpPtr udp(ip);
835                if (tcp) {
836                    rxDoneData |= Regs::RxDone_TcpPacket;
837                    rxTcpChecksums++;
838                    if (cksum(tcp) != 0) {
839                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
840                        rxDoneData |= Regs::RxDone_TcpError;
841                    }
842                } else if (udp) {
843                    rxDoneData |= Regs::RxDone_UdpPacket;
844                    rxUdpChecksums++;
845                    if (cksum(udp) != 0) {
846                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
847                        rxDoneData |= Regs::RxDone_UdpError;
848                    }
849                }
850            }
851        }
852        rxState = rxBeginCopy;
853        break;
854
855      case rxBeginCopy:
856        if (dmaInterface && dmaInterface->busy())
857            goto exit;
858
859        rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData));
860        rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes);
861        rxDmaData = rxPacketBufPtr;
862        rxState = rxCopy;
863
864        if (dmaInterface) {
865            dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
866                                curTick, &rxDmaEvent, true);
867            goto exit;
868        }
869
870        if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
871            Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
872            Tick start = curTick + dmaWriteDelay + factor;
873            rxDmaEvent.schedule(start);
874            goto exit;
875        }
876
877        rxDmaCopy();
878        break;
879
880      case rxCopy:
881        DPRINTF(EthernetSM, "receive machine still copying\n");
882        goto exit;
883
884      case rxCopyDone:
885        regs.RxDone = rxDoneData | rxDmaLen;
886
887        if (rxPktBytes == rxDmaLen) {
888            rxPacket = NULL;
889            rxFifo.pop();
890        } else {
891            regs.RxDone |= Regs::RxDone_More;
892            rxPktBytes -= rxDmaLen;
893            rxPacketBufPtr += rxDmaLen;
894        }
895
896        regs.RxDone |= Regs::RxDone_Complete;
897        devIntrPost(Regs::Intr_RxDMA);
898        rxState = rxIdle;
899        break;
900
901      default:
902        panic("Invalid rxState!");
903    }
904
905    DPRINTF(EthernetSM, "entering next rxState=%s\n",
906            RxStateStrings[rxState]);
907
908    goto next;
909
910  exit:
911    /**
912     * @todo do we want to schedule a future kick?
913     */
914    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
915            RxStateStrings[rxState]);
916}
917
918void
919Device::txDmaCopy()
920{
921    assert(txState == txCopy);
922    txState = txCopyDone;
923    physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
924    DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
925            txDmaAddr, txDmaLen);
926    DDUMP(EthernetData, txDmaData, txDmaLen);
927}
928
929void
930Device::txDmaDone()
931{
932    txDmaCopy();
933
934    // If the receive state machine  has a pending DMA, let it go first
935    if (rxState == rxBeginCopy)
936        rxKick();
937
938    txKick();
939}
940
941void
942Device::transmit()
943{
944    if (txFifo.empty()) {
945        DPRINTF(Ethernet, "nothing to transmit\n");
946        return;
947    }
948
949    uint32_t interrupts;
950    PacketPtr packet = txFifo.front();
951    if (!interface->sendPacket(packet)) {
952        DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
953                txFifo.avail());
954        goto reschedule;
955    }
956
957    txFifo.pop();
958#if TRACING_ON
959    if (DTRACE(Ethernet)) {
960        IpPtr ip(packet);
961        if (ip) {
962            DPRINTF(Ethernet, "ID is %d\n", ip->id());
963            TcpPtr tcp(ip);
964            if (tcp) {
965                DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
966                        tcp->sport(), tcp->dport());
967            }
968        }
969    }
970#endif
971
972    DDUMP(EthernetData, packet->data, packet->length);
973    txBytes += packet->length;
974    txPackets++;
975
976    DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
977            txFifo.avail());
978
979    interrupts = Regs::Intr_TxPacket;
980    if (txFifo.size() < regs.TxFifoMark)
981        interrupts |= Regs::Intr_TxLow;
982    devIntrPost(interrupts);
983
984  reschedule:
985   if (!txFifo.empty() && !txEvent.scheduled()) {
986       DPRINTF(Ethernet, "reschedule transmit\n");
987       txEvent.schedule(curTick + retryTime);
988   }
989}
990
991void
992Device::txKick()
993{
994    DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n",
995            TxStateStrings[txState], txFifo.size());
996
997    if (txKickTick > curTick) {
998        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
999                txKickTick);
1000        return;
1001    }
1002
1003  next:
1004    switch (txState) {
1005      case txIdle:
1006        goto exit;
1007
1008      case txFifoBlock:
1009        if (!txPacket) {
1010            // Grab a new packet from the fifo.
1011            txPacket = new PacketData(16384);
1012            txPacketBufPtr = txPacket->data;
1013        }
1014
1015        if (txFifo.avail() - txPacket->length <
1016            Regs::get_TxData_Len(regs.TxData)) {
1017            DPRINTF(EthernetSM, "transmit fifo full.  Nothing to do.\n");
1018            goto exit;
1019        }
1020
1021        txState = txBeginCopy;
1022        break;
1023
1024      case txBeginCopy:
1025        if (dmaInterface && dmaInterface->busy())
1026            goto exit;
1027
1028        txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
1029        txDmaLen = Regs::get_TxData_Len(regs.TxData);
1030        txDmaData = txPacketBufPtr;
1031        txState = txCopy;
1032
1033        if (dmaInterface) {
1034            dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
1035                                curTick, &txDmaEvent, true);
1036            goto exit;
1037        }
1038
1039        if (dmaReadDelay != 0 || dmaReadFactor != 0) {
1040            Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
1041            Tick start = curTick + dmaReadDelay + factor;
1042            txDmaEvent.schedule(start);
1043            goto exit;
1044        }
1045
1046        txDmaCopy();
1047        break;
1048
1049      case txCopy:
1050        DPRINTF(EthernetSM, "transmit machine still copying\n");
1051        goto exit;
1052
1053      case txCopyDone:
1054        txPacket->length += txDmaLen;
1055        if ((regs.TxData & Regs::TxData_More)) {
1056            txPacketBufPtr += txDmaLen;
1057        } else {
1058            assert(txPacket->length <= txFifo.avail());
1059            if ((regs.TxData & Regs::TxData_Checksum)) {
1060                IpPtr ip(txPacket);
1061                if (ip) {
1062                    TcpPtr tcp(ip);
1063                    if (tcp) {
1064                        tcp->sum(0);
1065                        tcp->sum(cksum(tcp));
1066                        txTcpChecksums++;
1067                    }
1068
1069                    UdpPtr udp(ip);
1070                    if (udp) {
1071                        udp->sum(0);
1072                        udp->sum(cksum(udp));
1073                        txUdpChecksums++;
1074                    }
1075
1076                    ip->sum(0);
1077                    ip->sum(cksum(ip));
1078                    txIpChecksums++;
1079                }
1080            }
1081            txFifo.push(txPacket);
1082            if (txFifo.avail() < regs.TxMaxCopy) {
1083                devIntrPost(Regs::Intr_TxFull);
1084                txFull = true;
1085            }
1086            txPacket = 0;
1087            transmit();
1088        }
1089
1090        regs.TxDone = txDmaLen | Regs::TxDone_Complete;
1091        devIntrPost(Regs::Intr_TxDMA);
1092        txState = txIdle;
1093        break;
1094
1095      default:
1096        panic("Invalid txState!");
1097    }
1098
1099    DPRINTF(EthernetSM, "entering next txState=%s\n",
1100            TxStateStrings[txState]);
1101
1102    goto next;
1103
1104  exit:
1105    /**
1106     * @todo do we want to schedule a future kick?
1107     */
1108    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1109            TxStateStrings[txState]);
1110}
1111
1112void
1113Device::transferDone()
1114{
1115    if (txFifo.empty()) {
1116        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
1117        return;
1118    }
1119
1120    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
1121
1122    if (txEvent.scheduled())
1123        txEvent.reschedule(curTick + cycles(1));
1124    else
1125        txEvent.schedule(curTick + cycles(1));
1126}
1127
1128bool
1129Device::rxFilter(const PacketPtr &packet)
1130{
1131    if (!Regs::get_Config_Filter(regs.Config))
1132        return false;
1133
1134    panic("receive filter not implemented\n");
1135    bool drop = true;
1136
1137#if 0
1138    string type;
1139
1140    EthHdr *eth = packet->eth();
1141    if (eth->unicast()) {
1142        // If we're accepting all unicast addresses
1143        if (acceptUnicast)
1144            drop = false;
1145
1146        // If we make a perfect match
1147        if (acceptPerfect && params->eaddr == eth.dst())
1148            drop = false;
1149
1150        if (acceptArp && eth->type() == ETH_TYPE_ARP)
1151            drop = false;
1152
1153    } else if (eth->broadcast()) {
1154        // if we're accepting broadcasts
1155        if (acceptBroadcast)
1156            drop = false;
1157
1158    } else if (eth->multicast()) {
1159        // if we're accepting all multicasts
1160        if (acceptMulticast)
1161            drop = false;
1162
1163    }
1164
1165    if (drop) {
1166        DPRINTF(Ethernet, "rxFilter drop\n");
1167        DDUMP(EthernetData, packet->data, packet->length);
1168    }
1169#endif
1170    return drop;
1171}
1172
1173bool
1174Device::recvPacket(PacketPtr packet)
1175{
1176    rxBytes += packet->length;
1177    rxPackets++;
1178
1179    DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
1180            rxFifo.avail());
1181
1182    if (!rxEnable) {
1183        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
1184        return true;
1185    }
1186
1187    if (rxFilter(packet)) {
1188        DPRINTF(Ethernet, "packet filtered...dropped\n");
1189        return true;
1190    }
1191
1192    if (rxFifo.size() >= regs.RxFifoMark)
1193        devIntrPost(Regs::Intr_RxHigh);
1194
1195    if (!rxFifo.push(packet)) {
1196        DPRINTF(Ethernet,
1197                "packet will not fit in receive buffer...packet dropped\n");
1198        return false;
1199    }
1200
1201    devIntrPost(Regs::Intr_RxPacket);
1202    rxKick();
1203    return true;
1204}
1205
1206//=====================================================================
1207//
1208//
1209void
1210Base::serialize(ostream &os)
1211{
1212    // Serialize the PciDev base class
1213    PciDev::serialize(os);
1214
1215    SERIALIZE_SCALAR(rxEnable);
1216    SERIALIZE_SCALAR(txEnable);
1217    SERIALIZE_SCALAR(cpuIntrEnable);
1218
1219    /*
1220     * Keep track of pending interrupt status.
1221     */
1222    SERIALIZE_SCALAR(intrTick);
1223    SERIALIZE_SCALAR(cpuPendingIntr);
1224    Tick intrEventTick = 0;
1225    if (intrEvent)
1226        intrEventTick = intrEvent->when();
1227    SERIALIZE_SCALAR(intrEventTick);
1228}
1229
1230void
1231Base::unserialize(Checkpoint *cp, const std::string &section)
1232{
1233    // Unserialize the PciDev base class
1234    PciDev::unserialize(cp, section);
1235
1236    UNSERIALIZE_SCALAR(rxEnable);
1237    UNSERIALIZE_SCALAR(txEnable);
1238    UNSERIALIZE_SCALAR(cpuIntrEnable);
1239
1240    /*
1241     * Keep track of pending interrupt status.
1242     */
1243    UNSERIALIZE_SCALAR(intrTick);
1244    UNSERIALIZE_SCALAR(cpuPendingIntr);
1245    Tick intrEventTick;
1246    UNSERIALIZE_SCALAR(intrEventTick);
1247    if (intrEventTick) {
1248        intrEvent = new IntrEvent(this, true);
1249        intrEvent->schedule(intrEventTick);
1250    }
1251}
1252
1253void
1254Device::serialize(ostream &os)
1255{
1256    // Serialize the PciDev base class
1257    Base::serialize(os);
1258
1259    if (rxState == rxCopy)
1260        panic("can't serialize with an in flight dma request rxState=%s",
1261              RxStateStrings[rxState]);
1262
1263    if (txState == txCopy)
1264        panic("can't serialize with an in flight dma request txState=%s",
1265              TxStateStrings[txState]);
1266
1267    /*
1268     * Serialize the device registers
1269     */
1270    SERIALIZE_SCALAR(regs.Config);
1271    SERIALIZE_SCALAR(regs.IntrStatus);
1272    SERIALIZE_SCALAR(regs.IntrMask);
1273    SERIALIZE_SCALAR(regs.RxMaxCopy);
1274    SERIALIZE_SCALAR(regs.TxMaxCopy);
1275    SERIALIZE_SCALAR(regs.RxMaxIntr);
1276    SERIALIZE_SCALAR(regs.RxData);
1277    SERIALIZE_SCALAR(regs.RxDone);
1278    SERIALIZE_SCALAR(regs.TxData);
1279    SERIALIZE_SCALAR(regs.TxDone);
1280
1281    /*
1282     * Serialize rx state machine
1283     */
1284    int rxState = this->rxState;
1285    SERIALIZE_SCALAR(rxState);
1286    SERIALIZE_SCALAR(rxEmpty);
1287    rxFifo.serialize("rxFifo", os);
1288    bool rxPacketExists = rxPacket;
1289    SERIALIZE_SCALAR(rxPacketExists);
1290    if (rxPacketExists) {
1291        rxPacket->serialize("rxPacket", os);
1292        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
1293        SERIALIZE_SCALAR(rxPktBufPtr);
1294        SERIALIZE_SCALAR(rxPktBytes);
1295    }
1296    SERIALIZE_SCALAR(rxDoneData);
1297
1298    /*
1299     * Serialize tx state machine
1300     */
1301    int txState = this->txState;
1302    SERIALIZE_SCALAR(txState);
1303    SERIALIZE_SCALAR(txFull);
1304    txFifo.serialize("txFifo", os);
1305    bool txPacketExists = txPacket;
1306    SERIALIZE_SCALAR(txPacketExists);
1307    if (txPacketExists) {
1308        txPacket->serialize("txPacket", os);
1309        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
1310        SERIALIZE_SCALAR(txPktBufPtr);
1311        SERIALIZE_SCALAR(txPktBytes);
1312    }
1313
1314    /*
1315     * If there's a pending transmit, store the time so we can
1316     * reschedule it later
1317     */
1318    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
1319    SERIALIZE_SCALAR(transmitTick);
1320}
1321
1322void
1323Device::unserialize(Checkpoint *cp, const std::string &section)
1324{
1325    // Unserialize the PciDev base class
1326    Base::unserialize(cp, section);
1327
1328    /*
1329     * Unserialize the device registers
1330     */
1331    UNSERIALIZE_SCALAR(regs.Config);
1332    UNSERIALIZE_SCALAR(regs.IntrStatus);
1333    UNSERIALIZE_SCALAR(regs.IntrMask);
1334    UNSERIALIZE_SCALAR(regs.RxMaxCopy);
1335    UNSERIALIZE_SCALAR(regs.TxMaxCopy);
1336    UNSERIALIZE_SCALAR(regs.RxMaxIntr);
1337    UNSERIALIZE_SCALAR(regs.RxData);
1338    UNSERIALIZE_SCALAR(regs.RxDone);
1339    UNSERIALIZE_SCALAR(regs.TxData);
1340    UNSERIALIZE_SCALAR(regs.TxDone);
1341
1342    /*
1343     * Unserialize rx state machine
1344     */
1345    int rxState;
1346    UNSERIALIZE_SCALAR(rxState);
1347    UNSERIALIZE_SCALAR(rxEmpty);
1348    this->rxState = (RxState) rxState;
1349    rxFifo.unserialize("rxFifo", cp, section);
1350    bool rxPacketExists;
1351    UNSERIALIZE_SCALAR(rxPacketExists);
1352    rxPacket = 0;
1353    if (rxPacketExists) {
1354        rxPacket = new PacketData(16384);
1355        rxPacket->unserialize("rxPacket", cp, section);
1356        uint32_t rxPktBufPtr;
1357        UNSERIALIZE_SCALAR(rxPktBufPtr);
1358        this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
1359        UNSERIALIZE_SCALAR(rxPktBytes);
1360    }
1361    UNSERIALIZE_SCALAR(rxDoneData);
1362
1363    /*
1364     * Unserialize tx state machine
1365     */
1366    int txState;
1367    UNSERIALIZE_SCALAR(txState);
1368    UNSERIALIZE_SCALAR(txFull);
1369    this->txState = (TxState) txState;
1370    txFifo.unserialize("txFifo", cp, section);
1371    bool txPacketExists;
1372    UNSERIALIZE_SCALAR(txPacketExists);
1373    txPacket = 0;
1374    if (txPacketExists) {
1375        txPacket = new PacketData(16384);
1376        txPacket->unserialize("txPacket", cp, section);
1377        uint32_t txPktBufPtr;
1378        UNSERIALIZE_SCALAR(txPktBufPtr);
1379        this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
1380        UNSERIALIZE_SCALAR(txPktBytes);
1381    }
1382
1383    /*
1384     * If there's a pending transmit, reschedule it now
1385     */
1386    Tick transmitTick;
1387    UNSERIALIZE_SCALAR(transmitTick);
1388    if (transmitTick)
1389        txEvent.schedule(curTick + transmitTick);
1390
1391    /*
1392     * re-add addrRanges to bus bridges
1393     */
1394    if (pioInterface) {
1395        pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
1396        pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
1397    }
1398}
1399
1400Tick
1401Device::cacheAccess(MemReqPtr &req)
1402{
1403    Addr daddr;
1404    int bar;
1405    if (!getBAR(req->paddr, daddr, bar))
1406        panic("address does not map to a BAR pa=%#x va=%#x size=%d",
1407              req->paddr, req->vaddr, req->size);
1408
1409    DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
1410            req->cmd.toString(), req->paddr, bar, daddr);
1411
1412    if (!pioDelayWrite || !req->cmd.isWrite())
1413        return curTick + pioLatency;
1414
1415    if (bar == 0) {
1416        int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
1417        std::list<RegWriteData> &wq = writeQueue[cpu];
1418        if (wq.empty())
1419            panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr);
1420
1421        const RegWriteData &data = wq.front();
1422        if (data.daddr != daddr)
1423            panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
1424                  cpu, data.daddr, daddr);
1425
1426        const Regs::Info &info = regInfo(data.daddr);
1427        if (info.delay_write)
1428            regWrite(daddr, cpu, (uint8_t *)&data.value);
1429
1430        wq.pop_front();
1431    }
1432
1433    return curTick + pioLatency;
1434}
1435
1436BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
1437
1438    SimObjectParam<EtherInt *> peer;
1439    SimObjectParam<Device *> device;
1440
1441END_DECLARE_SIM_OBJECT_PARAMS(Interface)
1442
1443BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
1444
1445    INIT_PARAM_DFLT(peer, "peer interface", NULL),
1446    INIT_PARAM(device, "Ethernet device of this interface")
1447
1448END_INIT_SIM_OBJECT_PARAMS(Interface)
1449
1450CREATE_SIM_OBJECT(Interface)
1451{
1452    Interface *dev_int = new Interface(getInstanceName(), device);
1453
1454    EtherInt *p = (EtherInt *)peer;
1455    if (p) {
1456        dev_int->setPeer(p);
1457        p->setPeer(dev_int);
1458    }
1459
1460    return dev_int;
1461}
1462
1463REGISTER_SIM_OBJECT("SinicInt", Interface)
1464
1465
1466BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
1467
1468    Param<Tick> clock;
1469
1470    Param<Addr> addr;
1471    SimObjectParam<MemoryController *> mmu;
1472    SimObjectParam<PhysicalMemory *> physmem;
1473    SimObjectParam<PciConfigAll *> configspace;
1474    SimObjectParam<PciConfigData *> configdata;
1475    SimObjectParam<Platform *> platform;
1476    Param<uint32_t> pci_bus;
1477    Param<uint32_t> pci_dev;
1478    Param<uint32_t> pci_func;
1479
1480    SimObjectParam<HierParams *> hier;
1481    SimObjectParam<Bus*> pio_bus;
1482    SimObjectParam<Bus*> dma_bus;
1483    SimObjectParam<Bus*> payload_bus;
1484    Param<Tick> dma_read_delay;
1485    Param<Tick> dma_read_factor;
1486    Param<Tick> dma_write_delay;
1487    Param<Tick> dma_write_factor;
1488    Param<bool> dma_no_allocate;
1489    Param<Tick> pio_latency;
1490    Param<bool> pio_delay_write;
1491    Param<Tick> intr_delay;
1492
1493    Param<Tick> rx_delay;
1494    Param<Tick> tx_delay;
1495    Param<uint32_t> rx_max_copy;
1496    Param<uint32_t> tx_max_copy;
1497    Param<uint32_t> rx_max_intr;
1498    Param<uint32_t> rx_fifo_size;
1499    Param<uint32_t> tx_fifo_size;
1500    Param<uint32_t> rx_fifo_threshold;
1501    Param<uint32_t> tx_fifo_threshold;
1502
1503    Param<bool> rx_filter;
1504    Param<string> hardware_address;
1505    Param<bool> dedicated;
1506
1507END_DECLARE_SIM_OBJECT_PARAMS(Device)
1508
1509BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
1510
1511    INIT_PARAM(clock, "State machine cycle time"),
1512
1513    INIT_PARAM(addr, "Device Address"),
1514    INIT_PARAM(mmu, "Memory Controller"),
1515    INIT_PARAM(physmem, "Physical Memory"),
1516    INIT_PARAM(configspace, "PCI Configspace"),
1517    INIT_PARAM(configdata, "PCI Config data"),
1518    INIT_PARAM(platform, "Platform"),
1519    INIT_PARAM(pci_bus, "PCI bus"),
1520    INIT_PARAM(pci_dev, "PCI device number"),
1521    INIT_PARAM(pci_func, "PCI function code"),
1522
1523    INIT_PARAM(hier, "Hierarchy global variables"),
1524    INIT_PARAM(pio_bus, ""),
1525    INIT_PARAM(dma_bus, ""),
1526    INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"),
1527    INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
1528    INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
1529    INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
1530    INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
1531    INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"),
1532    INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"),
1533    INIT_PARAM(pio_delay_write, ""),
1534    INIT_PARAM(intr_delay, "Interrupt Delay"),
1535
1536    INIT_PARAM(rx_delay, "Receive Delay"),
1537    INIT_PARAM(tx_delay, "Transmit Delay"),
1538    INIT_PARAM(rx_max_copy, "rx max copy"),
1539    INIT_PARAM(tx_max_copy, "rx max copy"),
1540    INIT_PARAM(rx_max_intr, "rx max intr"),
1541    INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
1542    INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
1543    INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
1544    INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
1545
1546    INIT_PARAM(rx_filter, "Enable Receive Filter"),
1547    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
1548    INIT_PARAM(dedicated, "dedicate a kernel thread to the driver")
1549
1550END_INIT_SIM_OBJECT_PARAMS(Device)
1551
1552
1553CREATE_SIM_OBJECT(Device)
1554{
1555    Device::Params *params = new Device::Params;
1556
1557    params->name = getInstanceName();
1558
1559    params->clock = clock;
1560
1561    params->mmu = mmu;
1562    params->physmem = physmem;
1563    params->configSpace = configspace;
1564    params->configData = configdata;
1565    params->plat = platform;
1566    params->busNum = pci_bus;
1567    params->deviceNum = pci_dev;
1568    params->functionNum = pci_func;
1569
1570    params->hier = hier;
1571    params->pio_bus = pio_bus;
1572    params->header_bus = dma_bus;
1573    params->payload_bus = payload_bus;
1574    params->dma_read_delay = dma_read_delay;
1575    params->dma_read_factor = dma_read_factor;
1576    params->dma_write_delay = dma_write_delay;
1577    params->dma_write_factor = dma_write_factor;
1578    params->dma_no_allocate = dma_no_allocate;
1579    params->pio_latency = pio_latency;
1580    params->pio_delay_write = pio_delay_write;
1581    params->intr_delay = intr_delay;
1582
1583    params->tx_delay = tx_delay;
1584    params->rx_delay = rx_delay;
1585    params->rx_max_copy = rx_max_copy;
1586    params->tx_max_copy = tx_max_copy;
1587    params->rx_max_intr = rx_max_intr;
1588    params->rx_fifo_size = rx_fifo_size;
1589    params->tx_fifo_size = tx_fifo_size;
1590    params->rx_fifo_threshold = rx_fifo_threshold;
1591    params->tx_fifo_threshold = tx_fifo_threshold;
1592
1593    params->rx_filter = rx_filter;
1594    params->eaddr = hardware_address;
1595    params->dedicated = dedicated;
1596
1597    return new Device(params);
1598}
1599
1600REGISTER_SIM_OBJECT("Sinic", Device)
1601
1602/* namespace Sinic */ }
1603