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