e5cd877a0a91b2da02adbbedc5b8df25ea46a4c0
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"
36 #include "dev/etherlink.hh"
37 #include "dev/sinic.hh"
38 #include "dev/pciconfigall.hh"
39 #include "mem/bus/bus.hh"
40 #include "mem/bus/dma_interface.hh"
41 #include "mem/bus/pio_interface.hh"
42 #include "mem/bus/pio_interface_impl.hh"
43 #include "mem/functional/memory_control.hh"
44 #include "mem/functional/physical.hh"
45 #include "sim/builder.hh"
46 #include "sim/debug.hh"
47 #include "sim/eventq.hh"
48 #include "sim/host.hh"
49 #include "sim/stats.hh"
50 #include "targetarch/vtophys.hh"
56 const char *RxStateStrings
[] =
65 const char *TxStateStrings
[] =
75 ///////////////////////////////////////////////////////////////////////
80 : PciDev(p
), rxEnable(false), txEnable(false), cycleTime(p
->cycle_time
),
81 intrDelay(p
->intr_delay
), intrTick(0), cpuIntrEnable(false),
82 cpuPendingIntr(false), intrEvent(0), interface(NULL
)
86 Device::Device(Params
*p
)
87 : Base(p
), plat(p
->plat
), physmem(p
->physmem
),
88 rxFifo(p
->rx_fifo_size
), txFifo(p
->tx_fifo_size
),
89 rxKickTick(0), txKickTick(0),
90 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
91 dmaReadDelay(p
->dma_read_delay
), dmaReadFactor(p
->dma_read_factor
),
92 dmaWriteDelay(p
->dma_write_delay
), dmaWriteFactor(p
->dma_write_factor
)
97 pioInterface
= newPioInterface(p
->name
, p
->hier
, p
->io_bus
, this,
98 &Device::cacheAccess
);
100 pioLatency
= p
->pio_latency
* p
->io_bus
->clockRate
;
103 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma", p
->io_bus
,
107 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma", p
->io_bus
,
110 } else if (p
->payload_bus
) {
111 pioInterface
= newPioInterface(p
->name
, p
->hier
, p
->payload_bus
, this,
112 &Device::cacheAccess
);
114 pioLatency
= p
->pio_latency
* p
->payload_bus
->clockRate
;
116 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma", p
->payload_bus
,
129 .name(name() + ".rxBytes")
130 .desc("Bytes Received")
135 .name(name() + ".rxBandwidth")
136 .desc("Receive Bandwidth (bits/s)")
142 .name(name() + ".rxPackets")
143 .desc("Number of Packets Received")
148 .name(name() + ".rxPPS")
149 .desc("Packet Reception Rate (packets/s)")
155 .name(name() + ".rxIpPackets")
156 .desc("Number of IP Packets Received")
161 .name(name() + ".rxTcpPackets")
162 .desc("Number of Packets Received")
167 .name(name() + ".rxUdpPackets")
168 .desc("Number of UDP Packets Received")
173 .name(name() + ".rxIpChecksums")
174 .desc("Number of rx IP Checksums done by device")
180 .name(name() + ".rxTcpChecksums")
181 .desc("Number of rx TCP Checksums done by device")
187 .name(name() + ".rxUdpChecksums")
188 .desc("Number of rx UDP Checksums done by device")
194 .name(name() + ".totBandwidth")
195 .desc("Total Bandwidth (bits/s)")
201 .name(name() + ".totPackets")
202 .desc("Total Packets")
208 .name(name() + ".totBytes")
215 .name(name() + ".totPPS")
216 .desc("Total Tranmission Rate (packets/s)")
222 .name(name() + ".txBytes")
223 .desc("Bytes Transmitted")
228 .name(name() + ".txBandwidth")
229 .desc("Transmit Bandwidth (bits/s)")
235 .name(name() + ".txPackets")
236 .desc("Number of Packets Transmitted")
241 .name(name() + ".txPPS")
242 .desc("Packet Tranmission Rate (packets/s)")
248 .name(name() + ".txIpPackets")
249 .desc("Number of IP Packets Transmitted")
254 .name(name() + ".txTcpPackets")
255 .desc("Number of TCP Packets Transmitted")
260 .name(name() + ".txUdpPackets")
261 .desc("Number of Packets Transmitted")
266 .name(name() + ".txIpChecksums")
267 .desc("Number of tx IP Checksums done by device")
273 .name(name() + ".txTcpChecksums")
274 .desc("Number of tx TCP Checksums done by device")
280 .name(name() + ".txUdpChecksums")
281 .desc("Number of tx UDP Checksums done by device")
286 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
287 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
288 totBandwidth
= txBandwidth
+ rxBandwidth
;
289 totBytes
= txBytes
+ rxBytes
;
290 totPackets
= txPackets
+ rxPackets
;
291 txPacketRate
= txPackets
/ simSeconds
;
292 rxPacketRate
= rxPackets
/ simSeconds
;
296 * This is to write to the PCI general configuration registers
299 Device::WriteConfig(int offset
, int size
, uint32_t data
)
302 case PCI0_BASE_ADDR0
:
303 // Need to catch writes to BARs to update the PIO interface
304 PciDev::WriteConfig(offset
, size
, data
);
305 if (BARAddrs
[0] != 0) {
307 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
309 BARAddrs
[0] &= EV5::PAddrUncachedMask
;
314 PciDev::WriteConfig(offset
, size
, data
);
319 * This reads the device registers, which are detailed in the NS83820
323 Device::read(MemReqPtr
&req
, uint8_t *data
)
325 assert(config
.hdr
.command
& PCI_CMD_MSE
);
327 //The mask is to give you only the offset into the device register file
328 Addr daddr
= req
->paddr
& 0xfff;
330 if (Regs::regSize(daddr
) == 0)
331 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
332 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
334 if (req
->size
!= Regs::regSize(daddr
))
335 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
336 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
338 DPRINTF(EthernetPIO
, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
339 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
341 uint32_t ®32
= *(uint32_t *)data
;
342 uint64_t ®64
= *(uint64_t *)data
;
349 case Regs::RxMaxCopy
:
350 reg32
= regs
.RxMaxCopy
;
353 case Regs::TxMaxCopy
:
354 reg32
= regs
.TxMaxCopy
;
357 case Regs::RxThreshold
:
358 reg32
= regs
.RxThreshold
;
361 case Regs::TxThreshold
:
362 reg32
= regs
.TxThreshold
;
365 case Regs::IntrStatus
:
366 reg32
= regs
.IntrStatus
;
371 reg32
= regs
.IntrMask
;
380 reg64
= Regs::set_RxDone_FifoLen(regs
.RxDone
,
381 min(rxFifo
.packets(), 255));
390 reg64
= Regs::set_TxDone_FifoLen(regs
.TxDone
,
391 min(txFifo
.packets(), 255));
395 reg64
= params()->eaddr
;
399 panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
400 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
403 DPRINTF(EthernetPIO
, "read reg=%s done val=%#x\n", Regs::regName(daddr
),
404 Regs::regSize(daddr
) == 4 ? reg32
: reg64
);
410 Device::write(MemReqPtr
&req
, const uint8_t *data
)
412 assert(config
.hdr
.command
& PCI_CMD_MSE
);
413 Addr daddr
= req
->paddr
& 0xfff;
415 if (Regs::regSize(daddr
) == 0)
416 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
417 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
419 if (req
->size
!= Regs::regSize(daddr
))
420 panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
421 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
423 uint32_t reg32
= *(uint32_t *)data
;
424 uint64_t reg64
= *(uint64_t *)data
;
426 DPRINTF(EthernetPIO
, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
427 Regs::regName(daddr
), Regs::regSize(daddr
) == 4 ? reg32
: reg64
,
428 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
436 case Regs::RxThreshold
:
437 regs
.RxThreshold
= reg32
;
440 case Regs::TxThreshold
:
441 regs
.TxThreshold
= reg32
;
445 devIntrChangeMask(reg32
);
449 if (rxState
!= rxIdle
)
450 panic("receive machine busy with another request!");
455 rxState
= rxFifoBlock
;
461 if (txState
!= txIdle
)
462 panic("transmit machine busy with another request!");
467 txState
= txFifoBlock
;
473 panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
474 Regs::regName(daddr
), daddr
, req
->paddr
, req
->vaddr
, req
->size
);
481 Device::devIntrPost(uint32_t interrupts
)
483 if ((interrupts
& Regs::Intr_Res
))
484 panic("Cannot set a reserved interrupt");
486 regs
.IntrStatus
|= interrupts
;
488 DPRINTF(EthernetIntr
,
489 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
490 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
492 if ((regs
.IntrStatus
& regs
.IntrMask
)) {
494 if ((regs
.IntrStatus
& regs
.IntrMask
& Regs::Intr_NoDelay
) == 0)
501 Device::devIntrClear(uint32_t interrupts
)
503 if ((interrupts
& Regs::Intr_Res
))
504 panic("Cannot clear a reserved interrupt");
506 regs
.IntrStatus
&= ~interrupts
;
508 DPRINTF(EthernetIntr
,
509 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
510 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
512 if (!(regs
.IntrStatus
& regs
.IntrMask
))
517 Device::devIntrChangeMask(uint32_t newmask
)
519 if (regs
.IntrMask
== newmask
)
522 regs
.IntrMask
= newmask
;
524 DPRINTF(EthernetIntr
,
525 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
526 regs
.IntrStatus
, regs
.IntrMask
, regs
.IntrStatus
& regs
.IntrMask
);
528 if (regs
.IntrStatus
& regs
.IntrMask
)
529 cpuIntrPost(curTick
);
535 Base::cpuIntrPost(Tick when
)
537 // If the interrupt you want to post is later than an interrupt
538 // already scheduled, just let it post in the coming one and don't
540 // HOWEVER, must be sure that the scheduled intrTick is in the
541 // future (this was formerly the source of a bug)
543 * @todo this warning should be removed and the intrTick code should
546 assert(when
>= curTick
);
547 assert(intrTick
>= curTick
|| intrTick
== 0);
548 if (!cpuIntrEnable
) {
549 DPRINTF(EthernetIntr
, "interrupts not enabled.\n",
554 if (when
> intrTick
&& intrTick
!= 0) {
555 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
561 if (intrTick
< curTick
) {
566 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
571 intrEvent
= new IntrEvent(this, true);
572 intrEvent
->schedule(intrTick
);
578 assert(intrTick
== curTick
);
580 // Whether or not there's a pending interrupt, we don't care about
585 // Don't send an interrupt if there's already one
586 if (cpuPendingIntr
) {
587 DPRINTF(EthernetIntr
,
588 "would send an interrupt now, but there's already pending\n");
591 cpuPendingIntr
= true;
593 DPRINTF(EthernetIntr
, "posting interrupt\n");
611 cpuPendingIntr
= false;
613 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
618 Base::cpuIntrPending() const
619 { return cpuPendingIntr
; }
622 Device::changeConfig(uint32_t newconf
)
624 uint32_t changed
= regs
.Config
^ newconf
;
628 regs
.Config
= newconf
;
630 if ((changed
& Regs::Config_Reset
)) {
631 assert(regs
.Config
& Regs::Config_Reset
);
633 regs
.Config
&= ~Regs::Config_Reset
;
636 if ((changed
& Regs::Config_IntEn
)) {
637 cpuIntrEnable
= regs
.Config
& Regs::Config_IntEn
;
639 if (regs
.IntrStatus
& regs
.IntrMask
)
640 cpuIntrPost(curTick
);
646 if ((changed
& Regs::Config_TxEn
)) {
647 txEnable
= regs
.Config
& Regs::Config_TxEn
;
652 if ((changed
& Regs::Config_RxEn
)) {
653 rxEnable
= regs
.Config
& Regs::Config_RxEn
;
662 using namespace Regs
;
663 memset(®s
, 0, sizeof(regs
));
664 regs
.RxMaxCopy
= params()->rx_max_copy
;
665 regs
.TxMaxCopy
= params()->tx_max_copy
;
666 regs
.IntrMask
= Intr_TxFifo
| Intr_RxFifo
| Intr_RxData
;
678 assert(rxState
== rxCopy
);
679 rxState
= rxCopyDone
;
680 physmem
->dma_write(rxDmaAddr
, (uint8_t *)rxDmaData
, rxDmaLen
);
681 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
682 rxDmaAddr
, rxDmaLen
);
683 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
696 DPRINTF(EthernetSM
, "receive kick rxState=%s (rxFifo.size=%d)\n",
697 RxStateStrings
[rxState
], rxFifo
.size());
699 if (rxKickTick
> curTick
) {
700 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
709 pioInterface
->respond(rxPioRequest
, curTick
);
716 rxState
= rxBeginCopy
;
720 if (rxFifo
.empty()) {
721 DPRINTF(EthernetSM
, "receive waiting for data. Nothing to do.\n");
725 // Grab a new packet from the fifo.
726 rxPacket
= rxFifo
.front();
727 rxPacketBufPtr
= rxPacket
->data
;
728 rxPktBytes
= rxPacket
->length
;
732 /* scope for variables */ {
735 rxDoneData
|= Regs::RxDone_IpPacket
;
737 if (cksum(ip
) != 0) {
738 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
739 rxDoneData
|= Regs::RxDone_IpError
;
744 rxDoneData
|= Regs::RxDone_TcpPacket
;
746 if (cksum(tcp
) != 0) {
747 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
748 rxDoneData
|= Regs::RxDone_TcpError
;
751 rxDoneData
|= Regs::RxDone_UdpPacket
;
753 if (cksum(udp
) != 0) {
754 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
755 rxDoneData
|= Regs::RxDone_UdpError
;
760 rxState
= rxBeginCopy
;
764 rxDmaAddr
= plat
->pciToDma(Regs::get_RxData_Addr(regs
.RxData
));
765 rxDmaLen
= min
<int>(Regs::get_RxData_Len(regs
.RxData
), rxPktBytes
);
766 rxDmaData
= rxPacketBufPtr
;
769 if (!dmaInterface
->busy()) {
770 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
,
771 curTick
, &rxDmaEvent
, true);
778 if (dmaWriteDelay
!= 0 || dmaWriteFactor
!= 0) {
779 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
780 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
781 rxDmaEvent
.schedule(start
);
789 DPRINTF(EthernetSM
, "receive machine still copying\n");
793 regs
.RxDone
= rxDoneData
| rxDmaLen
;
795 if (rxPktBytes
== rxDmaLen
) {
799 regs
.RxDone
|= Regs::RxDone_More
;
800 rxPktBytes
-= rxDmaLen
;
801 rxPacketBufPtr
+= rxDmaLen
;
804 regs
.RxDone
|= Regs::RxDone_Complete
;
805 devIntrPost(Regs::Intr_RxData
);
810 panic("Invalid rxState!");
813 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
814 RxStateStrings
[rxState
]);
820 * @todo do we want to schedule a future kick?
822 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
823 RxStateStrings
[rxState
]);
829 assert(txState
== txCopy
);
830 txState
= txCopyDone
;
831 physmem
->dma_read((uint8_t *)txDmaData
, txDmaAddr
, txDmaLen
);
832 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
833 txDmaAddr
, txDmaLen
);
834 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
847 if (txFifo
.empty()) {
848 DPRINTF(Ethernet
, "nothing to transmit\n");
852 PacketPtr packet
= txFifo
.front();
853 if (!interface
->sendPacket(packet
)) {
854 DPRINTF(Ethernet
, "Packet Transmit: failed txFifo available %d\n",
862 if (DTRACE(Ethernet
)) {
865 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
868 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
869 tcp
->sport(), tcp
->dport());
875 DDUMP(Ethernet
, packet
->data
, packet
->length
);
876 txBytes
+= packet
->length
;
879 DPRINTF(Ethernet
, "Packet Transmit: successful txFifo Available %d\n",
882 if (txFifo
.size() <= params()->tx_fifo_threshold
)
883 devIntrPost(Regs::Intr_TxFifo
);
885 devIntrPost(Regs::Intr_TxDone
);
888 if (!txFifo
.empty() && !txEvent
.scheduled()) {
889 DPRINTF(Ethernet
, "reschedule transmit\n");
890 txEvent
.schedule(curTick
+ retryTime
);
897 DPRINTF(EthernetSM
, "transmit kick txState=%s (txFifo.size=%d)\n",
898 TxStateStrings
[txState
], txFifo
.size());
900 if (txKickTick
> curTick
) {
901 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
910 pioInterface
->respond(txPioRequest
, curTick
+ pioLatency
);
917 // Grab a new packet from the fifo.
918 txPacket
= new PacketData(16384);
919 txPacketBufPtr
= txPacket
->data
;
922 if (txFifo
.avail() - txPacket
->length
<
923 Regs::get_TxData_Len(regs
.TxData
)) {
924 DPRINTF(EthernetSM
, "transmit fifo full. Nothing to do.\n");
928 txState
= txBeginCopy
;
932 txDmaAddr
= plat
->pciToDma(Regs::get_TxData_Addr(regs
.TxData
));
933 txDmaLen
= Regs::get_TxData_Len(regs
.TxData
);
934 txDmaData
= txPacketBufPtr
;
937 if (!dmaInterface
->busy()) {
938 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
,
939 curTick
, &txDmaEvent
, true);
947 if (dmaReadDelay
!= 0 || dmaReadFactor
!= 0) {
948 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
949 Tick start
= curTick
+ dmaReadDelay
+ factor
;
950 txDmaEvent
.schedule(start
);
958 DPRINTF(EthernetSM
, "transmit machine still copying\n");
962 txPacket
->length
+= txDmaLen
;
963 if ((regs
.TxData
& Regs::TxData_More
)) {
964 txPacketBufPtr
+= txDmaLen
;
966 assert(txPacket
->length
<= txFifo
.avail());
967 if ((regs
.TxData
& Regs::TxData_Checksum
)) {
973 tcp
->sum(cksum(tcp
));
980 udp
->sum(cksum(udp
));
989 txFifo
.push(txPacket
);
994 regs
.TxDone
= txDmaLen
| Regs::TxDone_Complete
;
995 devIntrPost(Regs::Intr_TxData
);
1000 panic("Invalid txState!");
1003 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1004 TxStateStrings
[txState
]);
1010 * @todo do we want to schedule a future kick?
1012 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1013 TxStateStrings
[txState
]);
1017 Device::transferDone()
1019 if (txFifo
.empty()) {
1020 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1024 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1026 if (txEvent
.scheduled())
1027 txEvent
.reschedule(curTick
+ cycles(1));
1029 txEvent
.schedule(curTick
+ cycles(1));
1033 Device::rxFilter(const PacketPtr
&packet
)
1035 if (!Regs::get_Config_Filter(regs
.Config
))
1038 panic("receive filter not implemented\n");
1044 EthHdr
*eth
= packet
->eth();
1045 if (eth
->unicast()) {
1046 // If we're accepting all unicast addresses
1050 // If we make a perfect match
1051 if (acceptPerfect
&& params
->eaddr
== eth
.dst())
1054 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
1057 } else if (eth
->broadcast()) {
1058 // if we're accepting broadcasts
1059 if (acceptBroadcast
)
1062 } else if (eth
->multicast()) {
1063 // if we're accepting all multicasts
1064 if (acceptMulticast
)
1070 DPRINTF(Ethernet
, "rxFilter drop\n");
1071 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1078 Device::recvPacket(PacketPtr packet
)
1080 rxBytes
+= packet
->length
;
1083 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifo Available is %d\n",
1087 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1088 interface
->recvDone();
1092 if (rxFilter(packet
)) {
1093 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1094 interface
->recvDone();
1098 if (rxFifo
.size() >= params()->rx_fifo_threshold
)
1099 devIntrPost(Regs::Intr_RxFifo
);
1101 if (!rxFifo
.push(packet
)) {
1103 "packet will not fit in receive buffer...packet dropped\n");
1107 interface
->recvDone();
1108 devIntrPost(Regs::Intr_RxDone
);
1113 //=====================================================================
1117 Base::serialize(ostream
&os
)
1119 // Serialize the PciDev base class
1120 PciDev::serialize(os
);
1122 SERIALIZE_SCALAR(rxEnable
);
1123 SERIALIZE_SCALAR(txEnable
);
1124 SERIALIZE_SCALAR(cpuIntrEnable
);
1127 * Keep track of pending interrupt status.
1129 SERIALIZE_SCALAR(intrTick
);
1130 SERIALIZE_SCALAR(cpuPendingIntr
);
1131 Tick intrEventTick
= 0;
1133 intrEventTick
= intrEvent
->when();
1134 SERIALIZE_SCALAR(intrEventTick
);
1138 Base::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1140 // Unserialize the PciDev base class
1141 PciDev::unserialize(cp
, section
);
1143 UNSERIALIZE_SCALAR(rxEnable
);
1144 UNSERIALIZE_SCALAR(txEnable
);
1145 UNSERIALIZE_SCALAR(cpuIntrEnable
);
1148 * Keep track of pending interrupt status.
1150 UNSERIALIZE_SCALAR(intrTick
);
1151 UNSERIALIZE_SCALAR(cpuPendingIntr
);
1153 UNSERIALIZE_SCALAR(intrEventTick
);
1154 if (intrEventTick
) {
1155 intrEvent
= new IntrEvent(this, true);
1156 intrEvent
->schedule(intrEventTick
);
1161 Device::serialize(ostream
&os
)
1163 // Serialize the PciDev base class
1164 Base::serialize(os
);
1166 if (rxDmaEvent
.scheduled())
1169 if (txDmaEvent
.scheduled())
1173 * Serialize the device registers
1175 SERIALIZE_SCALAR(regs
.Config
);
1176 SERIALIZE_SCALAR(regs
.RxMaxCopy
);
1177 SERIALIZE_SCALAR(regs
.TxMaxCopy
);
1178 SERIALIZE_SCALAR(regs
.RxThreshold
);
1179 SERIALIZE_SCALAR(regs
.TxThreshold
);
1180 SERIALIZE_SCALAR(regs
.IntrStatus
);
1181 SERIALIZE_SCALAR(regs
.IntrMask
);
1182 SERIALIZE_SCALAR(regs
.RxData
);
1183 SERIALIZE_SCALAR(regs
.RxDone
);
1184 SERIALIZE_SCALAR(regs
.TxData
);
1185 SERIALIZE_SCALAR(regs
.TxDone
);
1188 * Serialize rx state machine
1190 int rxState
= this->rxState
;
1191 SERIALIZE_SCALAR(rxState
);
1192 rxFifo
.serialize("rxFifo", os
);
1193 bool rxPacketExists
= rxPacket
;
1194 SERIALIZE_SCALAR(rxPacketExists
);
1195 if (rxPacketExists
) {
1196 rxPacket
->serialize("rxPacket", os
);
1197 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
1198 SERIALIZE_SCALAR(rxPktBufPtr
);
1199 SERIALIZE_SCALAR(rxPktBytes
);
1201 SERIALIZE_SCALAR(rxDoneData
);
1204 * Serialize tx state machine
1206 int txState
= this->txState
;
1207 SERIALIZE_SCALAR(txState
);
1208 txFifo
.serialize("txFifo", os
);
1209 bool txPacketExists
= txPacket
;
1210 SERIALIZE_SCALAR(txPacketExists
);
1211 if (txPacketExists
) {
1212 txPacket
->serialize("txPacket", os
);
1213 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
1214 SERIALIZE_SCALAR(txPktBufPtr
);
1215 SERIALIZE_SCALAR(txPktBytes
);
1219 * If there's a pending transmit, store the time so we can
1220 * reschedule it later
1222 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
1223 SERIALIZE_SCALAR(transmitTick
);
1227 Device::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1229 // Unserialize the PciDev base class
1230 Base::unserialize(cp
, section
);
1233 * Unserialize the device registers
1235 UNSERIALIZE_SCALAR(regs
.Config
);
1236 UNSERIALIZE_SCALAR(regs
.RxMaxCopy
);
1237 UNSERIALIZE_SCALAR(regs
.TxMaxCopy
);
1238 UNSERIALIZE_SCALAR(regs
.RxThreshold
);
1239 UNSERIALIZE_SCALAR(regs
.TxThreshold
);
1240 UNSERIALIZE_SCALAR(regs
.IntrStatus
);
1241 UNSERIALIZE_SCALAR(regs
.IntrMask
);
1242 UNSERIALIZE_SCALAR(regs
.RxData
);
1243 UNSERIALIZE_SCALAR(regs
.RxDone
);
1244 UNSERIALIZE_SCALAR(regs
.TxData
);
1245 UNSERIALIZE_SCALAR(regs
.TxDone
);
1248 * Unserialize rx state machine
1251 UNSERIALIZE_SCALAR(rxState
);
1252 this->rxState
= (RxState
) rxState
;
1253 rxFifo
.unserialize("rxFifo", cp
, section
);
1254 bool rxPacketExists
;
1255 UNSERIALIZE_SCALAR(rxPacketExists
);
1257 if (rxPacketExists
) {
1258 rxPacket
= new PacketData(16384);
1259 rxPacket
->unserialize("rxPacket", cp
, section
);
1260 uint32_t rxPktBufPtr
;
1261 UNSERIALIZE_SCALAR(rxPktBufPtr
);
1262 this->rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
1263 UNSERIALIZE_SCALAR(rxPktBytes
);
1265 UNSERIALIZE_SCALAR(rxDoneData
);
1268 * Unserialize tx state machine
1271 UNSERIALIZE_SCALAR(txState
);
1272 this->txState
= (TxState
) txState
;
1273 txFifo
.unserialize("txFifo", cp
, section
);
1274 bool txPacketExists
;
1275 UNSERIALIZE_SCALAR(txPacketExists
);
1277 if (txPacketExists
) {
1278 txPacket
= new PacketData(16384);
1279 txPacket
->unserialize("txPacket", cp
, section
);
1280 uint32_t txPktBufPtr
;
1281 UNSERIALIZE_SCALAR(txPktBufPtr
);
1282 this->txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
1283 UNSERIALIZE_SCALAR(txPktBytes
);
1287 * If there's a pending transmit, reschedule it now
1290 UNSERIALIZE_SCALAR(transmitTick
);
1292 txEvent
.schedule(curTick
+ transmitTick
);
1295 * re-add addrRanges to bus bridges
1298 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
1302 Device::cacheAccess(MemReqPtr
&req
)
1304 //The mask is to give you only the offset into the device register file
1305 Addr daddr
= req
->paddr
- addr
;
1307 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
1310 Tick when
= curTick
+ pioLatency
;
1314 if (rxState
!= rxIdle
) {
1321 if (txState
!= txIdle
) {
1331 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1333 SimObjectParam
<EtherInt
*> peer
;
1334 SimObjectParam
<Device
*> device
;
1336 END_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1338 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface
)
1340 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1341 INIT_PARAM(device
, "Ethernet device of this interface")
1343 END_INIT_SIM_OBJECT_PARAMS(Interface
)
1345 CREATE_SIM_OBJECT(Interface
)
1347 Interface
*dev_int
= new Interface(getInstanceName(), device
);
1349 EtherInt
*p
= (EtherInt
*)peer
;
1351 dev_int
->setPeer(p
);
1352 p
->setPeer(dev_int
);
1358 REGISTER_SIM_OBJECT("SinicInt", Interface
)
1361 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device
)
1364 Param
<Tick
> cycle_time
;
1365 Param
<Tick
> tx_delay
;
1366 Param
<Tick
> rx_delay
;
1367 Param
<Tick
> intr_delay
;
1368 SimObjectParam
<MemoryController
*> mmu
;
1369 SimObjectParam
<PhysicalMemory
*> physmem
;
1370 Param
<bool> rx_filter
;
1371 Param
<string
> hardware_address
;
1372 SimObjectParam
<Bus
*> io_bus
;
1373 SimObjectParam
<Bus
*> payload_bus
;
1374 SimObjectParam
<HierParams
*> hier
;
1375 Param
<Tick
> pio_latency
;
1376 SimObjectParam
<PciConfigAll
*> configspace
;
1377 SimObjectParam
<PciConfigData
*> configdata
;
1378 SimObjectParam
<Platform
*> platform
;
1379 Param
<uint32_t> pci_bus
;
1380 Param
<uint32_t> pci_dev
;
1381 Param
<uint32_t> pci_func
;
1382 Param
<uint32_t> rx_max_copy
;
1383 Param
<uint32_t> tx_max_copy
;
1384 Param
<uint32_t> rx_fifo_size
;
1385 Param
<uint32_t> tx_fifo_size
;
1386 Param
<uint32_t> rx_fifo_threshold
;
1387 Param
<uint32_t> tx_fifo_threshold
;
1388 Param
<Tick
> dma_read_delay
;
1389 Param
<Tick
> dma_read_factor
;
1390 Param
<Tick
> dma_write_delay
;
1391 Param
<Tick
> dma_write_factor
;
1392 Param
<bool> dma_no_allocate
;
1394 END_DECLARE_SIM_OBJECT_PARAMS(Device
)
1396 BEGIN_INIT_SIM_OBJECT_PARAMS(Device
)
1398 INIT_PARAM(addr
, "Device Address"),
1399 INIT_PARAM(cycle_time
, "State machine cycle time"),
1400 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
1401 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
1402 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
1403 INIT_PARAM(mmu
, "Memory Controller"),
1404 INIT_PARAM(physmem
, "Physical Memory"),
1405 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
1406 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
1407 "00:99:00:00:00:01"),
1408 INIT_PARAM_DFLT(io_bus
, "The IO Bus to attach to for headers", NULL
),
1409 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
1410 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
1411 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
1412 INIT_PARAM(configspace
, "PCI Configspace"),
1413 INIT_PARAM(configdata
, "PCI Config data"),
1414 INIT_PARAM(platform
, "Platform"),
1415 INIT_PARAM(pci_bus
, "PCI bus"),
1416 INIT_PARAM(pci_dev
, "PCI device number"),
1417 INIT_PARAM(pci_func
, "PCI function code"),
1418 INIT_PARAM_DFLT(rx_max_copy
, "rx max copy", 16*1024),
1419 INIT_PARAM_DFLT(tx_max_copy
, "rx max copy", 16*1024),
1420 INIT_PARAM_DFLT(rx_fifo_size
, "max size in bytes of rxFifo", 64*1024),
1421 INIT_PARAM_DFLT(tx_fifo_size
, "max size in bytes of txFifo", 64*1024),
1422 INIT_PARAM_DFLT(rx_fifo_threshold
, "max size in bytes of rxFifo", 48*1024),
1423 INIT_PARAM_DFLT(tx_fifo_threshold
, "max size in bytes of txFifo", 16*1024),
1424 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
1425 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
1426 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
1427 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
1428 INIT_PARAM_DFLT(dma_no_allocate
, "Should we allocat on read in cache", true)
1430 END_INIT_SIM_OBJECT_PARAMS(Device
)
1433 CREATE_SIM_OBJECT(Device
)
1435 Device::Params
*params
= new Device::Params
;
1436 params
->name
= getInstanceName();
1437 params
->intr_delay
= intr_delay
;
1438 params
->physmem
= physmem
;
1439 params
->cycle_time
= cycle_time
;
1440 params
->tx_delay
= tx_delay
;
1441 params
->rx_delay
= rx_delay
;
1443 params
->hier
= hier
;
1444 params
->io_bus
= io_bus
;
1445 params
->payload_bus
= payload_bus
;
1446 params
->pio_latency
= pio_latency
;
1447 params
->configSpace
= configspace
;
1448 params
->configData
= configdata
;
1449 params
->plat
= platform
;
1450 params
->busNum
= pci_bus
;
1451 params
->deviceNum
= pci_dev
;
1452 params
->functionNum
= pci_func
;
1453 params
->rx_filter
= rx_filter
;
1454 params
->eaddr
= hardware_address
;
1455 params
->rx_max_copy
= rx_max_copy
;
1456 params
->tx_max_copy
= tx_max_copy
;
1457 params
->rx_fifo_size
= rx_fifo_size
;
1458 params
->tx_fifo_size
= tx_fifo_size
;
1459 params
->rx_fifo_threshold
= rx_fifo_threshold
;
1460 params
->tx_fifo_threshold
= tx_fifo_threshold
;
1461 params
->dma_read_delay
= dma_read_delay
;
1462 params
->dma_read_factor
= dma_read_factor
;
1463 params
->dma_write_delay
= dma_write_delay
;
1464 params
->dma_write_factor
= dma_write_factor
;
1465 params
->dma_no_allocate
= dma_no_allocate
;
1466 return new Device(params
);
1469 REGISTER_SIM_OBJECT("Sinic", Device
)
1471 /* namespace Sinic */ }