c28ab335b6d11c6062d99d1fc4cbc8a48b36b3f3
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
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"
53 using namespace TheISA
;
57 const char *RxStateStrings
[] =
66 const char *TxStateStrings
[] =
76 ///////////////////////////////////////////////////////////////////////
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
)
87 Device::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
)
98 pioInterface
= newPioInterface(p
->name
+ ".pio", p
->hier
, p
->pio_bus
,
99 this, &Device::cacheAccess
);
100 pioLatency
= p
->pio_latency
* p
->pio_bus
->clockRate
;
105 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
110 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
114 } else if (p
->payload_bus
)
115 panic("must define a header bus if defining a payload bus");
125 .name(name() + ".rxBytes")
126 .desc("Bytes Received")
131 .name(name() + ".rxBandwidth")
132 .desc("Receive Bandwidth (bits/s)")
138 .name(name() + ".rxPackets")
139 .desc("Number of Packets Received")
144 .name(name() + ".rxPPS")
145 .desc("Packet Reception Rate (packets/s)")
151 .name(name() + ".rxIpPackets")
152 .desc("Number of IP Packets Received")
157 .name(name() + ".rxTcpPackets")
158 .desc("Number of Packets Received")
163 .name(name() + ".rxUdpPackets")
164 .desc("Number of UDP Packets Received")
169 .name(name() + ".rxIpChecksums")
170 .desc("Number of rx IP Checksums done by device")
176 .name(name() + ".rxTcpChecksums")
177 .desc("Number of rx TCP Checksums done by device")
183 .name(name() + ".rxUdpChecksums")
184 .desc("Number of rx UDP Checksums done by device")
190 .name(name() + ".totBandwidth")
191 .desc("Total Bandwidth (bits/s)")
197 .name(name() + ".totPackets")
198 .desc("Total Packets")
204 .name(name() + ".totBytes")
211 .name(name() + ".totPPS")
212 .desc("Total Tranmission Rate (packets/s)")
218 .name(name() + ".txBytes")
219 .desc("Bytes Transmitted")
224 .name(name() + ".txBandwidth")
225 .desc("Transmit Bandwidth (bits/s)")
231 .name(name() + ".txPackets")
232 .desc("Number of Packets Transmitted")
237 .name(name() + ".txPPS")
238 .desc("Packet Tranmission Rate (packets/s)")
244 .name(name() + ".txIpPackets")
245 .desc("Number of IP Packets Transmitted")
250 .name(name() + ".txTcpPackets")
251 .desc("Number of TCP Packets Transmitted")
256 .name(name() + ".txUdpPackets")
257 .desc("Number of Packets Transmitted")
262 .name(name() + ".txIpChecksums")
263 .desc("Number of tx IP Checksums done by device")
269 .name(name() + ".txTcpChecksums")
270 .desc("Number of tx TCP Checksums done by device")
276 .name(name() + ".txUdpChecksums")
277 .desc("Number of tx UDP Checksums done by device")
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
;
292 * This is to write to the PCI general configuration registers
295 Device::writeConfig(int offset
, int size
, const uint8_t *data
)
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) {
303 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
305 BARAddrs
[0] &= EV5::PAddrUncachedMask
;
310 PciDev::writeConfig(offset
, size
, data
);
315 Device::prepareIO(int cpu
, int index
)
317 int size
= virtualRegs
.size();
321 virtualRegs
.resize(index
+ 1);
322 for (int i
= size
; i
<= index
; ++i
)
323 virtualRegs
[i
].rxPacket
= rxFifo
.end();
327 Device::prepareRead(int cpu
, int index
)
329 using namespace Regs
;
330 prepareIO(cpu
, index
);
332 VirtualReg
&vnic
= virtualRegs
[index
];
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
;
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
;
352 Device::prepareWrite(int cpu
, int index
)
354 prepareIO(cpu
, index
);
358 * I/O read of device register
361 Device::read(MemReqPtr
&req
, uint8_t *data
)
363 assert(config
.command
& PCI_CMD_MSE
);
364 Fault fault
= readBar(req
, data
);
366 if (fault
->isMachineCheckFault()) {
367 panic("address does not map to a BAR pa=%#x va=%#x size=%d",
368 req
->paddr
, req
->vaddr
, req
->size
);
370 return genMachineCheckFault();
377 Device::readBar0(MemReqPtr
&req
, Addr daddr
, uint8_t *data
)
379 int cpu
= (req
->xc
->regs
.ipr
[TheISA::IPR_PALtemp16
] >> 8) & 0xff;
380 Addr index
= daddr
>> Regs::VirtualShift
;
381 Addr raddr
= daddr
& Regs::VirtualMask
;
383 if (!regValid(raddr
))
384 panic("invalid register: cpu=%d, da=%#x pa=%#x va=%#x size=%d",
385 cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
387 const Regs::Info
&info
= regInfo(raddr
);
389 panic("reading %s (write only): cpu=%d da=%#x pa=%#x va=%#x size=%d",
390 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
392 if (req
->size
!= info
.size
)
393 panic("invalid size for reg %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
394 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
396 prepareRead(cpu
, index
);
399 if (req
->size
== 4) {
400 uint32_t ®
= *(uint32_t *)data
;
401 reg
= regData32(raddr
);
405 if (req
->size
== 8) {
406 uint64_t ®
= *(uint64_t *)data
;
407 reg
= regData64(raddr
);
412 "read %s cpu=%d da=%#x pa=%#x va=%#x size=%d val=%#x\n",
413 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
, value
);
415 // reading the interrupt status register has the side effect of
417 if (raddr
== Regs::IntrStatus
)
424 * IPR read of device register
427 Device::iprRead(Addr daddr
, int cpu
, uint64_t &result
)
429 if (!regValid(daddr
))
430 panic("invalid address: da=%#x", daddr
);
432 const Regs::Info
&info
= regInfo(daddr
);
434 panic("reading %s (write only): cpu=%d da=%#x", info
.name
, cpu
, daddr
);
436 DPRINTF(EthernetPIO
, "IPR read %s: cpu=%d da=%#x\n",
437 info
.name
, cpu
, daddr
);
442 result
= regData32(daddr
);
445 result
= regData64(daddr
);
447 DPRINTF(EthernetPIO
, "IPR read %s: cpu=%s da=%#x val=%#x\n",
448 info
.name
, cpu
, result
);
454 * I/O write of device register
457 Device::write(MemReqPtr
&req
, const uint8_t *data
)
459 assert(config
.command
& PCI_CMD_MSE
);
460 Fault fault
= writeBar(req
, data
);
462 if (fault
->isMachineCheckFault()) {
463 panic("address does not map to a BAR pa=%#x va=%#x size=%d",
464 req
->paddr
, req
->vaddr
, req
->size
);
466 return genMachineCheckFault();
473 Device::writeBar0(MemReqPtr
&req
, Addr daddr
, const uint8_t *data
)
475 int cpu
= (req
->xc
->regs
.ipr
[TheISA::IPR_PALtemp16
] >> 8) & 0xff;
476 Addr index
= daddr
>> Regs::VirtualShift
;
477 Addr raddr
= daddr
& Regs::VirtualMask
;
479 if (!regValid(raddr
))
480 panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d",
481 cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
483 const Regs::Info
&info
= regInfo(raddr
);
485 panic("writing %s (read only): cpu=%d da=%#x",
486 info
.name
, cpu
, daddr
);
488 if (req
->size
!= info
.size
)
489 panic("invalid size for %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
490 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
492 //These are commmented out because when the DPRINTF below isn't used,
493 //these values aren't used and gcc issues a warning. With -Werror,
494 //this prevents compilation.
495 //uint32_t reg32 = *(uint32_t *)data;
496 //uint64_t reg64 = *(uint64_t *)data;
498 "write %s: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n",
499 info
.name
, cpu
, info
.size
== 4 ?
500 (*(uint32_t *)data
) :
502 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
504 prepareWrite(cpu
, index
);
506 regWrite(daddr
, cpu
, data
);
512 Device::regWrite(Addr daddr
, int cpu
, const uint8_t *data
)
514 Addr index
= daddr
>> Regs::VirtualShift
;
515 Addr raddr
= daddr
& Regs::VirtualMask
;
517 uint32_t reg32
= *(uint32_t *)data
;
518 uint64_t reg64
= *(uint64_t *)data
;
519 VirtualReg
&vnic
= virtualRegs
[index
];
530 case Regs::IntrStatus
:
531 devIntrClear(regs
.IntrStatus
& reg32
);
535 devIntrChangeMask(reg32
);
539 if (Regs::get_RxDone_Busy(vnic
.RxDone
))
540 panic("receive machine busy with another request! rxState=%s",
541 RxStateStrings
[rxState
]);
543 vnic
.RxDone
= Regs::RxDone_Busy
;
545 rxList
.push_back(index
);
546 if (rxEnable
&& rxState
== rxIdle
) {
547 rxState
= rxFifoBlock
;
553 if (Regs::get_TxDone_Busy(vnic
.TxDone
))
554 panic("transmit machine busy with another request! txState=%s",
555 TxStateStrings
[txState
]);
557 vnic
.TxDone
= Regs::TxDone_Busy
;
559 if (txList
.empty() || txList
.front() != index
)
560 txList
.push_back(index
);
561 if (txEnable
&& txState
== txIdle
&& txList
.front() == index
) {
562 txState
= txFifoBlock
;
570 Device::devIntrPost(uint32_t interrupts
)
572 if ((interrupts
& Regs::Intr_Res
))
573 panic("Cannot set a reserved interrupt");
575 regs
.IntrStatus
|= interrupts
;
577 DPRINTF(EthernetIntr
,
578 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
579 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
581 interrupts
= regs
.IntrStatus
& regs
.IntrMask
;
583 // Intr_RxHigh is special, we only signal it if we've emptied the fifo
584 // and then filled it above the high watermark
588 interrupts
&= ~Regs::Intr_RxHigh
;
590 // Intr_TxLow is special, we only signal it if we've filled up the fifo
591 // and then dropped below the low watermark
595 interrupts
&= ~Regs::Intr_TxLow
;
599 if ((interrupts
& Regs::Intr_NoDelay
) == 0)
606 Device::devIntrClear(uint32_t interrupts
)
608 if ((interrupts
& Regs::Intr_Res
))
609 panic("Cannot clear a reserved interrupt");
611 regs
.IntrStatus
&= ~interrupts
;
613 DPRINTF(EthernetIntr
,
614 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
615 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
617 if (!(regs
.IntrStatus
& regs
.IntrMask
))
622 Device::devIntrChangeMask(uint32_t newmask
)
624 if (regs
.IntrMask
== newmask
)
627 regs
.IntrMask
= newmask
;
629 DPRINTF(EthernetIntr
,
630 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
631 regs
.IntrStatus
, regs
.IntrMask
, regs
.IntrStatus
& regs
.IntrMask
);
633 if (regs
.IntrStatus
& regs
.IntrMask
)
634 cpuIntrPost(curTick
);
640 Base::cpuIntrPost(Tick when
)
642 // If the interrupt you want to post is later than an interrupt
643 // already scheduled, just let it post in the coming one and don't
645 // HOWEVER, must be sure that the scheduled intrTick is in the
646 // future (this was formerly the source of a bug)
648 * @todo this warning should be removed and the intrTick code should
651 assert(when
>= curTick
);
652 assert(intrTick
>= curTick
|| intrTick
== 0);
653 if (!cpuIntrEnable
) {
654 DPRINTF(EthernetIntr
, "interrupts not enabled.\n",
659 if (when
> intrTick
&& intrTick
!= 0) {
660 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
666 if (intrTick
< curTick
) {
671 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
676 intrEvent
= new IntrEvent(this, true);
677 intrEvent
->schedule(intrTick
);
683 assert(intrTick
== curTick
);
685 // Whether or not there's a pending interrupt, we don't care about
690 // Don't send an interrupt if there's already one
691 if (cpuPendingIntr
) {
692 DPRINTF(EthernetIntr
,
693 "would send an interrupt now, but there's already pending\n");
696 cpuPendingIntr
= true;
698 DPRINTF(EthernetIntr
, "posting interrupt\n");
716 cpuPendingIntr
= false;
718 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
723 Base::cpuIntrPending() const
724 { return cpuPendingIntr
; }
727 Device::changeConfig(uint32_t newconf
)
729 uint32_t changed
= regs
.Config
^ newconf
;
733 regs
.Config
= newconf
;
735 if ((changed
& Regs::Config_IntEn
)) {
736 cpuIntrEnable
= regs
.Config
& Regs::Config_IntEn
;
738 if (regs
.IntrStatus
& regs
.IntrMask
)
739 cpuIntrPost(curTick
);
745 if ((changed
& Regs::Config_TxEn
)) {
746 txEnable
= regs
.Config
& Regs::Config_TxEn
;
751 if ((changed
& Regs::Config_RxEn
)) {
752 rxEnable
= regs
.Config
& Regs::Config_RxEn
;
759 Device::command(uint32_t command
)
761 if (command
& Regs::Command_Intr
)
762 devIntrPost(Regs::Intr_Soft
);
764 if (command
& Regs::Command_Reset
)
771 using namespace Regs
;
773 memset(®s
, 0, sizeof(regs
));
776 if (params()->rx_thread
)
777 regs
.Config
|= Config_RxThread
;
778 if (params()->tx_thread
)
779 regs
.Config
|= Config_TxThread
;
780 regs
.IntrMask
= Intr_Soft
| Intr_RxHigh
| Intr_RxPacket
| Intr_TxLow
;
781 regs
.RxMaxCopy
= params()->rx_max_copy
;
782 regs
.TxMaxCopy
= params()->tx_max_copy
;
783 regs
.RxMaxIntr
= params()->rx_max_intr
;
784 regs
.RxFifoSize
= params()->rx_fifo_size
;
785 regs
.TxFifoSize
= params()->tx_fifo_size
;
786 regs
.RxFifoMark
= params()->rx_fifo_threshold
;
787 regs
.TxFifoMark
= params()->tx_fifo_threshold
;
788 regs
.HwAddr
= params()->eaddr
;
797 rxFifoPtr
= rxFifo
.end();
802 int size
= virtualRegs
.size();
804 virtualRegs
.resize(size
);
805 for (int i
= 0; i
< size
; ++i
)
806 virtualRegs
[i
].rxPacket
= rxFifo
.end();
812 assert(rxState
== rxCopy
);
813 rxState
= rxCopyDone
;
814 physmem
->dma_write(rxDmaAddr
, (uint8_t *)rxDmaData
, rxDmaLen
);
815 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
816 rxDmaAddr
, rxDmaLen
);
817 DDUMP(EthernetData
, rxDmaData
, rxDmaLen
);
825 // If the transmit state machine has a pending DMA, let it go first
826 if (txState
== txBeginCopy
)
837 DPRINTF(EthernetSM
, "receive kick rxState=%s (rxFifo.size=%d)\n",
838 RxStateStrings
[rxState
], rxFifo
.size());
840 if (rxKickTick
> curTick
) {
841 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
847 if (rxState
== rxIdle
)
850 assert(!rxList
.empty());
851 vnic
= &virtualRegs
[rxList
.front()];
853 DPRINTF(EthernetSM
, "processing rxState=%s for virtual nic %d\n",
854 RxStateStrings
[rxState
], rxList
.front());
858 if (vnic
->rxPacket
!= rxFifo
.end()) {
859 rxState
= rxBeginCopy
;
863 if (rxFifoPtr
== rxFifo
.end()) {
864 DPRINTF(EthernetSM
, "receive waiting for data. Nothing to do.\n");
868 assert(!rxFifo
.empty());
870 // Grab a new packet from the fifo.
871 vnic
->rxPacket
= rxFifoPtr
++;
872 vnic
->rxPacketOffset
= 0;
873 vnic
->rxPacketBytes
= (*vnic
->rxPacket
)->length
;
874 assert(vnic
->rxPacketBytes
);
876 vnic
->rxDoneData
= 0;
877 /* scope for variables */ {
878 IpPtr
ip(*vnic
->rxPacket
);
880 vnic
->rxDoneData
|= Regs::RxDone_IpPacket
;
882 if (cksum(ip
) != 0) {
883 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
884 vnic
->rxDoneData
|= Regs::RxDone_IpError
;
889 vnic
->rxDoneData
|= Regs::RxDone_TcpPacket
;
891 if (cksum(tcp
) != 0) {
892 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
893 vnic
->rxDoneData
|= Regs::RxDone_TcpError
;
896 vnic
->rxDoneData
|= Regs::RxDone_UdpPacket
;
898 if (cksum(udp
) != 0) {
899 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
900 vnic
->rxDoneData
|= Regs::RxDone_UdpError
;
905 rxState
= rxBeginCopy
;
909 if (dmaInterface
&& dmaInterface
->busy())
912 rxDmaAddr
= plat
->pciToDma(Regs::get_RxData_Addr(vnic
->RxData
));
913 rxDmaLen
= min
<int>(Regs::get_RxData_Len(vnic
->RxData
),
914 vnic
->rxPacketBytes
);
915 rxDmaData
= (*vnic
->rxPacket
)->data
+ vnic
->rxPacketOffset
;
919 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
,
920 curTick
, &rxDmaEvent
, true);
924 if (dmaWriteDelay
!= 0 || dmaWriteFactor
!= 0) {
925 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
926 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
927 rxDmaEvent
.schedule(start
);
935 DPRINTF(EthernetSM
, "receive machine still copying\n");
939 vnic
->RxDone
= vnic
->rxDoneData
| rxDmaLen
;
940 vnic
->RxDone
|= Regs::RxDone_Complete
;
942 if (vnic
->rxPacketBytes
== rxDmaLen
) {
943 DPRINTF(EthernetSM
, "rxKick: packet complete on vnic %d\n",
945 rxFifo
.remove(vnic
->rxPacket
);
946 vnic
->rxPacket
= rxFifo
.end();
948 vnic
->RxDone
|= Regs::RxDone_More
;
949 vnic
->rxPacketBytes
-= rxDmaLen
;
950 vnic
->rxPacketOffset
+= rxDmaLen
;
952 "rxKick: packet not complete on vnic %d: %d bytes left\n",
953 rxList
.front(), vnic
->rxPacketBytes
);
957 rxState
= rxList
.empty() ? rxIdle
: rxFifoBlock
;
959 if (rxFifo
.empty()) {
960 devIntrPost(Regs::Intr_RxEmpty
);
964 devIntrPost(Regs::Intr_RxDMA
);
968 panic("Invalid rxState!");
971 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
972 RxStateStrings
[rxState
]);
978 * @todo do we want to schedule a future kick?
980 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
981 RxStateStrings
[rxState
]);
987 assert(txState
== txCopy
);
988 txState
= txCopyDone
;
989 physmem
->dma_read((uint8_t *)txDmaData
, txDmaAddr
, txDmaLen
);
990 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
991 txDmaAddr
, txDmaLen
);
992 DDUMP(EthernetData
, txDmaData
, txDmaLen
);
1000 // If the receive state machine has a pending DMA, let it go first
1001 if (rxState
== rxBeginCopy
)
1010 if (txFifo
.empty()) {
1011 DPRINTF(Ethernet
, "nothing to transmit\n");
1015 uint32_t interrupts
;
1016 PacketPtr packet
= txFifo
.front();
1017 if (!interface
->sendPacket(packet
)) {
1018 DPRINTF(Ethernet
, "Packet Transmit: failed txFifo available %d\n",
1025 if (DTRACE(Ethernet
)) {
1028 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
1031 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
1032 tcp
->sport(), tcp
->dport());
1038 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1039 txBytes
+= packet
->length
;
1042 DPRINTF(Ethernet
, "Packet Transmit: successful txFifo Available %d\n",
1045 interrupts
= Regs::Intr_TxPacket
;
1046 if (txFifo
.size() < regs
.TxFifoMark
)
1047 interrupts
|= Regs::Intr_TxLow
;
1048 devIntrPost(interrupts
);
1051 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1052 DPRINTF(Ethernet
, "reschedule transmit\n");
1053 txEvent
.schedule(curTick
+ retryTime
);
1061 DPRINTF(EthernetSM
, "transmit kick txState=%s (txFifo.size=%d)\n",
1062 TxStateStrings
[txState
], txFifo
.size());
1064 if (txKickTick
> curTick
) {
1065 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
1071 if (txState
== txIdle
)
1074 assert(!txList
.empty());
1075 vnic
= &virtualRegs
[txList
.front()];
1079 assert(Regs::get_TxDone_Busy(vnic
->TxData
));
1081 // Grab a new packet from the fifo.
1082 txPacket
= new PacketData(16384);
1086 if (txFifo
.avail() - txPacket
->length
<
1087 Regs::get_TxData_Len(vnic
->TxData
)) {
1088 DPRINTF(EthernetSM
, "transmit fifo full. Nothing to do.\n");
1092 txState
= txBeginCopy
;
1096 if (dmaInterface
&& dmaInterface
->busy())
1099 txDmaAddr
= plat
->pciToDma(Regs::get_TxData_Addr(vnic
->TxData
));
1100 txDmaLen
= Regs::get_TxData_Len(vnic
->TxData
);
1101 txDmaData
= txPacket
->data
+ txPacketOffset
;
1105 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
,
1106 curTick
, &txDmaEvent
, true);
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
);
1121 DPRINTF(EthernetSM
, "transmit machine still copying\n");
1125 vnic
->TxDone
= txDmaLen
| Regs::TxDone_Complete
;
1126 txPacket
->length
+= txDmaLen
;
1127 if ((vnic
->TxData
& Regs::TxData_More
)) {
1128 txPacketOffset
+= txDmaLen
;
1130 devIntrPost(Regs::Intr_TxDMA
);
1134 assert(txPacket
->length
<= txFifo
.avail());
1135 if ((vnic
->TxData
& Regs::TxData_Checksum
)) {
1141 tcp
->sum(cksum(tcp
));
1148 udp
->sum(cksum(udp
));
1158 txFifo
.push(txPacket
);
1159 if (txFifo
.avail() < regs
.TxMaxCopy
) {
1160 devIntrPost(Regs::Intr_TxFull
);
1166 txState
= txList
.empty() ? txIdle
: txFifoBlock
;
1167 devIntrPost(Regs::Intr_TxDMA
);
1171 panic("Invalid txState!");
1174 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1175 TxStateStrings
[txState
]);
1181 * @todo do we want to schedule a future kick?
1183 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1184 TxStateStrings
[txState
]);
1188 Device::transferDone()
1190 if (txFifo
.empty()) {
1191 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1195 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1197 if (txEvent
.scheduled())
1198 txEvent
.reschedule(curTick
+ cycles(1));
1200 txEvent
.schedule(curTick
+ cycles(1));
1204 Device::rxFilter(const PacketPtr
&packet
)
1206 if (!Regs::get_Config_Filter(regs
.Config
))
1209 panic("receive filter not implemented\n");
1215 EthHdr
*eth
= packet
->eth();
1216 if (eth
->unicast()) {
1217 // If we're accepting all unicast addresses
1221 // If we make a perfect match
1222 if (acceptPerfect
&& params
->eaddr
== eth
.dst())
1225 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
1228 } else if (eth
->broadcast()) {
1229 // if we're accepting broadcasts
1230 if (acceptBroadcast
)
1233 } else if (eth
->multicast()) {
1234 // if we're accepting all multicasts
1235 if (acceptMulticast
)
1241 DPRINTF(Ethernet
, "rxFilter drop\n");
1242 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1249 Device::recvPacket(PacketPtr packet
)
1251 rxBytes
+= packet
->length
;
1254 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifo Available is %d\n",
1258 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1262 if (rxFilter(packet
)) {
1263 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1267 if (rxFifo
.size() >= regs
.RxFifoMark
)
1268 devIntrPost(Regs::Intr_RxHigh
);
1270 if (!rxFifo
.push(packet
)) {
1272 "packet will not fit in receive buffer...packet dropped\n");
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())
1281 devIntrPost(Regs::Intr_RxPacket
);
1286 //=====================================================================
1290 Base::serialize(ostream
&os
)
1292 // Serialize the PciDev base class
1293 PciDev::serialize(os
);
1295 SERIALIZE_SCALAR(rxEnable
);
1296 SERIALIZE_SCALAR(txEnable
);
1297 SERIALIZE_SCALAR(cpuIntrEnable
);
1300 * Keep track of pending interrupt status.
1302 SERIALIZE_SCALAR(intrTick
);
1303 SERIALIZE_SCALAR(cpuPendingIntr
);
1304 Tick intrEventTick
= 0;
1306 intrEventTick
= intrEvent
->when();
1307 SERIALIZE_SCALAR(intrEventTick
);
1311 Base::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1313 // Unserialize the PciDev base class
1314 PciDev::unserialize(cp
, section
);
1316 UNSERIALIZE_SCALAR(rxEnable
);
1317 UNSERIALIZE_SCALAR(txEnable
);
1318 UNSERIALIZE_SCALAR(cpuIntrEnable
);
1321 * Keep track of pending interrupt status.
1323 UNSERIALIZE_SCALAR(intrTick
);
1324 UNSERIALIZE_SCALAR(cpuPendingIntr
);
1326 UNSERIALIZE_SCALAR(intrEventTick
);
1327 if (intrEventTick
) {
1328 intrEvent
= new IntrEvent(this, true);
1329 intrEvent
->schedule(intrEventTick
);
1334 Device::serialize(ostream
&os
)
1336 // Serialize the PciDev base class
1337 Base::serialize(os
);
1339 if (rxState
== rxCopy
)
1340 panic("can't serialize with an in flight dma request rxState=%s",
1341 RxStateStrings
[rxState
]);
1343 if (txState
== txCopy
)
1344 panic("can't serialize with an in flight dma request txState=%s",
1345 TxStateStrings
[txState
]);
1348 * Serialize the device registers
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
);
1362 * Serialize the virtual nic state
1364 int virtualRegsSize
= virtualRegs
.size();
1365 SERIALIZE_SCALAR(virtualRegsSize
);
1366 for (int i
= 0; i
< virtualRegsSize
; ++i
) {
1367 VirtualReg
*vnic
= &virtualRegs
[i
];
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
);
1375 PacketFifo::iterator rxFifoPtr
;
1377 bool rxPacketExists
= vnic
->rxPacket
!= rxFifo
.end();
1378 paramOut(os
, reg
+ ".rxPacketExists", rxPacketExists
);
1379 if (rxPacketExists
) {
1381 PacketFifo::iterator i
= rxFifo
.begin();
1382 while (i
!= vnic
->rxPacket
) {
1383 assert(i
!= rxFifo
.end());
1388 paramOut(os
, reg
+ ".rxPacket", rxPacket
);
1389 paramOut(os
, reg
+ ".rxPacketOffset", vnic
->rxPacketOffset
);
1390 paramOut(os
, reg
+ ".rxPacketBytes", vnic
->rxPacketBytes
);
1392 paramOut(os
, reg
+ ".rxDoneData", vnic
->rxDoneData
);
1395 VirtualList::iterator i
, end
;
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
);
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
);
1409 * Serialize rx state machine
1411 int rxState
= this->rxState
;
1412 SERIALIZE_SCALAR(rxState
);
1413 SERIALIZE_SCALAR(rxEmpty
);
1414 rxFifo
.serialize("rxFifo", os
);
1417 * Serialize tx state machine
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
);
1432 * If there's a pending transmit, store the time so we can
1433 * reschedule it later
1435 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
1436 SERIALIZE_SCALAR(transmitTick
);
1440 Device::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1442 // Unserialize the PciDev base class
1443 Base::unserialize(cp
, section
);
1446 * Unserialize the device registers
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
);
1460 UNSERIALIZE_SCALAR(rxListSize
);
1462 for (int i
= 0; i
< rxListSize
; ++i
) {
1464 paramIn(cp
, section
, csprintf("rxList%d", i
), value
);
1465 rxList
.push_back(value
);
1469 UNSERIALIZE_SCALAR(txListSize
);
1471 for (int i
= 0; i
< txListSize
; ++i
) {
1473 paramIn(cp
, section
, csprintf("txList%d", i
), value
);
1474 txList
.push_back(value
);
1478 * Unserialize rx state machine
1481 UNSERIALIZE_SCALAR(rxState
);
1482 UNSERIALIZE_SCALAR(rxEmpty
);
1483 this->rxState
= (RxState
) rxState
;
1484 rxFifo
.unserialize("rxFifo", cp
, section
);
1487 * Unserialize tx state machine
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
);
1497 if (txPacketExists
) {
1498 txPacket
= new PacketData(16384);
1499 txPacket
->unserialize("txPacket", cp
, section
);
1500 UNSERIALIZE_SCALAR(txPacketOffset
);
1501 UNSERIALIZE_SCALAR(txPacketBytes
);
1505 * unserialize the virtual nic registers/state
1507 * this must be done after the unserialization of the rxFifo
1508 * because the packet iterators depend on the fifo being populated
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
);
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
);
1523 bool rxPacketExists
;
1524 paramIn(cp
, section
, reg
+ ".rxPacketExists", rxPacketExists
);
1525 if (rxPacketExists
) {
1527 paramIn(cp
, section
, reg
+ ".rxPacket", rxPacket
);
1528 vnic
->rxPacket
= rxFifo
.begin();
1532 paramIn(cp
, section
, reg
+ ".rxPacketOffset",
1533 vnic
->rxPacketOffset
);
1534 paramIn(cp
, section
, reg
+ ".rxPacketBytes", vnic
->rxPacketBytes
);
1536 vnic
->rxPacket
= rxFifo
.end();
1538 paramIn(cp
, section
, reg
+ ".rxDoneData", vnic
->rxDoneData
);
1542 * If there's a pending transmit, reschedule it now
1545 UNSERIALIZE_SCALAR(transmitTick
);
1547 txEvent
.schedule(curTick
+ transmitTick
);
1550 * re-add addrRanges to bus bridges
1553 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
1554 pioInterface
->addAddrRange(RangeSize(BARAddrs
[1], BARSize
[1]));
1559 Device::cacheAccess(MemReqPtr
&req
)
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
);
1567 DPRINTF(EthernetPIO
, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
1568 req
->cmd
.toString(), req
->paddr
, bar
, daddr
);
1570 return curTick
+ pioLatency
;
1573 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1575 SimObjectParam
<EtherInt
*> peer
;
1576 SimObjectParam
<Device
*> device
;
1578 END_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1580 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface
)
1582 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1583 INIT_PARAM(device
, "Ethernet device of this interface")
1585 END_INIT_SIM_OBJECT_PARAMS(Interface
)
1587 CREATE_SIM_OBJECT(Interface
)
1589 Interface
*dev_int
= new Interface(getInstanceName(), device
);
1591 EtherInt
*p
= (EtherInt
*)peer
;
1593 dev_int
->setPeer(p
);
1594 p
->setPeer(dev_int
);
1600 REGISTER_SIM_OBJECT("SinicInt", Interface
)
1603 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device
)
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
;
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
;
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
;
1639 Param
<bool> rx_filter
;
1640 Param
<string
> hardware_address
;
1641 Param
<bool> rx_thread
;
1642 Param
<bool> tx_thread
;
1644 END_DECLARE_SIM_OBJECT_PARAMS(Device
)
1646 BEGIN_INIT_SIM_OBJECT_PARAMS(Device
)
1648 INIT_PARAM(clock
, "State machine cycle time"),
1650 INIT_PARAM(addr
, "Device Address"),
1651 INIT_PARAM(mmu
, "Memory Controller"),
1652 INIT_PARAM(physmem
, "Physical Memory"),
1653 INIT_PARAM(configspace
, "PCI Configspace"),
1654 INIT_PARAM(configdata
, "PCI Config data"),
1655 INIT_PARAM(platform
, "Platform"),
1656 INIT_PARAM(pci_bus
, "PCI bus"),
1657 INIT_PARAM(pci_dev
, "PCI device number"),
1658 INIT_PARAM(pci_func
, "PCI function code"),
1660 INIT_PARAM(hier
, "Hierarchy global variables"),
1661 INIT_PARAM(pio_bus
, ""),
1662 INIT_PARAM(dma_bus
, ""),
1663 INIT_PARAM(payload_bus
, "The IO Bus to attach to for payload"),
1664 INIT_PARAM(dma_read_delay
, "fixed delay for dma reads"),
1665 INIT_PARAM(dma_read_factor
, "multiplier for dma reads"),
1666 INIT_PARAM(dma_write_delay
, "fixed delay for dma writes"),
1667 INIT_PARAM(dma_write_factor
, "multiplier for dma writes"),
1668 INIT_PARAM(dma_no_allocate
, "Should we allocat on read in cache"),
1669 INIT_PARAM(pio_latency
, "Programmed IO latency in bus cycles"),
1670 INIT_PARAM(intr_delay
, "Interrupt Delay"),
1672 INIT_PARAM(rx_delay
, "Receive Delay"),
1673 INIT_PARAM(tx_delay
, "Transmit Delay"),
1674 INIT_PARAM(rx_max_copy
, "rx max copy"),
1675 INIT_PARAM(tx_max_copy
, "rx max copy"),
1676 INIT_PARAM(rx_max_intr
, "rx max intr"),
1677 INIT_PARAM(rx_fifo_size
, "max size in bytes of rxFifo"),
1678 INIT_PARAM(tx_fifo_size
, "max size in bytes of txFifo"),
1679 INIT_PARAM(rx_fifo_threshold
, "max size in bytes of rxFifo"),
1680 INIT_PARAM(tx_fifo_threshold
, "max size in bytes of txFifo"),
1682 INIT_PARAM(rx_filter
, "Enable Receive Filter"),
1683 INIT_PARAM(hardware_address
, "Ethernet Hardware Address"),
1684 INIT_PARAM(rx_thread
, ""),
1685 INIT_PARAM(tx_thread
, "")
1687 END_INIT_SIM_OBJECT_PARAMS(Device
)
1690 CREATE_SIM_OBJECT(Device
)
1692 Device::Params
*params
= new Device::Params
;
1694 params
->name
= getInstanceName();
1696 params
->clock
= clock
;
1699 params
->physmem
= physmem
;
1700 params
->configSpace
= configspace
;
1701 params
->configData
= configdata
;
1702 params
->plat
= platform
;
1703 params
->busNum
= pci_bus
;
1704 params
->deviceNum
= pci_dev
;
1705 params
->functionNum
= pci_func
;
1707 params
->hier
= hier
;
1708 params
->pio_bus
= pio_bus
;
1709 params
->header_bus
= dma_bus
;
1710 params
->payload_bus
= payload_bus
;
1711 params
->dma_read_delay
= dma_read_delay
;
1712 params
->dma_read_factor
= dma_read_factor
;
1713 params
->dma_write_delay
= dma_write_delay
;
1714 params
->dma_write_factor
= dma_write_factor
;
1715 params
->dma_no_allocate
= dma_no_allocate
;
1716 params
->pio_latency
= pio_latency
;
1717 params
->intr_delay
= intr_delay
;
1719 params
->tx_delay
= tx_delay
;
1720 params
->rx_delay
= rx_delay
;
1721 params
->rx_max_copy
= rx_max_copy
;
1722 params
->tx_max_copy
= tx_max_copy
;
1723 params
->rx_max_intr
= rx_max_intr
;
1724 params
->rx_fifo_size
= rx_fifo_size
;
1725 params
->tx_fifo_size
= tx_fifo_size
;
1726 params
->rx_fifo_threshold
= rx_fifo_threshold
;
1727 params
->tx_fifo_threshold
= tx_fifo_threshold
;
1729 params
->rx_filter
= rx_filter
;
1730 params
->eaddr
= hardware_address
;
1731 params
->rx_thread
= rx_thread
;
1732 params
->tx_thread
= tx_thread
;
1734 return new Device(params
);
1737 REGISTER_SIM_OBJECT("Sinic", Device
)
1739 /* namespace Sinic */ }