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.
28 * Authors: Nathan Binkert
35 #include "base/inet.hh"
36 #include "cpu/thread_context.hh"
37 #include "cpu/intr_control.hh"
38 #include "dev/etherlink.hh"
39 #include "dev/sinic.hh"
40 #include "mem/packet.hh"
41 #include "sim/builder.hh"
42 #include "sim/debug.hh"
43 #include "sim/eventq.hh"
44 #include "sim/host.hh"
45 #include "sim/stats.hh"
46 #include "arch/vtophys.hh"
49 using namespace TheISA
;
53 const char *RxStateStrings
[] =
62 const char *TxStateStrings
[] =
72 ///////////////////////////////////////////////////////////////////////
77 : PciDev(p
), rxEnable(false), txEnable(false), clock(p
->clock
),
78 intrDelay(p
->intr_delay
), intrTick(0), cpuIntrEnable(false),
79 cpuPendingIntr(false), intrEvent(0), interface(NULL
)
83 Device::Device(Params
*p
)
84 : Base(p
), rxUnique(0), txUnique(0),
85 virtualRegs(p
->virtual_count
< 1 ? 1 : p
->virtual_count
),
86 rxFifo(p
->rx_fifo_size
), txFifo(p
->tx_fifo_size
),
87 rxKickTick(0), txKickTick(0),
88 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
89 dmaReadDelay(p
->dma_read_delay
), dmaReadFactor(p
->dma_read_factor
),
90 dmaWriteDelay(p
->dma_write_delay
), dmaWriteFactor(p
->dma_write_factor
)
103 .name(name() + ".rxBytes")
104 .desc("Bytes Received")
109 .name(name() + ".rxBandwidth")
110 .desc("Receive Bandwidth (bits/s)")
116 .name(name() + ".rxPackets")
117 .desc("Number of Packets Received")
122 .name(name() + ".rxPPS")
123 .desc("Packet Reception Rate (packets/s)")
129 .name(name() + ".rxIpPackets")
130 .desc("Number of IP Packets Received")
135 .name(name() + ".rxTcpPackets")
136 .desc("Number of Packets Received")
141 .name(name() + ".rxUdpPackets")
142 .desc("Number of UDP Packets Received")
147 .name(name() + ".rxIpChecksums")
148 .desc("Number of rx IP Checksums done by device")
154 .name(name() + ".rxTcpChecksums")
155 .desc("Number of rx TCP Checksums done by device")
161 .name(name() + ".rxUdpChecksums")
162 .desc("Number of rx UDP Checksums done by device")
168 .name(name() + ".totBandwidth")
169 .desc("Total Bandwidth (bits/s)")
175 .name(name() + ".totPackets")
176 .desc("Total Packets")
182 .name(name() + ".totBytes")
189 .name(name() + ".totPPS")
190 .desc("Total Tranmission Rate (packets/s)")
196 .name(name() + ".txBytes")
197 .desc("Bytes Transmitted")
202 .name(name() + ".txBandwidth")
203 .desc("Transmit Bandwidth (bits/s)")
209 .name(name() + ".txPackets")
210 .desc("Number of Packets Transmitted")
215 .name(name() + ".txPPS")
216 .desc("Packet Tranmission Rate (packets/s)")
222 .name(name() + ".txIpPackets")
223 .desc("Number of IP Packets Transmitted")
228 .name(name() + ".txTcpPackets")
229 .desc("Number of TCP Packets Transmitted")
234 .name(name() + ".txUdpPackets")
235 .desc("Number of Packets Transmitted")
240 .name(name() + ".txIpChecksums")
241 .desc("Number of tx IP Checksums done by device")
247 .name(name() + ".txTcpChecksums")
248 .desc("Number of tx TCP Checksums done by device")
254 .name(name() + ".txUdpChecksums")
255 .desc("Number of tx UDP Checksums done by device")
260 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
261 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
262 totBandwidth
= txBandwidth
+ rxBandwidth
;
263 totBytes
= txBytes
+ rxBytes
;
264 totPackets
= txPackets
+ rxPackets
;
265 txPacketRate
= txPackets
/ simSeconds
;
266 rxPacketRate
= rxPackets
/ simSeconds
;
270 Device::prepareIO(int cpu
, int index
)
272 int size
= virtualRegs
.size();
274 panic("Trying to access a vnic that doesn't exist %d > %d\n",
279 Device::prepareRead(int cpu
, int index
)
281 using namespace Regs
;
282 prepareIO(cpu
, index
);
284 VirtualReg
&vnic
= virtualRegs
[index
];
286 // update rx registers
287 uint64_t rxdone
= vnic
.RxDone
;
288 rxdone
= set_RxDone_Packets(rxdone
, rxFifo
.countPacketsAfter(rxFifoPtr
));
289 rxdone
= set_RxDone_Empty(rxdone
, rxFifo
.empty());
290 rxdone
= set_RxDone_High(rxdone
, rxFifo
.size() > regs
.RxFifoMark
);
291 rxdone
= set_RxDone_NotHigh(rxdone
, rxLow
);
292 regs
.RxData
= vnic
.RxData
;
293 regs
.RxDone
= rxdone
;
294 regs
.RxWait
= rxdone
;
296 // update tx regsiters
297 uint64_t txdone
= vnic
.TxDone
;
298 txdone
= set_TxDone_Packets(txdone
, txFifo
.packets());
299 txdone
= set_TxDone_Full(txdone
, txFifo
.avail() < regs
.TxMaxCopy
);
300 txdone
= set_TxDone_Low(txdone
, txFifo
.size() < regs
.TxFifoMark
);
301 regs
.TxData
= vnic
.TxData
;
302 regs
.TxDone
= txdone
;
303 regs
.TxWait
= txdone
;
307 Device::prepareWrite(int cpu
, int index
)
309 prepareIO(cpu
, index
);
313 * I/O read of device register
316 Device::read(Packet
*pkt
)
318 assert(config
.command
& PCI_CMD_MSE
);
319 assert(pkt
->getAddr() >= BARAddrs
[0] && pkt
->getSize() < BARSize
[0]);
321 int cpu
= pkt
->req
->getCpuNum();
322 Addr daddr
= pkt
->getAddr() - BARAddrs
[0];
323 Addr index
= daddr
>> Regs::VirtualShift
;
324 Addr raddr
= daddr
& Regs::VirtualMask
;
328 if (!regValid(raddr
))
329 panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
330 cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize());
332 const Regs::Info
&info
= regInfo(raddr
);
334 panic("read %s (write only): "
335 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
336 info
.name
, cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize());
338 panic("read %s (invalid size): "
339 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
340 info
.name
, cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize());
342 prepareRead(cpu
, index
);
345 if (pkt
->getSize() == 4) {
346 uint32_t reg
= regData32(raddr
);
351 if (pkt
->getSize() == 8) {
352 uint64_t reg
= regData64(raddr
);
358 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
359 info
.name
, cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize(), value
);
361 // reading the interrupt status register has the side effect of
363 if (raddr
== Regs::IntrStatus
)
370 * IPR read of device register
373 Device::iprRead(Addr daddr, int cpu, uint64_t &result)
375 if (!regValid(daddr))
376 panic("invalid address: da=%#x", daddr);
378 const Regs::Info &info = regInfo(daddr);
380 panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr);
382 DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",
383 info.name, cpu, daddr);
388 result = regData32(daddr);
391 result = regData64(daddr);
393 DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
394 info.name, cpu, result);
400 * I/O write of device register
403 Device::write(Packet
*pkt
)
405 assert(config
.command
& PCI_CMD_MSE
);
406 assert(pkt
->getAddr() >= BARAddrs
[0] && pkt
->getSize() < BARSize
[0]);
408 int cpu
= pkt
->req
->getCpuNum();
409 Addr daddr
= pkt
->getAddr() - BARAddrs
[0];
410 Addr index
= daddr
>> Regs::VirtualShift
;
411 Addr raddr
= daddr
& Regs::VirtualMask
;
413 if (!regValid(raddr
))
414 panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
415 cpu
, daddr
, pkt
->getAddr(), pkt
->getSize());
417 const Regs::Info
&info
= regInfo(raddr
);
419 panic("write %s (read only): "
420 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
421 info
.name
, cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize());
423 if (pkt
->getSize() != info
.size
)
424 panic("write %s (invalid size): "
425 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
426 info
.name
, cpu
, index
, daddr
, pkt
->getAddr(), pkt
->getSize());
428 VirtualReg
&vnic
= virtualRegs
[index
];
431 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
432 info
.name
, index
, cpu
, info
.size
== 4 ? pkt
->get
<uint32_t>() :
433 pkt
->get
<uint64_t>(), daddr
, pkt
->getAddr(), pkt
->getSize());
435 prepareWrite(cpu
, index
);
439 changeConfig(pkt
->get
<uint32_t>());
443 command(pkt
->get
<uint32_t>());
446 case Regs::IntrStatus
:
447 devIntrClear(regs
.IntrStatus
& pkt
->get
<uint32_t>());
451 devIntrChangeMask(pkt
->get
<uint32_t>());
455 if (Regs::get_RxDone_Busy(vnic
.RxDone
))
456 panic("receive machine busy with another request! rxState=%s",
457 RxStateStrings
[rxState
]);
459 vnic
.rxUnique
= rxUnique
++;
460 vnic
.RxDone
= Regs::RxDone_Busy
;
461 vnic
.RxData
= pkt
->get
<uint64_t>();
463 if (Regs::get_RxData_Vaddr(pkt
->get
<uint64_t>())) {
464 panic("vtophys not implemented in newmem");
465 /* Addr vaddr = Regs::get_RxData_Addr(reg64);
466 Addr paddr = vtophys(req->xc, vaddr);
467 DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "
468 "vaddr=%#x, paddr=%#x\n",
469 index, vnic.rxUnique, vaddr, paddr);
471 vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/
473 DPRINTF(EthernetPIO
, "write RxData vnic %d (rxunique %d)\n",
474 index
, vnic
.rxUnique
);
477 if (vnic
.rxPacket
== rxFifo
.end()) {
478 DPRINTF(EthernetPIO
, "request new packet...appending to rxList\n");
479 rxList
.push_back(index
);
481 DPRINTF(EthernetPIO
, "packet exists...appending to rxBusy\n");
482 rxBusy
.push_back(index
);
485 if (rxEnable
&& (rxState
== rxIdle
|| rxState
== rxFifoBlock
)) {
486 rxState
= rxFifoBlock
;
492 if (Regs::get_TxDone_Busy(vnic
.TxDone
))
493 panic("transmit machine busy with another request! txState=%s",
494 TxStateStrings
[txState
]);
496 vnic
.txUnique
= txUnique
++;
497 vnic
.TxDone
= Regs::TxDone_Busy
;
499 if (Regs::get_TxData_Vaddr(pkt
->get
<uint64_t>())) {
500 panic("vtophys won't work here in newmem.\n");
501 /*Addr vaddr = Regs::get_TxData_Addr(reg64);
502 Addr paddr = vtophys(req->xc, vaddr);
503 DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "
504 "vaddr=%#x, paddr=%#x\n",
505 index, vnic.txUnique, vaddr, paddr);
507 vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/
509 DPRINTF(EthernetPIO
, "write TxData vnic %d (rxunique %d)\n",
510 index
, vnic
.txUnique
);
513 if (txList
.empty() || txList
.front() != index
)
514 txList
.push_back(index
);
515 if (txEnable
&& txState
== txIdle
&& txList
.front() == index
) {
516 txState
= txFifoBlock
;
526 Device::devIntrPost(uint32_t interrupts
)
528 if ((interrupts
& Regs::Intr_Res
))
529 panic("Cannot set a reserved interrupt");
531 regs
.IntrStatus
|= interrupts
;
533 DPRINTF(EthernetIntr
,
534 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
535 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
537 interrupts
= regs
.IntrStatus
& regs
.IntrMask
;
539 // Intr_RxHigh is special, we only signal it if we've emptied the fifo
540 // and then filled it above the high watermark
544 interrupts
&= ~Regs::Intr_RxHigh
;
546 // Intr_TxLow is special, we only signal it if we've filled up the fifo
547 // and then dropped below the low watermark
551 interrupts
&= ~Regs::Intr_TxLow
;
555 if ((interrupts
& Regs::Intr_NoDelay
) == 0)
562 Device::devIntrClear(uint32_t interrupts
)
564 if ((interrupts
& Regs::Intr_Res
))
565 panic("Cannot clear a reserved interrupt");
567 regs
.IntrStatus
&= ~interrupts
;
569 DPRINTF(EthernetIntr
,
570 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
571 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
573 if (!(regs
.IntrStatus
& regs
.IntrMask
))
578 Device::devIntrChangeMask(uint32_t newmask
)
580 if (regs
.IntrMask
== newmask
)
583 regs
.IntrMask
= newmask
;
585 DPRINTF(EthernetIntr
,
586 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
587 regs
.IntrStatus
, regs
.IntrMask
, regs
.IntrStatus
& regs
.IntrMask
);
589 if (regs
.IntrStatus
& regs
.IntrMask
)
590 cpuIntrPost(curTick
);
596 Base::cpuIntrPost(Tick when
)
598 // If the interrupt you want to post is later than an interrupt
599 // already scheduled, just let it post in the coming one and don't
601 // HOWEVER, must be sure that the scheduled intrTick is in the
602 // future (this was formerly the source of a bug)
604 * @todo this warning should be removed and the intrTick code should
607 assert(when
>= curTick
);
608 assert(intrTick
>= curTick
|| intrTick
== 0);
609 if (!cpuIntrEnable
) {
610 DPRINTF(EthernetIntr
, "interrupts not enabled.\n",
615 if (when
> intrTick
&& intrTick
!= 0) {
616 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
622 if (intrTick
< curTick
) {
627 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
632 intrEvent
= new IntrEvent(this, true);
633 intrEvent
->schedule(intrTick
);
639 assert(intrTick
== curTick
);
641 // Whether or not there's a pending interrupt, we don't care about
646 // Don't send an interrupt if there's already one
647 if (cpuPendingIntr
) {
648 DPRINTF(EthernetIntr
,
649 "would send an interrupt now, but there's already pending\n");
652 cpuPendingIntr
= true;
654 DPRINTF(EthernetIntr
, "posting interrupt\n");
672 cpuPendingIntr
= false;
674 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
679 Base::cpuIntrPending() const
680 { return cpuPendingIntr
; }
683 Device::changeConfig(uint32_t newconf
)
685 uint32_t changed
= regs
.Config
^ newconf
;
689 regs
.Config
= newconf
;
691 if ((changed
& Regs::Config_IntEn
)) {
692 cpuIntrEnable
= regs
.Config
& Regs::Config_IntEn
;
694 if (regs
.IntrStatus
& regs
.IntrMask
)
695 cpuIntrPost(curTick
);
701 if ((changed
& Regs::Config_TxEn
)) {
702 txEnable
= regs
.Config
& Regs::Config_TxEn
;
707 if ((changed
& Regs::Config_RxEn
)) {
708 rxEnable
= regs
.Config
& Regs::Config_RxEn
;
715 Device::command(uint32_t command
)
717 if (command
& Regs::Command_Intr
)
718 devIntrPost(Regs::Intr_Soft
);
720 if (command
& Regs::Command_Reset
)
727 using namespace Regs
;
729 memset(®s
, 0, sizeof(regs
));
732 if (params()->rx_thread
)
733 regs
.Config
|= Config_RxThread
;
734 if (params()->tx_thread
)
735 regs
.Config
|= Config_TxThread
;
737 regs
.Config
|= Config_RSS
;
738 if (params()->zero_copy
)
739 regs
.Config
|= Config_ZeroCopy
;
740 if (params()->delay_copy
)
741 regs
.Config
|= Config_DelayCopy
;
742 if (params()->virtual_addr
)
743 regs
.Config
|= Config_Vaddr
;
745 if (params()->delay_copy
&& params()->zero_copy
)
746 panic("Can't delay copy and zero copy");
748 regs
.IntrMask
= Intr_Soft
| Intr_RxHigh
| Intr_RxPacket
| Intr_TxLow
;
749 regs
.RxMaxCopy
= params()->rx_max_copy
;
750 regs
.TxMaxCopy
= params()->tx_max_copy
;
751 regs
.RxMaxIntr
= params()->rx_max_intr
;
752 regs
.VirtualCount
= params()->virtual_count
;
753 regs
.RxFifoSize
= params()->rx_fifo_size
;
754 regs
.TxFifoSize
= params()->tx_fifo_size
;
755 regs
.RxFifoMark
= params()->rx_fifo_threshold
;
756 regs
.TxFifoMark
= params()->tx_fifo_threshold
;
757 regs
.HwAddr
= params()->eaddr
;
768 rxFifoPtr
= rxFifo
.end();
774 int size
= virtualRegs
.size();
776 virtualRegs
.resize(size
);
777 for (int i
= 0; i
< size
; ++i
)
778 virtualRegs
[i
].rxPacket
= rxFifo
.end();
784 assert(rxState
== rxCopy
);
785 rxState
= rxCopyDone
;
786 DPRINTF(EthernetDMA
, "end rx dma write paddr=%#x len=%d\n",
787 rxDmaAddr
, rxDmaLen
);
788 DDUMP(EthernetData
, rxDmaData
, rxDmaLen
);
790 // If the transmit state machine has a pending DMA, let it go first
791 if (txState
== txBeginCopy
)
800 VirtualReg
*vnic
= NULL
;
802 DPRINTF(EthernetSM
, "rxKick: rxState=%s (rxFifo.size=%d)\n",
803 RxStateStrings
[rxState
], rxFifo
.size());
805 if (rxKickTick
> curTick
) {
806 DPRINTF(EthernetSM
, "rxKick: exiting, can't run till %d\n",
812 if (rxState
== rxIdle
)
815 if (rxActive
== -1) {
816 if (rxState
!= rxFifoBlock
)
817 panic("no active vnic while in state %s", RxStateStrings
[rxState
]);
819 DPRINTF(EthernetSM
, "processing rxState=%s\n",
820 RxStateStrings
[rxState
]);
822 vnic
= &virtualRegs
[rxActive
];
824 "processing rxState=%s for vnic %d (rxunique %d)\n",
825 RxStateStrings
[rxState
], rxActive
, vnic
->rxUnique
);
830 if (DTRACE(EthernetSM
)) {
831 PacketFifo::iterator end
= rxFifo
.end();
832 int size
= virtualRegs
.size();
833 for (int i
= 0; i
< size
; ++i
) {
834 VirtualReg
*vn
= &virtualRegs
[i
];
835 if (vn
->rxPacket
!= end
&&
836 !Regs::get_RxDone_Busy(vn
->RxDone
)) {
838 "vnic %d (rxunique %d), has outstanding packet %d\n",
840 rxFifo
.countPacketsBefore(vn
->rxPacket
));
845 if (!rxBusy
.empty()) {
846 rxActive
= rxBusy
.front();
848 vnic
= &virtualRegs
[rxActive
];
850 if (vnic
->rxPacket
== rxFifo
.end())
851 panic("continuing vnic without packet\n");
854 "continue processing for vnic %d (rxunique %d)\n",
855 rxActive
, vnic
->rxUnique
);
857 rxState
= rxBeginCopy
;
862 if (rxFifoPtr
== rxFifo
.end()) {
863 DPRINTF(EthernetSM
, "receive waiting for data. Nothing to do.\n");
868 panic("Not idle, but nothing to do!");
870 assert(!rxFifo
.empty());
872 rxActive
= rxList
.front();
874 vnic
= &virtualRegs
[rxActive
];
877 "processing new packet for vnic %d (rxunique %d)\n",
878 rxActive
, vnic
->rxUnique
);
880 // Grab a new packet from the fifo.
881 vnic
->rxPacket
= rxFifoPtr
++;
882 vnic
->rxPacketOffset
= 0;
883 vnic
->rxPacketBytes
= (*vnic
->rxPacket
)->length
;
884 assert(vnic
->rxPacketBytes
);
886 vnic
->rxDoneData
= 0;
887 /* scope for variables */ {
888 IpPtr
ip(*vnic
->rxPacket
);
890 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
891 vnic
->rxDoneData
|= Regs::RxDone_IpPacket
;
893 if (cksum(ip
) != 0) {
894 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
895 vnic
->rxDoneData
|= Regs::RxDone_IpError
;
901 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
902 tcp
->sport(), tcp
->dport(), tcp
->seq(),
904 vnic
->rxDoneData
|= Regs::RxDone_TcpPacket
;
906 if (cksum(tcp
) != 0) {
907 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
908 vnic
->rxDoneData
|= Regs::RxDone_TcpError
;
911 vnic
->rxDoneData
|= Regs::RxDone_UdpPacket
;
913 if (cksum(udp
) != 0) {
914 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
915 vnic
->rxDoneData
|= Regs::RxDone_UdpError
;
920 rxState
= rxBeginCopy
;
924 if (dmaPending() || getState() != Running
)
927 rxDmaAddr
= params()->platform
->pciToDma(
928 Regs::get_RxData_Addr(vnic
->RxData
));
929 rxDmaLen
= std::min
<int>(Regs::get_RxData_Len(vnic
->RxData
),
930 vnic
->rxPacketBytes
);
931 rxDmaData
= (*vnic
->rxPacket
)->data
+ vnic
->rxPacketOffset
;
933 if (rxDmaAddr
== 1LL) {
934 rxState
= rxCopyDone
;
939 dmaWrite(rxDmaAddr
, rxDmaLen
, &rxDmaEvent
, rxDmaData
);
943 DPRINTF(EthernetSM
, "receive machine still copying\n");
947 vnic
->RxDone
= vnic
->rxDoneData
;
948 vnic
->RxDone
|= Regs::RxDone_Complete
;
950 if (vnic
->rxPacketBytes
== rxDmaLen
) {
951 // Packet is complete. Indicate how many bytes were copied
952 vnic
->RxDone
= Regs::set_RxDone_CopyLen(vnic
->RxDone
, rxDmaLen
);
955 "rxKick: packet complete on vnic %d (rxunique %d)\n",
956 rxActive
, vnic
->rxUnique
);
957 rxFifo
.remove(vnic
->rxPacket
);
958 vnic
->rxPacket
= rxFifo
.end();
960 vnic
->rxPacketBytes
-= rxDmaLen
;
961 vnic
->rxPacketOffset
+= rxDmaLen
;
962 vnic
->RxDone
|= Regs::RxDone_More
;
963 vnic
->RxDone
= Regs::set_RxDone_CopyLen(vnic
->RxDone
,
964 vnic
->rxPacketBytes
);
966 "rxKick: packet not complete on vnic %d (rxunique %d): "
968 rxActive
, vnic
->rxUnique
, vnic
->rxPacketBytes
);
972 rxState
= rxBusy
.empty() && rxList
.empty() ? rxIdle
: rxFifoBlock
;
974 if (rxFifo
.empty()) {
975 devIntrPost(Regs::Intr_RxEmpty
);
979 if (rxFifo
.size() < params()->rx_fifo_low_mark
)
982 if (rxFifo
.size() > params()->rx_fifo_threshold
)
985 devIntrPost(Regs::Intr_RxDMA
);
989 panic("Invalid rxState!");
992 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
993 RxStateStrings
[rxState
]);
999 * @todo do we want to schedule a future kick?
1001 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
1002 RxStateStrings
[rxState
]);
1008 assert(txState
== txCopy
);
1009 txState
= txCopyDone
;
1010 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1011 txDmaAddr
, txDmaLen
);
1012 DDUMP(EthernetData
, txDmaData
, txDmaLen
);
1014 // If the receive state machine has a pending DMA, let it go first
1015 if (rxState
== rxBeginCopy
)
1024 if (txFifo
.empty()) {
1025 DPRINTF(Ethernet
, "nothing to transmit\n");
1029 uint32_t interrupts
;
1030 EthPacketPtr packet
= txFifo
.front();
1031 if (!interface
->sendPacket(packet
)) {
1032 DPRINTF(Ethernet
, "Packet Transmit: failed txFifo available %d\n",
1039 if (DTRACE(Ethernet
)) {
1042 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
1046 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1047 tcp
->sport(), tcp
->dport(), tcp
->seq(),
1054 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1055 txBytes
+= packet
->length
;
1058 DPRINTF(Ethernet
, "Packet Transmit: successful txFifo Available %d\n",
1061 interrupts
= Regs::Intr_TxPacket
;
1062 if (txFifo
.size() < regs
.TxFifoMark
)
1063 interrupts
|= Regs::Intr_TxLow
;
1064 devIntrPost(interrupts
);
1067 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1068 DPRINTF(Ethernet
, "reschedule transmit\n");
1069 txEvent
.schedule(curTick
+ retryTime
);
1077 DPRINTF(EthernetSM
, "txKick: txState=%s (txFifo.size=%d)\n",
1078 TxStateStrings
[txState
], txFifo
.size());
1080 if (txKickTick
> curTick
) {
1081 DPRINTF(EthernetSM
, "txKick: exiting, can't run till %d\n",
1087 if (txState
== txIdle
)
1090 assert(!txList
.empty());
1091 vnic
= &virtualRegs
[txList
.front()];
1095 assert(Regs::get_TxDone_Busy(vnic
->TxDone
));
1097 // Grab a new packet from the fifo.
1098 txPacket
= new EthPacketData(16384);
1102 if (txFifo
.avail() - txPacket
->length
<
1103 Regs::get_TxData_Len(vnic
->TxData
)) {
1104 DPRINTF(EthernetSM
, "transmit fifo full. Nothing to do.\n");
1108 txState
= txBeginCopy
;
1112 if (dmaPending() || getState() != Running
)
1115 txDmaAddr
= params()->platform
->pciToDma(
1116 Regs::get_TxData_Addr(vnic
->TxData
));
1117 txDmaLen
= Regs::get_TxData_Len(vnic
->TxData
);
1118 txDmaData
= txPacket
->data
+ txPacketOffset
;
1121 dmaRead(txDmaAddr
, txDmaLen
, &txDmaEvent
, txDmaData
);
1125 DPRINTF(EthernetSM
, "transmit machine still copying\n");
1129 vnic
->TxDone
= txDmaLen
| Regs::TxDone_Complete
;
1130 txPacket
->length
+= txDmaLen
;
1131 if ((vnic
->TxData
& Regs::TxData_More
)) {
1132 txPacketOffset
+= txDmaLen
;
1134 devIntrPost(Regs::Intr_TxDMA
);
1138 assert(txPacket
->length
<= txFifo
.avail());
1139 if ((vnic
->TxData
& Regs::TxData_Checksum
)) {
1145 tcp
->sum(cksum(tcp
));
1152 udp
->sum(cksum(udp
));
1162 txFifo
.push(txPacket
);
1163 if (txFifo
.avail() < regs
.TxMaxCopy
) {
1164 devIntrPost(Regs::Intr_TxFull
);
1170 txState
= txList
.empty() ? txIdle
: txFifoBlock
;
1171 devIntrPost(Regs::Intr_TxDMA
);
1175 panic("Invalid txState!");
1178 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1179 TxStateStrings
[txState
]);
1185 * @todo do we want to schedule a future kick?
1187 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1188 TxStateStrings
[txState
]);
1192 Device::transferDone()
1194 if (txFifo
.empty()) {
1195 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1199 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1201 if (txEvent
.scheduled())
1202 txEvent
.reschedule(curTick
+ cycles(1));
1204 txEvent
.schedule(curTick
+ cycles(1));
1208 Device::rxFilter(const EthPacketPtr
&packet
)
1210 if (!Regs::get_Config_Filter(regs
.Config
))
1213 panic("receive filter not implemented\n");
1219 EthHdr
*eth
= packet
->eth();
1220 if (eth
->unicast()) {
1221 // If we're accepting all unicast addresses
1225 // If we make a perfect match
1226 if (acceptPerfect
&& params
->eaddr
== eth
.dst())
1229 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
1232 } else if (eth
->broadcast()) {
1233 // if we're accepting broadcasts
1234 if (acceptBroadcast
)
1237 } else if (eth
->multicast()) {
1238 // if we're accepting all multicasts
1239 if (acceptMulticast
)
1245 DPRINTF(Ethernet
, "rxFilter drop\n");
1246 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1253 Device::recvPacket(EthPacketPtr packet
)
1255 rxBytes
+= packet
->length
;
1258 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifo Available is %d\n",
1262 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1266 if (rxFilter(packet
)) {
1267 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1271 if (rxFifo
.size() >= regs
.RxFifoMark
)
1272 devIntrPost(Regs::Intr_RxHigh
);
1274 if (!rxFifo
.push(packet
)) {
1276 "packet will not fit in receive buffer...packet dropped\n");
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())
1285 devIntrPost(Regs::Intr_RxPacket
);
1293 SimObject::resume();
1295 // During drain we could have left the state machines in a waiting state and
1296 // they wouldn't get out until some other event occured to kick them.
1297 // This way they'll get out immediately
1302 //=====================================================================
1306 Base::serialize(std::ostream
&os
)
1308 // Serialize the PciDev base class
1309 PciDev::serialize(os
);
1311 SERIALIZE_SCALAR(rxEnable
);
1312 SERIALIZE_SCALAR(txEnable
);
1313 SERIALIZE_SCALAR(cpuIntrEnable
);
1316 * Keep track of pending interrupt status.
1318 SERIALIZE_SCALAR(intrTick
);
1319 SERIALIZE_SCALAR(cpuPendingIntr
);
1320 Tick intrEventTick
= 0;
1322 intrEventTick
= intrEvent
->when();
1323 SERIALIZE_SCALAR(intrEventTick
);
1327 Base::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1329 // Unserialize the PciDev base class
1330 PciDev::unserialize(cp
, section
);
1332 UNSERIALIZE_SCALAR(rxEnable
);
1333 UNSERIALIZE_SCALAR(txEnable
);
1334 UNSERIALIZE_SCALAR(cpuIntrEnable
);
1337 * Keep track of pending interrupt status.
1339 UNSERIALIZE_SCALAR(intrTick
);
1340 UNSERIALIZE_SCALAR(cpuPendingIntr
);
1342 UNSERIALIZE_SCALAR(intrEventTick
);
1343 if (intrEventTick
) {
1344 intrEvent
= new IntrEvent(this, true);
1345 intrEvent
->schedule(intrEventTick
);
1350 Device::serialize(std::ostream
&os
)
1354 // Serialize the PciDev base class
1355 Base::serialize(os
);
1357 if (rxState
== rxCopy
)
1358 panic("can't serialize with an in flight dma request rxState=%s",
1359 RxStateStrings
[rxState
]);
1361 if (txState
== txCopy
)
1362 panic("can't serialize with an in flight dma request txState=%s",
1363 TxStateStrings
[txState
]);
1366 * Serialize the device registers
1368 SERIALIZE_SCALAR(regs
.Config
);
1369 SERIALIZE_SCALAR(regs
.IntrStatus
);
1370 SERIALIZE_SCALAR(regs
.IntrMask
);
1371 SERIALIZE_SCALAR(regs
.RxMaxCopy
);
1372 SERIALIZE_SCALAR(regs
.TxMaxCopy
);
1373 SERIALIZE_SCALAR(regs
.RxMaxIntr
);
1374 SERIALIZE_SCALAR(regs
.VirtualCount
);
1375 SERIALIZE_SCALAR(regs
.RxData
);
1376 SERIALIZE_SCALAR(regs
.RxDone
);
1377 SERIALIZE_SCALAR(regs
.TxData
);
1378 SERIALIZE_SCALAR(regs
.TxDone
);
1381 * Serialize the virtual nic state
1383 int virtualRegsSize
= virtualRegs
.size();
1384 SERIALIZE_SCALAR(virtualRegsSize
);
1385 for (int i
= 0; i
< virtualRegsSize
; ++i
) {
1386 VirtualReg
*vnic
= &virtualRegs
[i
];
1388 std::string reg
= csprintf("vnic%d", i
);
1389 paramOut(os
, reg
+ ".RxData", vnic
->RxData
);
1390 paramOut(os
, reg
+ ".RxDone", vnic
->RxDone
);
1391 paramOut(os
, reg
+ ".TxData", vnic
->TxData
);
1392 paramOut(os
, reg
+ ".TxDone", vnic
->TxDone
);
1394 bool rxPacketExists
= vnic
->rxPacket
!= rxFifo
.end();
1395 paramOut(os
, reg
+ ".rxPacketExists", rxPacketExists
);
1396 if (rxPacketExists
) {
1398 PacketFifo::iterator i
= rxFifo
.begin();
1399 while (i
!= vnic
->rxPacket
) {
1400 assert(i
!= rxFifo
.end());
1405 paramOut(os
, reg
+ ".rxPacket", rxPacket
);
1406 paramOut(os
, reg
+ ".rxPacketOffset", vnic
->rxPacketOffset
);
1407 paramOut(os
, reg
+ ".rxPacketBytes", vnic
->rxPacketBytes
);
1409 paramOut(os
, reg
+ ".rxDoneData", vnic
->rxDoneData
);
1412 int rxFifoPtr
= rxFifo
.countPacketsBefore(this->rxFifoPtr
);
1413 SERIALIZE_SCALAR(rxFifoPtr
);
1415 SERIALIZE_SCALAR(rxActive
);
1417 VirtualList::iterator i
, end
;
1418 for (count
= 0, i
= rxList
.begin(), end
= rxList
.end(); i
!= end
; ++i
)
1419 paramOut(os
, csprintf("rxList%d", count
++), *i
);
1420 int rxListSize
= count
;
1421 SERIALIZE_SCALAR(rxListSize
);
1423 for (count
= 0, i
= rxBusy
.begin(), end
= rxBusy
.end(); i
!= end
; ++i
)
1424 paramOut(os
, csprintf("rxBusy%d", count
++), *i
);
1425 int rxBusySize
= count
;
1426 SERIALIZE_SCALAR(rxBusySize
);
1428 for (count
= 0, i
= txList
.begin(), end
= txList
.end(); i
!= end
; ++i
)
1429 paramOut(os
, csprintf("txList%d", count
++), *i
);
1430 int txListSize
= count
;
1431 SERIALIZE_SCALAR(txListSize
);
1434 * Serialize rx state machine
1436 int rxState
= this->rxState
;
1437 SERIALIZE_SCALAR(rxState
);
1438 SERIALIZE_SCALAR(rxEmpty
);
1439 SERIALIZE_SCALAR(rxLow
);
1440 rxFifo
.serialize("rxFifo", os
);
1443 * Serialize tx state machine
1445 int txState
= this->txState
;
1446 SERIALIZE_SCALAR(txState
);
1447 SERIALIZE_SCALAR(txFull
);
1448 txFifo
.serialize("txFifo", os
);
1449 bool txPacketExists
= txPacket
;
1450 SERIALIZE_SCALAR(txPacketExists
);
1451 if (txPacketExists
) {
1452 txPacket
->serialize("txPacket", os
);
1453 SERIALIZE_SCALAR(txPacketOffset
);
1454 SERIALIZE_SCALAR(txPacketBytes
);
1458 * If there's a pending transmit, store the time so we can
1459 * reschedule it later
1461 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
1462 SERIALIZE_SCALAR(transmitTick
);
1466 Device::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1468 // Unserialize the PciDev base class
1469 Base::unserialize(cp
, section
);
1472 * Unserialize the device registers
1474 UNSERIALIZE_SCALAR(regs
.Config
);
1475 UNSERIALIZE_SCALAR(regs
.IntrStatus
);
1476 UNSERIALIZE_SCALAR(regs
.IntrMask
);
1477 UNSERIALIZE_SCALAR(regs
.RxMaxCopy
);
1478 UNSERIALIZE_SCALAR(regs
.TxMaxCopy
);
1479 UNSERIALIZE_SCALAR(regs
.RxMaxIntr
);
1480 UNSERIALIZE_SCALAR(regs
.VirtualCount
);
1481 UNSERIALIZE_SCALAR(regs
.RxData
);
1482 UNSERIALIZE_SCALAR(regs
.RxDone
);
1483 UNSERIALIZE_SCALAR(regs
.TxData
);
1484 UNSERIALIZE_SCALAR(regs
.TxDone
);
1486 UNSERIALIZE_SCALAR(rxActive
);
1489 UNSERIALIZE_SCALAR(rxListSize
);
1491 for (int i
= 0; i
< rxListSize
; ++i
) {
1493 paramIn(cp
, section
, csprintf("rxList%d", i
), value
);
1494 rxList
.push_back(value
);
1498 UNSERIALIZE_SCALAR(rxBusySize
);
1500 for (int i
= 0; i
< rxBusySize
; ++i
) {
1502 paramIn(cp
, section
, csprintf("rxBusy%d", i
), value
);
1503 rxBusy
.push_back(value
);
1507 UNSERIALIZE_SCALAR(txListSize
);
1509 for (int i
= 0; i
< txListSize
; ++i
) {
1511 paramIn(cp
, section
, csprintf("txList%d", i
), value
);
1512 txList
.push_back(value
);
1516 * Unserialize rx state machine
1519 UNSERIALIZE_SCALAR(rxState
);
1520 UNSERIALIZE_SCALAR(rxEmpty
);
1521 UNSERIALIZE_SCALAR(rxLow
);
1522 this->rxState
= (RxState
) rxState
;
1523 rxFifo
.unserialize("rxFifo", cp
, section
);
1526 UNSERIALIZE_SCALAR(rxFifoPtr
);
1527 this->rxFifoPtr
= rxFifo
.begin();
1528 for (int i
= 0; i
< rxFifoPtr
; ++i
)
1532 * Unserialize tx state machine
1535 UNSERIALIZE_SCALAR(txState
);
1536 UNSERIALIZE_SCALAR(txFull
);
1537 this->txState
= (TxState
) txState
;
1538 txFifo
.unserialize("txFifo", cp
, section
);
1539 bool txPacketExists
;
1540 UNSERIALIZE_SCALAR(txPacketExists
);
1542 if (txPacketExists
) {
1543 txPacket
= new EthPacketData(16384);
1544 txPacket
->unserialize("txPacket", cp
, section
);
1545 UNSERIALIZE_SCALAR(txPacketOffset
);
1546 UNSERIALIZE_SCALAR(txPacketBytes
);
1550 * unserialize the virtual nic registers/state
1552 * this must be done after the unserialization of the rxFifo
1553 * because the packet iterators depend on the fifo being populated
1555 int virtualRegsSize
;
1556 UNSERIALIZE_SCALAR(virtualRegsSize
);
1557 virtualRegs
.clear();
1558 virtualRegs
.resize(virtualRegsSize
);
1559 for (int i
= 0; i
< virtualRegsSize
; ++i
) {
1560 VirtualReg
*vnic
= &virtualRegs
[i
];
1561 std::string reg
= csprintf("vnic%d", i
);
1563 paramIn(cp
, section
, reg
+ ".RxData", vnic
->RxData
);
1564 paramIn(cp
, section
, reg
+ ".RxDone", vnic
->RxDone
);
1565 paramIn(cp
, section
, reg
+ ".TxData", vnic
->TxData
);
1566 paramIn(cp
, section
, reg
+ ".TxDone", vnic
->TxDone
);
1568 vnic
->rxUnique
= rxUnique
++;
1569 vnic
->txUnique
= txUnique
++;
1571 bool rxPacketExists
;
1572 paramIn(cp
, section
, reg
+ ".rxPacketExists", rxPacketExists
);
1573 if (rxPacketExists
) {
1575 paramIn(cp
, section
, reg
+ ".rxPacket", rxPacket
);
1576 vnic
->rxPacket
= rxFifo
.begin();
1580 paramIn(cp
, section
, reg
+ ".rxPacketOffset",
1581 vnic
->rxPacketOffset
);
1582 paramIn(cp
, section
, reg
+ ".rxPacketBytes", vnic
->rxPacketBytes
);
1584 vnic
->rxPacket
= rxFifo
.end();
1586 paramIn(cp
, section
, reg
+ ".rxDoneData", vnic
->rxDoneData
);
1590 * If there's a pending transmit, reschedule it now
1593 UNSERIALIZE_SCALAR(transmitTick
);
1595 txEvent
.schedule(curTick
+ transmitTick
);
1597 pioPort
->sendStatusChange(Port::RangeChange
);
1601 /* namespace Sinic */ }
1603 BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicInterface
)
1605 SimObjectParam
<EtherInt
*> peer
;
1606 SimObjectParam
<Sinic::Device
*> device
;
1607 END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicInterface
)
1609 BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicInterface
)
1611 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1612 INIT_PARAM(device
, "Ethernet device of this interface")
1614 END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicInterface
)
1616 CREATE_SIM_OBJECT_WNS(Sinic
, SinicInterface
)
1618 Sinic::Interface
*dev_int
= new Sinic::Interface(getInstanceName(), device
);
1620 EtherInt
*p
= (EtherInt
*)peer
;
1622 dev_int
->setPeer(p
);
1623 p
->setPeer(dev_int
);
1629 REGISTER_SIM_OBJECT_WNS(Sinic
, "SinicInt", SinicInterface
)
1632 BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicDevice
)
1635 SimObjectParam
<System
*> system
;
1636 SimObjectParam
<Platform
*> platform
;
1637 SimObjectParam
<PciConfigData
*> configdata
;
1638 Param
<uint32_t> pci_bus
;
1639 Param
<uint32_t> pci_dev
;
1640 Param
<uint32_t> pci_func
;
1641 Param
<Tick
> pio_latency
;
1642 Param
<Tick
> config_latency
;
1643 Param
<Tick
> intr_delay
;
1646 Param
<Tick
> dma_read_delay
;
1647 Param
<Tick
> dma_read_factor
;
1648 Param
<Tick
> dma_write_delay
;
1649 Param
<Tick
> dma_write_factor
;
1651 Param
<Tick
> rx_delay
;
1652 Param
<Tick
> tx_delay
;
1653 Param
<uint32_t> rx_max_copy
;
1654 Param
<uint32_t> tx_max_copy
;
1655 Param
<uint32_t> rx_max_intr
;
1656 Param
<uint32_t> rx_fifo_size
;
1657 Param
<uint32_t> tx_fifo_size
;
1658 Param
<uint32_t> rx_fifo_threshold
;
1659 Param
<uint32_t> rx_fifo_low_mark
;
1660 Param
<uint32_t> tx_fifo_high_mark
;
1661 Param
<uint32_t> tx_fifo_threshold
;
1663 Param
<bool> rx_filter
;
1664 Param
<std::string
> hardware_address
;
1665 Param
<bool> rx_thread
;
1666 Param
<bool> tx_thread
;
1668 Param
<uint32_t> virtual_count
;
1669 Param
<bool> zero_copy
;
1670 Param
<bool> delay_copy
;
1671 Param
<bool> virtual_addr
;
1673 END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicDevice
)
1675 BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicDevice
)
1678 INIT_PARAM(system
, "System pointer"),
1679 INIT_PARAM(platform
, "Platform pointer"),
1680 INIT_PARAM(configdata
, "PCI Config data"),
1681 INIT_PARAM(pci_bus
, "PCI bus ID"),
1682 INIT_PARAM(pci_dev
, "PCI device number"),
1683 INIT_PARAM(pci_func
, "PCI function code"),
1684 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
1685 INIT_PARAM(config_latency
, "Number of cycles for a config read or write"),
1686 INIT_PARAM(intr_delay
, "Interrupt Delay"),
1687 INIT_PARAM(clock
, "State machine cycle time"),
1689 INIT_PARAM(dma_read_delay
, "fixed delay for dma reads"),
1690 INIT_PARAM(dma_read_factor
, "multiplier for dma reads"),
1691 INIT_PARAM(dma_write_delay
, "fixed delay for dma writes"),
1692 INIT_PARAM(dma_write_factor
, "multiplier for dma writes"),
1694 INIT_PARAM(rx_delay
, "Receive Delay"),
1695 INIT_PARAM(tx_delay
, "Transmit Delay"),
1696 INIT_PARAM(rx_max_copy
, "rx max copy"),
1697 INIT_PARAM(tx_max_copy
, "rx max copy"),
1698 INIT_PARAM(rx_max_intr
, "rx max intr"),
1699 INIT_PARAM(rx_fifo_size
, "max size in bytes of rxFifo"),
1700 INIT_PARAM(tx_fifo_size
, "max size in bytes of txFifo"),
1701 INIT_PARAM(rx_fifo_threshold
, "max size in bytes of rxFifo"),
1702 INIT_PARAM(rx_fifo_low_mark
, "max size in bytes of rxFifo"),
1703 INIT_PARAM(tx_fifo_high_mark
, "max size in bytes of txFifo"),
1704 INIT_PARAM(tx_fifo_threshold
, "max size in bytes of txFifo"),
1706 INIT_PARAM(rx_filter
, "Enable Receive Filter"),
1707 INIT_PARAM(hardware_address
, "Ethernet Hardware Address"),
1708 INIT_PARAM(rx_thread
, ""),
1709 INIT_PARAM(tx_thread
, ""),
1710 INIT_PARAM(rss
, ""),
1711 INIT_PARAM(virtual_count
, ""),
1712 INIT_PARAM(zero_copy
, ""),
1713 INIT_PARAM(delay_copy
, ""),
1714 INIT_PARAM(virtual_addr
, "")
1716 END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic
, SinicDevice
)
1719 CREATE_SIM_OBJECT_WNS(Sinic
, SinicDevice
)
1721 Sinic::Sinic::Device::Params
*params
= new Device::Params
;
1722 params
->name
= getInstanceName();
1723 params
->platform
= platform
;
1724 params
->system
= system
;
1725 params
->configData
= configdata
;
1726 params
->busNum
= pci_bus
;
1727 params
->deviceNum
= pci_dev
;
1728 params
->functionNum
= pci_func
;
1729 params
->pio_delay
= pio_latency
;
1730 params
->config_delay
= config_latency
;
1731 params
->intr_delay
= intr_delay
;
1732 params
->clock
= clock
;
1734 params
->dma_read_delay
= dma_read_delay
;
1735 params
->dma_read_factor
= dma_read_factor
;
1736 params
->dma_write_delay
= dma_write_delay
;
1737 params
->dma_write_factor
= dma_write_factor
;
1739 params
->tx_delay
= tx_delay
;
1740 params
->rx_delay
= rx_delay
;
1741 params
->rx_max_copy
= rx_max_copy
;
1742 params
->tx_max_copy
= tx_max_copy
;
1743 params
->rx_max_intr
= rx_max_intr
;
1744 params
->rx_fifo_size
= rx_fifo_size
;
1745 params
->tx_fifo_size
= tx_fifo_size
;
1746 params
->rx_fifo_threshold
= rx_fifo_threshold
;
1747 params
->rx_fifo_low_mark
= rx_fifo_low_mark
;
1748 params
->tx_fifo_high_mark
= tx_fifo_high_mark
;
1749 params
->tx_fifo_threshold
= tx_fifo_threshold
;
1751 params
->rx_filter
= rx_filter
;
1752 params
->eaddr
= hardware_address
;
1753 params
->rx_thread
= rx_thread
;
1754 params
->tx_thread
= tx_thread
;
1756 params
->virtual_count
= virtual_count
;
1757 params
->zero_copy
= zero_copy
;
1758 params
->delay_copy
= delay_copy
;
1759 params
->virtual_addr
= virtual_addr
;
1761 return new Sinic::Device(params
);
1764 REGISTER_SIM_OBJECT_WNS(Sinic
, "Sinic", SinicDevice
)