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