fa4cd570ff848b7c990fad1a67fab9b95b03dbf4
2 * Copyright (c) 2004 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"
37 #include "dev/etherlink.hh"
38 #include "dev/sinic.hh"
39 #include "dev/pciconfigall.hh"
40 #include "mem/bus/bus.hh"
41 #include "mem/bus/dma_interface.hh"
42 #include "mem/bus/pio_interface.hh"
43 #include "mem/bus/pio_interface_impl.hh"
44 #include "mem/functional_mem/memory_control.hh"
45 #include "mem/functional_mem/physical_memory.hh"
46 #include "sim/builder.hh"
47 #include "sim/debug.hh"
48 #include "sim/eventq.hh"
49 #include "sim/host.hh"
50 #include "sim/stats.hh"
51 #include "targetarch/vtophys.hh"
57 const char *RxStateStrings
[] =
66 const char *TxStateStrings
[] =
76 ///////////////////////////////////////////////////////////////////////
81 : PciDev(p
), rxEnable(false), txEnable(false),
82 intrDelay(US2Ticks(p
->intr_delay
)),
83 intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0),
88 Device::Device(Params
*p
)
89 : Base(p
), plat(p
->plat
), physmem(p
->physmem
),
90 rxFifo(p
->rx_fifo_size
), txFifo(p
->tx_fifo_size
),
91 rxKickTick(0), txKickTick(0),
92 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
93 dmaReadDelay(p
->dma_read_delay
), dmaReadFactor(p
->dma_read_factor
),
94 dmaWriteDelay(p
->dma_write_delay
), dmaWriteFactor(p
->dma_write_factor
)
99 pioInterface
= newPioInterface(p
->name
, p
->hier
, p
->header_bus
, this,
100 &Device::cacheAccess
);
102 pioLatency
= p
->pio_latency
* p
->header_bus
->clockRatio
;
105 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
106 p
->header_bus
, p
->payload_bus
,
109 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
110 p
->header_bus
, p
->header_bus
,
112 } else if (p
->payload_bus
) {
113 pioInterface
= newPioInterface(p
->name
, p
->hier
, p
->payload_bus
, this,
114 &Device::cacheAccess
);
116 pioLatency
= p
->pio_latency
* p
->payload_bus
->clockRatio
;
118 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma", p
->payload_bus
,
130 .name(name() + ".rxBytes")
131 .desc("Bytes Received")
136 .name(name() + ".rxBandwidth")
137 .desc("Receive Bandwidth (bits/s)")
143 .name(name() + ".rxPackets")
144 .desc("Number of Packets Received")
149 .name(name() + ".rxPPS")
150 .desc("Packet Reception Rate (packets/s)")
156 .name(name() + ".rxIpPackets")
157 .desc("Number of IP Packets Received")
162 .name(name() + ".rxTcpPackets")
163 .desc("Number of Packets Received")
168 .name(name() + ".rxUdpPackets")
169 .desc("Number of UDP Packets Received")
174 .name(name() + ".rxIpChecksums")
175 .desc("Number of rx IP Checksums done by device")
181 .name(name() + ".rxTcpChecksums")
182 .desc("Number of rx TCP Checksums done by device")
188 .name(name() + ".rxUdpChecksums")
189 .desc("Number of rx UDP Checksums done by device")
195 .name(name() + ".totBandwidth")
196 .desc("Total Bandwidth (bits/s)")
202 .name(name() + ".totPackets")
203 .desc("Total Packets")
209 .name(name() + ".totBytes")
216 .name(name() + ".totPPS")
217 .desc("Total Tranmission Rate (packets/s)")
223 .name(name() + ".txBytes")
224 .desc("Bytes Transmitted")
229 .name(name() + ".txBandwidth")
230 .desc("Transmit Bandwidth (bits/s)")
236 .name(name() + ".txPackets")
237 .desc("Number of Packets Transmitted")
242 .name(name() + ".txPPS")
243 .desc("Packet Tranmission Rate (packets/s)")
249 .name(name() + ".txIpPackets")
250 .desc("Number of IP Packets Transmitted")
255 .name(name() + ".txTcpPackets")
256 .desc("Number of TCP Packets Transmitted")
261 .name(name() + ".txUdpPackets")
262 .desc("Number of Packets Transmitted")
267 .name(name() + ".txIpChecksums")
268 .desc("Number of tx IP Checksums done by device")
274 .name(name() + ".txTcpChecksums")
275 .desc("Number of tx TCP Checksums done by device")
281 .name(name() + ".txUdpChecksums")
282 .desc("Number of tx UDP Checksums done by device")
287 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
288 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
289 totBandwidth
= txBandwidth
+ rxBandwidth
;
290 totBytes
= txBytes
+ rxBytes
;
291 totPackets
= txPackets
+ rxPackets
;
292 txPacketRate
= txPackets
/ simSeconds
;
293 rxPacketRate
= rxPackets
/ simSeconds
;
297 * This is to write to the PCI general configuration registers
300 Device::WriteConfig(int offset
, int size
, uint32_t data
)
303 case PCI0_BASE_ADDR0
:
304 // Need to catch writes to BARs to update the PIO interface
305 PciDev::WriteConfig(offset
, size
, data
);
306 if (BARAddrs
[0] != 0) {
308 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
310 BARAddrs
[0] &= EV5::PAddrUncachedMask
;
315 PciDev::WriteConfig(offset
, size
, data
);
320 * This reads the device registers, which are detailed in the NS83820
324 Device::read(MemReqPtr
&req
, uint8_t *data
)
326 assert(config
.hdr
.command
& PCI_CMD_MSE
);
328 //The mask is to give you only the offset into the device register file
329 Addr daddr
= req
->paddr
& 0xfff;
331 if (Regs::regSize(daddr
) == 0)
332 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
333 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
335 if (req
->size
!= Regs::regSize(daddr
))
336 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
337 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
339 DPRINTF(EthernetPIO
, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
340 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
342 uint32_t ®32
= *(uint32_t *)data
;
343 uint64_t ®64
= *(uint64_t *)data
;
350 case Regs::RxMaxCopy
:
351 reg32
= regs
.RxMaxCopy
;
354 case Regs::TxMaxCopy
:
355 reg32
= regs
.TxMaxCopy
;
358 case Regs::RxThreshold
:
359 reg32
= regs
.RxThreshold
;
362 case Regs::TxThreshold
:
363 reg32
= regs
.TxThreshold
;
366 case Regs::IntrStatus
:
367 reg32
= regs
.IntrStatus
;
372 reg32
= regs
.IntrMask
;
381 reg64
= Regs::set_RxDone_FifoLen(regs
.RxDone
,
382 min(rxFifo
.packets(), 255));
391 reg64
= Regs::set_TxDone_FifoLen(regs
.TxDone
,
392 min(txFifo
.packets(), 255));
396 reg64
= params()->eaddr
;
400 panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
401 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
404 DPRINTF(EthernetPIO
, "read reg=%s done val=%#x\n", Regs::regName(daddr
),
405 Regs::regSize(daddr
) == 4 ? reg32
: reg64
);
411 Device::write(MemReqPtr
&req
, const uint8_t *data
)
413 assert(config
.hdr
.command
& PCI_CMD_MSE
);
414 Addr daddr
= req
->paddr
& 0xfff;
416 if (Regs::regSize(daddr
) == 0)
417 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
418 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
420 if (req
->size
!= Regs::regSize(daddr
))
421 panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
422 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
424 uint32_t reg32
= *(uint32_t *)data
;
425 uint64_t reg64
= *(uint64_t *)data
;
427 DPRINTF(EthernetPIO
, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
428 Regs::regName(daddr
), Regs::regSize(daddr
) == 4 ? reg32
: reg64
,
429 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
437 case Regs::RxThreshold
:
438 regs
.RxThreshold
= reg32
;
441 case Regs::TxThreshold
:
442 regs
.TxThreshold
= reg32
;
446 devIntrChangeMask(reg32
);
450 if (rxState
!= rxIdle
)
451 panic("receive machine busy with another request!");
456 rxState
= rxFifoBlock
;
462 if (txState
!= txIdle
)
463 panic("transmit machine busy with another request!");
468 txState
= txFifoBlock
;
474 panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
475 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
482 Device::devIntrPost(uint32_t interrupts
)
484 if ((interrupts
& Regs::Intr_Res
))
485 panic("Cannot set a reserved interrupt");
487 regs
.IntrStatus
|= interrupts
;
489 DPRINTF(EthernetIntr
,
490 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
491 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
493 if ((regs
.IntrStatus
& regs
.IntrMask
)) {
495 if ((regs
.IntrStatus
& regs
.IntrMask
& Regs::Intr_NoDelay
) == 0)
502 Device::devIntrClear(uint32_t interrupts
)
504 if ((interrupts
& Regs::Intr_Res
))
505 panic("Cannot clear a reserved interrupt");
507 regs
.IntrStatus
&= ~interrupts
;
509 DPRINTF(EthernetIntr
,
510 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
511 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
513 if (!(regs
.IntrStatus
& regs
.IntrMask
))
518 Device::devIntrChangeMask(uint32_t newmask
)
520 if (regs
.IntrMask
== newmask
)
523 regs
.IntrMask
= newmask
;
525 DPRINTF(EthernetIntr
,
526 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
527 regs
.IntrStatus
, regs
.IntrMask
, regs
.IntrStatus
& regs
.IntrMask
);
529 if (regs
.IntrStatus
& regs
.IntrMask
)
530 cpuIntrPost(curTick
);
536 Base::cpuIntrPost(Tick when
)
538 // If the interrupt you want to post is later than an interrupt
539 // already scheduled, just let it post in the coming one and don't
541 // HOWEVER, must be sure that the scheduled intrTick is in the
542 // future (this was formerly the source of a bug)
544 * @todo this warning should be removed and the intrTick code should
547 assert(when
>= curTick
);
548 assert(intrTick
>= curTick
|| intrTick
== 0);
549 if (!cpuIntrEnable
) {
550 DPRINTF(EthernetIntr
, "interrupts not enabled.\n",
555 if (when
> intrTick
&& intrTick
!= 0) {
556 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
562 if (intrTick
< curTick
) {
567 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
572 intrEvent
= new IntrEvent(this, true);
573 intrEvent
->schedule(intrTick
);
579 assert(intrTick
== curTick
);
581 // Whether or not there's a pending interrupt, we don't care about
586 // Don't send an interrupt if there's already one
587 if (cpuPendingIntr
) {
588 DPRINTF(EthernetIntr
,
589 "would send an interrupt now, but there's already pending\n");
592 cpuPendingIntr
= true;
594 DPRINTF(EthernetIntr
, "posting interrupt\n");
612 cpuPendingIntr
= false;
614 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
619 Base::cpuIntrPending() const
620 { return cpuPendingIntr
; }
623 Device::changeConfig(uint32_t newconf
)
625 uint32_t changed
= regs
.Config
^ newconf
;
629 regs
.Config
= newconf
;
631 if ((changed
& Regs::Config_Reset
)) {
632 assert(regs
.Config
& Regs::Config_Reset
);
634 regs
.Config
&= ~Regs::Config_Reset
;
637 if ((changed
& Regs::Config_IntEn
)) {
638 cpuIntrEnable
= regs
.Config
& Regs::Config_IntEn
;
640 if (regs
.IntrStatus
& regs
.IntrMask
)
641 cpuIntrPost(curTick
);
647 if ((changed
& Regs::Config_TxEn
)) {
648 txEnable
= regs
.Config
& Regs::Config_TxEn
;
653 if ((changed
& Regs::Config_RxEn
)) {
654 rxEnable
= regs
.Config
& Regs::Config_RxEn
;
663 using namespace Regs
;
664 memset(®s
, 0, sizeof(regs
));
665 regs
.RxMaxCopy
= params()->rx_max_copy
;
666 regs
.TxMaxCopy
= params()->tx_max_copy
;
667 regs
.IntrMask
= Intr_TxFifo
| Intr_RxFifo
| Intr_RxData
;
679 assert(rxState
== rxCopy
);
680 rxState
= rxCopyDone
;
681 physmem
->dma_write(rxDmaAddr
, (uint8_t *)rxDmaData
, rxDmaLen
);
682 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
683 rxDmaAddr
, rxDmaLen
);
684 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
697 DPRINTF(EthernetSM
, "receive kick rxState=%s (rxFifo.size=%d)\n",
698 RxStateStrings
[rxState
], rxFifo
.size());
700 if (rxKickTick
> curTick
) {
701 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
710 pioInterface
->respond(rxPioRequest
, curTick
);
717 rxState
= rxBeginCopy
;
721 if (rxFifo
.empty()) {
722 DPRINTF(EthernetSM
, "receive waiting for data. Nothing to do.\n");
726 // Grab a new packet from the fifo.
727 rxPacket
= rxFifo
.front();
728 rxPacketBufPtr
= rxPacket
->data
;
729 rxPktBytes
= rxPacket
->length
;
733 /* scope for variables */ {
736 rxDoneData
|= Regs::RxDone_IpPacket
;
738 if (cksum(ip
) != 0) {
739 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
740 rxDoneData
|= Regs::RxDone_IpError
;
745 rxDoneData
|= Regs::RxDone_TcpPacket
;
747 if (cksum(tcp
) != 0) {
748 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
749 rxDoneData
|= Regs::RxDone_TcpError
;
752 rxDoneData
|= Regs::RxDone_UdpPacket
;
754 if (cksum(udp
) != 0) {
755 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
756 rxDoneData
|= Regs::RxDone_UdpError
;
761 rxState
= rxBeginCopy
;
765 rxDmaAddr
= plat
->pciToDma(Regs::get_RxData_Addr(regs
.RxData
));
766 rxDmaLen
= min
<int>(Regs::get_RxData_Len(regs
.RxData
), rxPktBytes
);
767 rxDmaData
= rxPacketBufPtr
;
770 if (!dmaInterface
->busy()) {
771 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
,
772 curTick
, &rxDmaEvent
, true);
779 if (dmaWriteDelay
!= 0 || dmaWriteFactor
!= 0) {
780 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
781 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
782 rxDmaEvent
.schedule(start
);
790 DPRINTF(EthernetSM
, "receive machine still copying\n");
794 regs
.RxDone
= rxDoneData
| rxDmaLen
;
796 if (rxPktBytes
== rxDmaLen
) {
800 regs
.RxDone
|= Regs::RxDone_More
;
801 rxPktBytes
-= rxDmaLen
;
802 rxPacketBufPtr
+= rxDmaLen
;
805 regs
.RxDone
|= Regs::RxDone_Complete
;
806 devIntrPost(Regs::Intr_RxData
);
811 panic("Invalid rxState!");
814 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
815 RxStateStrings
[rxState
]);
821 * @todo do we want to schedule a future kick?
823 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
824 RxStateStrings
[rxState
]);
830 assert(txState
== txCopy
);
831 txState
= txCopyDone
;
832 physmem
->dma_read((uint8_t *)txDmaData
, txDmaAddr
, txDmaLen
);
833 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
834 txDmaAddr
, txDmaLen
);
835 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
848 if (txFifo
.empty()) {
849 DPRINTF(Ethernet
, "nothing to transmit\n");
853 PacketPtr packet
= txFifo
.front();
854 if (!interface
->sendPacket(packet
)) {
855 DPRINTF(Ethernet
, "Packet Transmit: failed txFifo available %d\n",
863 if (DTRACE(Ethernet
)) {
866 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
869 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
870 tcp
->sport(), tcp
->dport());
876 DDUMP(Ethernet
, packet
->data
, packet
->length
);
877 txBytes
+= packet
->length
;
880 DPRINTF(Ethernet
, "Packet Transmit: successful txFifo Available %d\n",
883 if (txFifo
.size() <= params()->tx_fifo_threshold
)
884 devIntrPost(Regs::Intr_TxFifo
);
886 devIntrPost(Regs::Intr_TxDone
);
889 if (!txFifo
.empty() && !txEvent
.scheduled()) {
890 DPRINTF(Ethernet
, "reschedule transmit\n");
891 txEvent
.schedule(curTick
+ 1000);
898 DPRINTF(EthernetSM
, "transmit kick txState=%s (txFifo.size=%d)\n",
899 TxStateStrings
[txState
], txFifo
.size());
901 if (txKickTick
> curTick
) {
902 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
911 pioInterface
->respond(txPioRequest
, curTick
+ pioLatency
);
918 // Grab a new packet from the fifo.
919 txPacket
= new PacketData(16384);
920 txPacketBufPtr
= txPacket
->data
;
923 if (txFifo
.avail() - txPacket
->length
<
924 Regs::get_TxData_Len(regs
.TxData
)) {
925 DPRINTF(EthernetSM
, "transmit fifo full. Nothing to do.\n");
929 txState
= txBeginCopy
;
933 txDmaAddr
= plat
->pciToDma(Regs::get_TxData_Addr(regs
.TxData
));
934 txDmaLen
= Regs::get_TxData_Len(regs
.TxData
);
935 txDmaData
= txPacketBufPtr
;
938 if (!dmaInterface
->busy()) {
939 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
,
940 curTick
, &txDmaEvent
, true);
948 if (dmaReadDelay
!= 0 || dmaReadFactor
!= 0) {
949 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
950 Tick start
= curTick
+ dmaReadDelay
+ factor
;
951 txDmaEvent
.schedule(start
);
959 DPRINTF(EthernetSM
, "transmit machine still copying\n");
963 txPacket
->length
+= txDmaLen
;
964 if ((regs
.TxData
& Regs::TxData_More
)) {
965 txPacketBufPtr
+= txDmaLen
;
967 assert(txPacket
->length
<= txFifo
.avail());
968 if ((regs
.TxData
& Regs::TxData_Checksum
)) {
974 tcp
->sum(cksum(tcp
));
981 udp
->sum(cksum(udp
));
990 txFifo
.push(txPacket
);
995 regs
.TxDone
= txDmaLen
| Regs::TxDone_Complete
;
996 devIntrPost(Regs::Intr_TxData
);
1001 panic("Invalid txState!");
1004 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1005 TxStateStrings
[txState
]);
1011 * @todo do we want to schedule a future kick?
1013 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1014 TxStateStrings
[txState
]);
1018 Device::transferDone()
1020 if (txFifo
.empty()) {
1021 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1025 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1027 if (txEvent
.scheduled())
1028 txEvent
.reschedule(curTick
+ 1);
1030 txEvent
.schedule(curTick
+ 1);
1034 Device::rxFilter(const PacketPtr
&packet
)
1036 if (!Regs::get_Config_Filter(regs
.Config
))
1039 panic("receive filter not implemented\n");
1045 EthHdr
*eth
= packet
->eth();
1046 if (eth
->unicast()) {
1047 // If we're accepting all unicast addresses
1051 // If we make a perfect match
1052 if (acceptPerfect
&& params
->eaddr
== eth
.dst())
1055 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
1058 } else if (eth
->broadcast()) {
1059 // if we're accepting broadcasts
1060 if (acceptBroadcast
)
1063 } else if (eth
->multicast()) {
1064 // if we're accepting all multicasts
1065 if (acceptMulticast
)
1071 DPRINTF(Ethernet
, "rxFilter drop\n");
1072 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1079 Device::recvPacket(PacketPtr packet
)
1081 rxBytes
+= packet
->length
;
1084 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifo Available is %d\n",
1088 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1089 interface
->recvDone();
1093 if (rxFilter(packet
)) {
1094 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1095 interface
->recvDone();
1099 if (rxFifo
.size() >= params()->rx_fifo_threshold
)
1100 devIntrPost(Regs::Intr_RxFifo
);
1102 if (!rxFifo
.push(packet
)) {
1104 "packet will not fit in receive buffer...packet dropped\n");
1108 interface
->recvDone();
1109 devIntrPost(Regs::Intr_RxDone
);
1114 //=====================================================================
1118 Base::serialize(ostream
&os
)
1120 // Serialize the PciDev base class
1121 PciDev::serialize(os
);
1123 SERIALIZE_SCALAR(rxEnable
);
1124 SERIALIZE_SCALAR(txEnable
);
1125 SERIALIZE_SCALAR(cpuIntrEnable
);
1128 * Keep track of pending interrupt status.
1130 SERIALIZE_SCALAR(intrTick
);
1131 SERIALIZE_SCALAR(cpuPendingIntr
);
1132 Tick intrEventTick
= 0;
1134 intrEventTick
= intrEvent
->when();
1135 SERIALIZE_SCALAR(intrEventTick
);
1139 Base::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1141 // Unserialize the PciDev base class
1142 PciDev::unserialize(cp
, section
);
1144 UNSERIALIZE_SCALAR(rxEnable
);
1145 UNSERIALIZE_SCALAR(txEnable
);
1146 UNSERIALIZE_SCALAR(cpuIntrEnable
);
1149 * Keep track of pending interrupt status.
1151 UNSERIALIZE_SCALAR(intrTick
);
1152 UNSERIALIZE_SCALAR(cpuPendingIntr
);
1154 UNSERIALIZE_SCALAR(intrEventTick
);
1155 if (intrEventTick
) {
1156 intrEvent
= new IntrEvent(this, true);
1157 intrEvent
->schedule(intrEventTick
);
1162 Device::serialize(ostream
&os
)
1164 // Serialize the PciDev base class
1165 Base::serialize(os
);
1167 if (rxDmaEvent
.scheduled())
1170 if (txDmaEvent
.scheduled())
1174 * Serialize the device registers
1176 SERIALIZE_SCALAR(regs
.Config
);
1177 SERIALIZE_SCALAR(regs
.RxMaxCopy
);
1178 SERIALIZE_SCALAR(regs
.TxMaxCopy
);
1179 SERIALIZE_SCALAR(regs
.RxThreshold
);
1180 SERIALIZE_SCALAR(regs
.TxThreshold
);
1181 SERIALIZE_SCALAR(regs
.IntrStatus
);
1182 SERIALIZE_SCALAR(regs
.IntrMask
);
1183 SERIALIZE_SCALAR(regs
.RxData
);
1184 SERIALIZE_SCALAR(regs
.RxDone
);
1185 SERIALIZE_SCALAR(regs
.TxData
);
1186 SERIALIZE_SCALAR(regs
.TxDone
);
1189 * Serialize rx state machine
1191 int rxState
= this->rxState
;
1192 SERIALIZE_SCALAR(rxState
);
1193 rxFifo
.serialize("rxFifo", os
);
1194 bool rxPacketExists
= rxPacket
;
1195 SERIALIZE_SCALAR(rxPacketExists
);
1196 if (rxPacketExists
) {
1197 rxPacket
->serialize("rxPacket", os
);
1198 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
1199 SERIALIZE_SCALAR(rxPktBufPtr
);
1200 SERIALIZE_SCALAR(rxPktBytes
);
1202 SERIALIZE_SCALAR(rxDoneData
);
1205 * Serialize tx state machine
1207 int txState
= this->txState
;
1208 SERIALIZE_SCALAR(txState
);
1209 txFifo
.serialize("txFifo", os
);
1210 bool txPacketExists
= txPacket
;
1211 SERIALIZE_SCALAR(txPacketExists
);
1212 if (txPacketExists
) {
1213 txPacket
->serialize("txPacket", os
);
1214 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
1215 SERIALIZE_SCALAR(txPktBufPtr
);
1216 SERIALIZE_SCALAR(txPktBytes
);
1220 * If there's a pending transmit, store the time so we can
1221 * reschedule it later
1223 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
1224 SERIALIZE_SCALAR(transmitTick
);
1228 Device::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1230 // Unserialize the PciDev base class
1231 Base::unserialize(cp
, section
);
1234 * Unserialize the device registers
1236 UNSERIALIZE_SCALAR(regs
.Config
);
1237 UNSERIALIZE_SCALAR(regs
.RxMaxCopy
);
1238 UNSERIALIZE_SCALAR(regs
.TxMaxCopy
);
1239 UNSERIALIZE_SCALAR(regs
.RxThreshold
);
1240 UNSERIALIZE_SCALAR(regs
.TxThreshold
);
1241 UNSERIALIZE_SCALAR(regs
.IntrStatus
);
1242 UNSERIALIZE_SCALAR(regs
.IntrMask
);
1243 UNSERIALIZE_SCALAR(regs
.RxData
);
1244 UNSERIALIZE_SCALAR(regs
.RxDone
);
1245 UNSERIALIZE_SCALAR(regs
.TxData
);
1246 UNSERIALIZE_SCALAR(regs
.TxDone
);
1249 * Unserialize rx state machine
1252 UNSERIALIZE_SCALAR(rxState
);
1253 this->rxState
= (RxState
) rxState
;
1254 rxFifo
.unserialize("rxFifo", cp
, section
);
1255 bool rxPacketExists
;
1256 UNSERIALIZE_SCALAR(rxPacketExists
);
1258 if (rxPacketExists
) {
1259 rxPacket
= new PacketData(16384);
1260 rxPacket
->unserialize("rxPacket", cp
, section
);
1261 uint32_t rxPktBufPtr
;
1262 UNSERIALIZE_SCALAR(rxPktBufPtr
);
1263 this->rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
1264 UNSERIALIZE_SCALAR(rxPktBytes
);
1266 UNSERIALIZE_SCALAR(rxDoneData
);
1269 * Unserialize tx state machine
1272 UNSERIALIZE_SCALAR(txState
);
1273 this->txState
= (TxState
) txState
;
1274 txFifo
.unserialize("txFifo", cp
, section
);
1275 bool txPacketExists
;
1276 UNSERIALIZE_SCALAR(txPacketExists
);
1278 if (txPacketExists
) {
1279 txPacket
= new PacketData(16384);
1280 txPacket
->unserialize("txPacket", cp
, section
);
1281 uint32_t txPktBufPtr
;
1282 UNSERIALIZE_SCALAR(txPktBufPtr
);
1283 this->txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
1284 UNSERIALIZE_SCALAR(txPktBytes
);
1288 * If there's a pending transmit, reschedule it now
1291 UNSERIALIZE_SCALAR(transmitTick
);
1293 txEvent
.schedule(curTick
+ transmitTick
);
1296 * re-add addrRanges to bus bridges
1299 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
1303 Device::cacheAccess(MemReqPtr
&req
)
1305 //The mask is to give you only the offset into the device register file
1306 Addr daddr
= req
->paddr
- addr
;
1308 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
1311 Tick when
= curTick
+ pioLatency
;
1315 if (rxState
!= rxIdle
) {
1322 if (txState
!= txIdle
) {
1332 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1334 SimObjectParam
<EtherInt
*> peer
;
1335 SimObjectParam
<Device
*> device
;
1337 END_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1339 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface
)
1341 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1342 INIT_PARAM(device
, "Ethernet device of this interface")
1344 END_INIT_SIM_OBJECT_PARAMS(Interface
)
1346 CREATE_SIM_OBJECT(Interface
)
1348 Interface
*dev_int
= new Interface(getInstanceName(), device
);
1350 EtherInt
*p
= (EtherInt
*)peer
;
1352 dev_int
->setPeer(p
);
1353 p
->setPeer(dev_int
);
1359 REGISTER_SIM_OBJECT("SinicInt", Interface
)
1362 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device
)
1364 Param
<Tick
> tx_delay
;
1365 Param
<Tick
> rx_delay
;
1366 Param
<Tick
> intr_delay
;
1367 SimObjectParam
<MemoryController
*> mmu
;
1368 SimObjectParam
<PhysicalMemory
*> physmem
;
1369 Param
<bool> rx_filter
;
1370 Param
<string
> hardware_address
;
1371 SimObjectParam
<Bus
*> header_bus
;
1372 SimObjectParam
<Bus
*> payload_bus
;
1373 SimObjectParam
<HierParams
*> hier
;
1374 Param
<Tick
> pio_latency
;
1375 SimObjectParam
<PciConfigAll
*> configspace
;
1376 SimObjectParam
<PciConfigData
*> configdata
;
1377 SimObjectParam
<Platform
*> platform
;
1378 Param
<uint32_t> pci_bus
;
1379 Param
<uint32_t> pci_dev
;
1380 Param
<uint32_t> pci_func
;
1381 Param
<uint32_t> rx_max_copy
;
1382 Param
<uint32_t> tx_max_copy
;
1383 Param
<uint32_t> rx_fifo_size
;
1384 Param
<uint32_t> tx_fifo_size
;
1385 Param
<uint32_t> rx_fifo_threshold
;
1386 Param
<uint32_t> tx_fifo_threshold
;
1387 Param
<Tick
> dma_read_delay
;
1388 Param
<Tick
> dma_read_factor
;
1389 Param
<Tick
> dma_write_delay
;
1390 Param
<Tick
> dma_write_factor
;
1392 END_DECLARE_SIM_OBJECT_PARAMS(Device
)
1394 BEGIN_INIT_SIM_OBJECT_PARAMS(Device
)
1396 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
1397 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
1398 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
1399 INIT_PARAM(mmu
, "Memory Controller"),
1400 INIT_PARAM(physmem
, "Physical Memory"),
1401 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
1402 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
1403 "00:99:00:00:00:01"),
1404 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
1405 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
1406 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
1407 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
1408 INIT_PARAM(configspace
, "PCI Configspace"),
1409 INIT_PARAM(configdata
, "PCI Config data"),
1410 INIT_PARAM(platform
, "Platform"),
1411 INIT_PARAM(pci_bus
, "PCI bus"),
1412 INIT_PARAM(pci_dev
, "PCI device number"),
1413 INIT_PARAM(pci_func
, "PCI function code"),
1414 INIT_PARAM_DFLT(rx_max_copy
, "rx max copy", 16*1024),
1415 INIT_PARAM_DFLT(tx_max_copy
, "rx max copy", 16*1024),
1416 INIT_PARAM_DFLT(rx_fifo_size
, "max size in bytes of rxFifo", 64*1024),
1417 INIT_PARAM_DFLT(tx_fifo_size
, "max size in bytes of txFifo", 64*1024),
1418 INIT_PARAM_DFLT(rx_fifo_threshold
, "max size in bytes of rxFifo", 48*1024),
1419 INIT_PARAM_DFLT(tx_fifo_threshold
, "max size in bytes of txFifo", 16*1024),
1420 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
1421 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
1422 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
1423 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0)
1425 END_INIT_SIM_OBJECT_PARAMS(Device
)
1428 CREATE_SIM_OBJECT(Device
)
1430 Device::Params
*params
= new Device::Params
;
1431 params
->name
= getInstanceName();
1432 params
->intr_delay
= intr_delay
;
1433 params
->physmem
= physmem
;
1434 params
->tx_delay
= tx_delay
;
1435 params
->rx_delay
= rx_delay
;
1437 params
->hier
= hier
;
1438 params
->header_bus
= header_bus
;
1439 params
->payload_bus
= payload_bus
;
1440 params
->pio_latency
= pio_latency
;
1441 params
->configSpace
= configspace
;
1442 params
->configData
= configdata
;
1443 params
->plat
= platform
;
1444 params
->busNum
= pci_bus
;
1445 params
->deviceNum
= pci_dev
;
1446 params
->functionNum
= pci_func
;
1447 params
->rx_filter
= rx_filter
;
1448 params
->eaddr
= hardware_address
;
1449 params
->rx_max_copy
= rx_max_copy
;
1450 params
->tx_max_copy
= tx_max_copy
;
1451 params
->rx_fifo_size
= rx_fifo_size
;
1452 params
->tx_fifo_size
= tx_fifo_size
;
1453 params
->rx_fifo_threshold
= rx_fifo_threshold
;
1454 params
->tx_fifo_threshold
= tx_fifo_threshold
;
1455 params
->dma_read_delay
= dma_read_delay
;
1456 params
->dma_read_factor
= dma_read_factor
;
1457 params
->dma_write_delay
= dma_write_delay
;
1458 params
->dma_write_factor
= dma_write_factor
;
1459 return new Device(params
);
1462 REGISTER_SIM_OBJECT("Sinic", Device
)
1464 /* namespace Sinic */ }