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