2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "base/inet.hh"
34 #include "cpu/exec_context.hh"
35 #include "cpu/intr_control.hh"
36 #include "dev/etherlink.hh"
37 #include "dev/sinic.hh"
38 #include "dev/pciconfigall.hh"
39 #include "mem/bus/bus.hh"
40 #include "mem/bus/dma_interface.hh"
41 #include "mem/bus/pio_interface.hh"
42 #include "mem/bus/pio_interface_impl.hh"
43 #include "mem/functional/memory_control.hh"
44 #include "mem/functional/physical.hh"
45 #include "sim/builder.hh"
46 #include "sim/debug.hh"
47 #include "sim/eventq.hh"
48 #include "sim/host.hh"
49 #include "sim/stats.hh"
50 #include "targetarch/vtophys.hh"
56 const char *RxStateStrings
[] =
65 const char *TxStateStrings
[] =
75 ///////////////////////////////////////////////////////////////////////
80 : PciDev(p
), rxEnable(false), txEnable(false), clock(p
->clock
),
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
+ ".pio", p
->hier
, p
->pio_bus
,
98 this, &Device::cacheAccess
);
99 pioLatency
= p
->pio_latency
* p
->pio_bus
->clockRate
;
104 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
109 dmaInterface
= new DMAInterface
<Bus
>(p
->name
+ ".dma",
113 } else if (p
->payload_bus
)
114 panic("must define a header bus if defining a payload bus");
116 pioDelayWrite
= p
->pio_delay_write
&& pioInterface
;
126 .name(name() + ".rxBytes")
127 .desc("Bytes Received")
132 .name(name() + ".rxBandwidth")
133 .desc("Receive Bandwidth (bits/s)")
139 .name(name() + ".rxPackets")
140 .desc("Number of Packets Received")
145 .name(name() + ".rxPPS")
146 .desc("Packet Reception Rate (packets/s)")
152 .name(name() + ".rxIpPackets")
153 .desc("Number of IP Packets Received")
158 .name(name() + ".rxTcpPackets")
159 .desc("Number of Packets Received")
164 .name(name() + ".rxUdpPackets")
165 .desc("Number of UDP Packets Received")
170 .name(name() + ".rxIpChecksums")
171 .desc("Number of rx IP Checksums done by device")
177 .name(name() + ".rxTcpChecksums")
178 .desc("Number of rx TCP Checksums done by device")
184 .name(name() + ".rxUdpChecksums")
185 .desc("Number of rx UDP Checksums done by device")
191 .name(name() + ".totBandwidth")
192 .desc("Total Bandwidth (bits/s)")
198 .name(name() + ".totPackets")
199 .desc("Total Packets")
205 .name(name() + ".totBytes")
212 .name(name() + ".totPPS")
213 .desc("Total Tranmission Rate (packets/s)")
219 .name(name() + ".txBytes")
220 .desc("Bytes Transmitted")
225 .name(name() + ".txBandwidth")
226 .desc("Transmit Bandwidth (bits/s)")
232 .name(name() + ".txPackets")
233 .desc("Number of Packets Transmitted")
238 .name(name() + ".txPPS")
239 .desc("Packet Tranmission Rate (packets/s)")
245 .name(name() + ".txIpPackets")
246 .desc("Number of IP Packets Transmitted")
251 .name(name() + ".txTcpPackets")
252 .desc("Number of TCP Packets Transmitted")
257 .name(name() + ".txUdpPackets")
258 .desc("Number of Packets Transmitted")
263 .name(name() + ".txIpChecksums")
264 .desc("Number of tx IP Checksums done by device")
270 .name(name() + ".txTcpChecksums")
271 .desc("Number of tx TCP Checksums done by device")
277 .name(name() + ".txUdpChecksums")
278 .desc("Number of tx UDP Checksums done by device")
283 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
284 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
285 totBandwidth
= txBandwidth
+ rxBandwidth
;
286 totBytes
= txBytes
+ rxBytes
;
287 totPackets
= txPackets
+ rxPackets
;
288 txPacketRate
= txPackets
/ simSeconds
;
289 rxPacketRate
= rxPackets
/ simSeconds
;
293 * This is to write to the PCI general configuration registers
296 Device::writeConfig(int offset
, int size
, const uint8_t *data
)
299 case PCI0_BASE_ADDR0
:
300 // Need to catch writes to BARs to update the PIO interface
301 PciDev::writeConfig(offset
, size
, data
);
302 if (BARAddrs
[0] != 0) {
304 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
306 BARAddrs
[0] &= EV5::PAddrUncachedMask
;
311 PciDev::writeConfig(offset
, size
, data
);
316 Device::prepareIO(int cpu
)
318 if (cpu
>= writeQueue
.size())
319 writeQueue
.resize(cpu
+ 1);
323 Device::prepareRead(int cpu
)
325 using namespace Regs
;
327 // update rx registers
328 regs
.RxDone
= set_RxDone_Packets(regs
.RxDone
, rxFifo
.packets());
329 regs
.RxWait
= regs
.RxDone
;
331 // update tx regsiters
332 regs
.TxDone
= set_TxDone_Packets(regs
.TxDone
, txFifo
.packets());
333 regs
.TxDone
= set_TxDone_Full(regs
.TxDone
,
334 txFifo
.avail() < regs
.TxMaxCopy
);
335 regs
.TxDone
= set_TxDone_Low(regs
.TxDone
,
336 txFifo
.size() < regs
.TxFifoMark
);
337 regs
.TxWait
= regs
.TxDone
;
341 Device::prepareWrite(int cpu
)
347 * I/O read of device register
350 Device::read(MemReqPtr
&req
, uint8_t *data
)
352 assert(config
.command
& PCI_CMD_MSE
);
353 Fault fault
= readBar(req
, data
);
355 if (fault
== Machine_Check_Fault
) {
356 panic("address does not map to a BAR pa=%#x va=%#x size=%d",
357 req
->paddr
, req
->vaddr
, req
->size
);
359 return Machine_Check_Fault
;
366 Device::readBar0(MemReqPtr
&req
, Addr daddr
, uint8_t *data
)
368 int cpu
= (req
->xc
->regs
.ipr
[TheISA::IPR_PALtemp16
] >> 8) & 0xff;
370 if (!regValid(daddr
))
371 panic("invalid register: cpu=%d, da=%#x pa=%#x va=%#x size=%d",
372 cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
374 const Regs::Info
&info
= regInfo(daddr
);
376 panic("reading %s (write only): cpu=%d da=%#x pa=%#x va=%#x size=%d",
377 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
379 if (req
->size
!= info
.size
)
380 panic("invalid size for reg %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
381 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
386 if (req
->size
== 4) {
387 uint32_t ®
= *(uint32_t *)data
;
388 reg
= regData32(daddr
);
392 if (req
->size
== 8) {
393 uint64_t ®
= *(uint64_t *)data
;
394 reg
= regData64(daddr
);
399 "read %s cpu=%d da=%#x pa=%#x va=%#x size=%d val=%#x\n",
400 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
, value
);
402 // reading the interrupt status register has the side effect of
404 if (daddr
== Regs::IntrStatus
)
411 * IPR read of device register
414 Device::iprRead(Addr daddr
, int cpu
, uint64_t &result
)
416 if (!regValid(daddr
))
417 panic("invalid address: da=%#x", daddr
);
419 const Regs::Info
&info
= regInfo(daddr
);
421 panic("reading %s (write only): cpu=%d da=%#x", info
.name
, cpu
, daddr
);
423 DPRINTF(EthernetPIO
, "IPR read %s: cpu=%d da=%#x\n",
424 info
.name
, cpu
, daddr
);
429 result
= regData32(daddr
);
432 result
= regData64(daddr
);
434 DPRINTF(EthernetPIO
, "IPR read %s: cpu=%s da=%#x val=%#x\n",
435 info
.name
, cpu
, result
);
441 * I/O write of device register
444 Device::write(MemReqPtr
&req
, const uint8_t *data
)
446 assert(config
.command
& PCI_CMD_MSE
);
447 Fault fault
= writeBar(req
, data
);
449 if (fault
== Machine_Check_Fault
) {
450 panic("address does not map to a BAR pa=%#x va=%#x size=%d",
451 req
->paddr
, req
->vaddr
, req
->size
);
453 return Machine_Check_Fault
;
460 Device::writeBar0(MemReqPtr
&req
, Addr daddr
, const uint8_t *data
)
462 int cpu
= (req
->xc
->regs
.ipr
[TheISA::IPR_PALtemp16
] >> 8) & 0xff;
464 if (!regValid(daddr
))
465 panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d",
466 cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
468 const Regs::Info
&info
= regInfo(daddr
);
470 panic("writing %s (read only): cpu=%d da=%#x", info
.name
, cpu
, daddr
);
472 if (req
->size
!= info
.size
)
473 panic("invalid size for %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
474 info
.name
, cpu
, daddr
, req
->paddr
, req
->vaddr
, req
->size
);
476 uint32_t reg32
= *(uint32_t *)data
;
477 uint64_t reg64
= *(uint64_t *)data
;
479 "write %s: cpu=%d val=%#x da=%#x pa=%#x va=%#x size=%d\n",
480 info
.name
, cpu
, info
.size
== 4 ? reg32
: reg64
, daddr
,
481 req
->paddr
, req
->vaddr
, req
->size
);
485 writeQueue
[cpu
].push_back(RegWriteData(daddr
, reg64
));
487 if (!pioDelayWrite
|| !info
.delay_write
)
488 regWrite(daddr
, cpu
, data
);
494 Device::regWrite(Addr daddr
, int cpu
, const uint8_t *data
)
496 uint32_t reg32
= *(uint32_t *)data
;
497 uint64_t reg64
= *(uint64_t *)data
;
508 case Regs::IntrStatus
:
509 devIntrClear(regs
.IntrStatus
& reg32
);
513 devIntrChangeMask(reg32
);
517 if (rxState
!= rxIdle
)
518 panic("receive machine busy with another request! rxState=%s",
519 RxStateStrings
[rxState
]);
521 regs
.RxDone
= Regs::RxDone_Busy
;
524 rxState
= rxFifoBlock
;
530 if (txState
!= txIdle
)
531 panic("transmit machine busy with another request! txState=%s",
532 TxStateStrings
[txState
]);
534 regs
.TxDone
= Regs::TxDone_Busy
;
537 txState
= txFifoBlock
;
545 Device::devIntrPost(uint32_t interrupts
)
547 if ((interrupts
& Regs::Intr_Res
))
548 panic("Cannot set a reserved interrupt");
550 regs
.IntrStatus
|= interrupts
;
552 DPRINTF(EthernetIntr
,
553 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
554 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
556 interrupts
= regs
.IntrStatus
& regs
.IntrMask
;
558 // Intr_RxHigh is special, we only signal it if we've emptied the fifo
559 // and then filled it above the high watermark
563 interrupts
&= ~Regs::Intr_RxHigh
;
565 // Intr_TxLow is special, we only signal it if we've filled up the fifo
566 // and then dropped below the low watermark
570 interrupts
&= ~Regs::Intr_TxLow
;
574 if ((interrupts
& Regs::Intr_NoDelay
) == 0)
581 Device::devIntrClear(uint32_t interrupts
)
583 if ((interrupts
& Regs::Intr_Res
))
584 panic("Cannot clear a reserved interrupt");
586 regs
.IntrStatus
&= ~interrupts
;
588 DPRINTF(EthernetIntr
,
589 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
590 interrupts
, regs
.IntrStatus
, regs
.IntrMask
);
592 if (!(regs
.IntrStatus
& regs
.IntrMask
))
597 Device::devIntrChangeMask(uint32_t newmask
)
599 if (regs
.IntrMask
== newmask
)
602 regs
.IntrMask
= newmask
;
604 DPRINTF(EthernetIntr
,
605 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
606 regs
.IntrStatus
, regs
.IntrMask
, regs
.IntrStatus
& regs
.IntrMask
);
608 if (regs
.IntrStatus
& regs
.IntrMask
)
609 cpuIntrPost(curTick
);
615 Base::cpuIntrPost(Tick when
)
617 // If the interrupt you want to post is later than an interrupt
618 // already scheduled, just let it post in the coming one and don't
620 // HOWEVER, must be sure that the scheduled intrTick is in the
621 // future (this was formerly the source of a bug)
623 * @todo this warning should be removed and the intrTick code should
626 assert(when
>= curTick
);
627 assert(intrTick
>= curTick
|| intrTick
== 0);
628 if (!cpuIntrEnable
) {
629 DPRINTF(EthernetIntr
, "interrupts not enabled.\n",
634 if (when
> intrTick
&& intrTick
!= 0) {
635 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
641 if (intrTick
< curTick
) {
646 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
651 intrEvent
= new IntrEvent(this, true);
652 intrEvent
->schedule(intrTick
);
658 assert(intrTick
== curTick
);
660 // Whether or not there's a pending interrupt, we don't care about
665 // Don't send an interrupt if there's already one
666 if (cpuPendingIntr
) {
667 DPRINTF(EthernetIntr
,
668 "would send an interrupt now, but there's already pending\n");
671 cpuPendingIntr
= true;
673 DPRINTF(EthernetIntr
, "posting interrupt\n");
691 cpuPendingIntr
= false;
693 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
698 Base::cpuIntrPending() const
699 { return cpuPendingIntr
; }
702 Device::changeConfig(uint32_t newconf
)
704 uint32_t changed
= regs
.Config
^ newconf
;
708 regs
.Config
= newconf
;
710 if ((changed
& Regs::Config_IntEn
)) {
711 cpuIntrEnable
= regs
.Config
& Regs::Config_IntEn
;
713 if (regs
.IntrStatus
& regs
.IntrMask
)
714 cpuIntrPost(curTick
);
720 if ((changed
& Regs::Config_TxEn
)) {
721 txEnable
= regs
.Config
& Regs::Config_TxEn
;
726 if ((changed
& Regs::Config_RxEn
)) {
727 rxEnable
= regs
.Config
& Regs::Config_RxEn
;
734 Device::command(uint32_t command
)
736 if (command
& Regs::Command_Reset
)
743 using namespace Regs
;
745 memset(®s
, 0, sizeof(regs
));
748 if (params()->dedicated
)
749 regs
.Config
|= Config_Thread
;
750 regs
.IntrMask
= Intr_RxHigh
| Intr_RxDMA
| Intr_TxLow
;
751 regs
.RxMaxCopy
= params()->rx_max_copy
;
752 regs
.TxMaxCopy
= params()->tx_max_copy
;
753 regs
.RxMaxIntr
= params()->rx_max_intr
;
754 regs
.RxFifoSize
= params()->rx_fifo_size
;
755 regs
.TxFifoSize
= params()->tx_fifo_size
;
756 regs
.RxFifoMark
= params()->rx_fifo_threshold
;
757 regs
.TxFifoMark
= params()->tx_fifo_threshold
;
758 regs
.HwAddr
= params()->eaddr
;
772 assert(rxState
== rxCopy
);
773 rxState
= rxCopyDone
;
774 physmem
->dma_write(rxDmaAddr
, (uint8_t *)rxDmaData
, rxDmaLen
);
775 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
776 rxDmaAddr
, rxDmaLen
);
777 DDUMP(EthernetData
, rxDmaData
, rxDmaLen
);
785 // If the transmit state machine has a pending DMA, let it go first
786 if (txState
== txBeginCopy
)
795 DPRINTF(EthernetSM
, "receive kick rxState=%s (rxFifo.size=%d)\n",
796 RxStateStrings
[rxState
], rxFifo
.size());
798 if (rxKickTick
> curTick
) {
799 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
811 rxState
= rxBeginCopy
;
815 if (rxFifo
.empty()) {
816 DPRINTF(EthernetSM
, "receive waiting for data. Nothing to do.\n");
820 // Grab a new packet from the fifo.
821 rxPacket
= rxFifo
.front();
822 rxPacketBufPtr
= rxPacket
->data
;
823 rxPktBytes
= rxPacket
->length
;
827 /* scope for variables */ {
830 rxDoneData
|= Regs::RxDone_IpPacket
;
832 if (cksum(ip
) != 0) {
833 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
834 rxDoneData
|= Regs::RxDone_IpError
;
839 rxDoneData
|= Regs::RxDone_TcpPacket
;
841 if (cksum(tcp
) != 0) {
842 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
843 rxDoneData
|= Regs::RxDone_TcpError
;
846 rxDoneData
|= Regs::RxDone_UdpPacket
;
848 if (cksum(udp
) != 0) {
849 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
850 rxDoneData
|= Regs::RxDone_UdpError
;
855 rxState
= rxBeginCopy
;
859 if (dmaInterface
&& dmaInterface
->busy())
862 rxDmaAddr
= plat
->pciToDma(Regs::get_RxData_Addr(regs
.RxData
));
863 rxDmaLen
= min
<int>(Regs::get_RxData_Len(regs
.RxData
), rxPktBytes
);
864 rxDmaData
= rxPacketBufPtr
;
868 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
,
869 curTick
, &rxDmaEvent
, true);
873 if (dmaWriteDelay
!= 0 || dmaWriteFactor
!= 0) {
874 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
875 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
876 rxDmaEvent
.schedule(start
);
884 DPRINTF(EthernetSM
, "receive machine still copying\n");
888 regs
.RxDone
= rxDoneData
| rxDmaLen
;
890 if (rxPktBytes
== rxDmaLen
) {
894 regs
.RxDone
|= Regs::RxDone_More
;
895 rxPktBytes
-= rxDmaLen
;
896 rxPacketBufPtr
+= rxDmaLen
;
899 regs
.RxDone
|= Regs::RxDone_Complete
;
900 devIntrPost(Regs::Intr_RxDMA
);
905 panic("Invalid rxState!");
908 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
909 RxStateStrings
[rxState
]);
915 * @todo do we want to schedule a future kick?
917 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
918 RxStateStrings
[rxState
]);
924 assert(txState
== txCopy
);
925 txState
= txCopyDone
;
926 physmem
->dma_read((uint8_t *)txDmaData
, txDmaAddr
, txDmaLen
);
927 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
928 txDmaAddr
, txDmaLen
);
929 DDUMP(EthernetData
, txDmaData
, txDmaLen
);
937 // If the receive state machine has a pending DMA, let it go first
938 if (rxState
== rxBeginCopy
)
947 if (txFifo
.empty()) {
948 DPRINTF(Ethernet
, "nothing to transmit\n");
953 PacketPtr packet
= txFifo
.front();
954 if (!interface
->sendPacket(packet
)) {
955 DPRINTF(Ethernet
, "Packet Transmit: failed txFifo available %d\n",
962 if (DTRACE(Ethernet
)) {
965 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
968 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
969 tcp
->sport(), tcp
->dport());
975 DDUMP(EthernetData
, packet
->data
, packet
->length
);
976 txBytes
+= packet
->length
;
979 DPRINTF(Ethernet
, "Packet Transmit: successful txFifo Available %d\n",
982 interrupts
= Regs::Intr_TxPacket
;
983 if (txFifo
.size() < regs
.TxFifoMark
)
984 interrupts
|= Regs::Intr_TxLow
;
985 devIntrPost(interrupts
);
988 if (!txFifo
.empty() && !txEvent
.scheduled()) {
989 DPRINTF(Ethernet
, "reschedule transmit\n");
990 txEvent
.schedule(curTick
+ retryTime
);
997 DPRINTF(EthernetSM
, "transmit kick txState=%s (txFifo.size=%d)\n",
998 TxStateStrings
[txState
], txFifo
.size());
1000 if (txKickTick
> curTick
) {
1001 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
1013 // Grab a new packet from the fifo.
1014 txPacket
= new PacketData(16384);
1015 txPacketBufPtr
= txPacket
->data
;
1018 if (txFifo
.avail() - txPacket
->length
<
1019 Regs::get_TxData_Len(regs
.TxData
)) {
1020 DPRINTF(EthernetSM
, "transmit fifo full. Nothing to do.\n");
1024 txState
= txBeginCopy
;
1028 if (dmaInterface
&& dmaInterface
->busy())
1031 txDmaAddr
= plat
->pciToDma(Regs::get_TxData_Addr(regs
.TxData
));
1032 txDmaLen
= Regs::get_TxData_Len(regs
.TxData
);
1033 txDmaData
= txPacketBufPtr
;
1037 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
,
1038 curTick
, &txDmaEvent
, true);
1042 if (dmaReadDelay
!= 0 || dmaReadFactor
!= 0) {
1043 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1044 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1045 txDmaEvent
.schedule(start
);
1053 DPRINTF(EthernetSM
, "transmit machine still copying\n");
1057 txPacket
->length
+= txDmaLen
;
1058 if ((regs
.TxData
& Regs::TxData_More
)) {
1059 txPacketBufPtr
+= txDmaLen
;
1061 assert(txPacket
->length
<= txFifo
.avail());
1062 if ((regs
.TxData
& Regs::TxData_Checksum
)) {
1068 tcp
->sum(cksum(tcp
));
1075 udp
->sum(cksum(udp
));
1084 txFifo
.push(txPacket
);
1085 if (txFifo
.avail() < regs
.TxMaxCopy
) {
1086 devIntrPost(Regs::Intr_TxFull
);
1093 regs
.TxDone
= txDmaLen
| Regs::TxDone_Complete
;
1094 devIntrPost(Regs::Intr_TxDMA
);
1099 panic("Invalid txState!");
1102 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1103 TxStateStrings
[txState
]);
1109 * @todo do we want to schedule a future kick?
1111 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1112 TxStateStrings
[txState
]);
1116 Device::transferDone()
1118 if (txFifo
.empty()) {
1119 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1123 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1125 if (txEvent
.scheduled())
1126 txEvent
.reschedule(curTick
+ cycles(1));
1128 txEvent
.schedule(curTick
+ cycles(1));
1132 Device::rxFilter(const PacketPtr
&packet
)
1134 if (!Regs::get_Config_Filter(regs
.Config
))
1137 panic("receive filter not implemented\n");
1143 EthHdr
*eth
= packet
->eth();
1144 if (eth
->unicast()) {
1145 // If we're accepting all unicast addresses
1149 // If we make a perfect match
1150 if (acceptPerfect
&& params
->eaddr
== eth
.dst())
1153 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
1156 } else if (eth
->broadcast()) {
1157 // if we're accepting broadcasts
1158 if (acceptBroadcast
)
1161 } else if (eth
->multicast()) {
1162 // if we're accepting all multicasts
1163 if (acceptMulticast
)
1169 DPRINTF(Ethernet
, "rxFilter drop\n");
1170 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1177 Device::recvPacket(PacketPtr packet
)
1179 rxBytes
+= packet
->length
;
1182 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifo Available is %d\n",
1186 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1190 if (rxFilter(packet
)) {
1191 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1195 if (rxFifo
.size() >= regs
.RxFifoMark
)
1196 devIntrPost(Regs::Intr_RxHigh
);
1198 if (!rxFifo
.push(packet
)) {
1200 "packet will not fit in receive buffer...packet dropped\n");
1204 devIntrPost(Regs::Intr_RxPacket
);
1209 //=====================================================================
1213 Base::serialize(ostream
&os
)
1215 // Serialize the PciDev base class
1216 PciDev::serialize(os
);
1218 SERIALIZE_SCALAR(rxEnable
);
1219 SERIALIZE_SCALAR(txEnable
);
1220 SERIALIZE_SCALAR(cpuIntrEnable
);
1223 * Keep track of pending interrupt status.
1225 SERIALIZE_SCALAR(intrTick
);
1226 SERIALIZE_SCALAR(cpuPendingIntr
);
1227 Tick intrEventTick
= 0;
1229 intrEventTick
= intrEvent
->when();
1230 SERIALIZE_SCALAR(intrEventTick
);
1234 Base::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1236 // Unserialize the PciDev base class
1237 PciDev::unserialize(cp
, section
);
1239 UNSERIALIZE_SCALAR(rxEnable
);
1240 UNSERIALIZE_SCALAR(txEnable
);
1241 UNSERIALIZE_SCALAR(cpuIntrEnable
);
1244 * Keep track of pending interrupt status.
1246 UNSERIALIZE_SCALAR(intrTick
);
1247 UNSERIALIZE_SCALAR(cpuPendingIntr
);
1249 UNSERIALIZE_SCALAR(intrEventTick
);
1250 if (intrEventTick
) {
1251 intrEvent
= new IntrEvent(this, true);
1252 intrEvent
->schedule(intrEventTick
);
1257 Device::serialize(ostream
&os
)
1259 // Serialize the PciDev base class
1260 Base::serialize(os
);
1262 if (rxState
== rxCopy
)
1263 panic("can't serialize with an in flight dma request rxState=%s",
1264 RxStateStrings
[rxState
]);
1266 if (txState
== txCopy
)
1267 panic("can't serialize with an in flight dma request txState=%s",
1268 TxStateStrings
[txState
]);
1271 * Serialize the device registers
1273 SERIALIZE_SCALAR(regs
.Config
);
1274 SERIALIZE_SCALAR(regs
.IntrStatus
);
1275 SERIALIZE_SCALAR(regs
.IntrMask
);
1276 SERIALIZE_SCALAR(regs
.RxMaxCopy
);
1277 SERIALIZE_SCALAR(regs
.TxMaxCopy
);
1278 SERIALIZE_SCALAR(regs
.RxMaxIntr
);
1279 SERIALIZE_SCALAR(regs
.RxData
);
1280 SERIALIZE_SCALAR(regs
.RxDone
);
1281 SERIALIZE_SCALAR(regs
.TxData
);
1282 SERIALIZE_SCALAR(regs
.TxDone
);
1285 * Serialize rx state machine
1287 int rxState
= this->rxState
;
1288 SERIALIZE_SCALAR(rxState
);
1289 SERIALIZE_SCALAR(rxEmpty
);
1290 rxFifo
.serialize("rxFifo", os
);
1291 bool rxPacketExists
= rxPacket
;
1292 SERIALIZE_SCALAR(rxPacketExists
);
1293 if (rxPacketExists
) {
1294 rxPacket
->serialize("rxPacket", os
);
1295 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
1296 SERIALIZE_SCALAR(rxPktBufPtr
);
1297 SERIALIZE_SCALAR(rxPktBytes
);
1299 SERIALIZE_SCALAR(rxDoneData
);
1302 * Serialize tx state machine
1304 int txState
= this->txState
;
1305 SERIALIZE_SCALAR(txState
);
1306 SERIALIZE_SCALAR(txFull
);
1307 txFifo
.serialize("txFifo", os
);
1308 bool txPacketExists
= txPacket
;
1309 SERIALIZE_SCALAR(txPacketExists
);
1310 if (txPacketExists
) {
1311 txPacket
->serialize("txPacket", os
);
1312 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
1313 SERIALIZE_SCALAR(txPktBufPtr
);
1314 SERIALIZE_SCALAR(txPktBytes
);
1318 * If there's a pending transmit, store the time so we can
1319 * reschedule it later
1321 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
1322 SERIALIZE_SCALAR(transmitTick
);
1326 Device::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1328 // Unserialize the PciDev base class
1329 Base::unserialize(cp
, section
);
1332 * Unserialize the device registers
1334 UNSERIALIZE_SCALAR(regs
.Config
);
1335 UNSERIALIZE_SCALAR(regs
.IntrStatus
);
1336 UNSERIALIZE_SCALAR(regs
.IntrMask
);
1337 UNSERIALIZE_SCALAR(regs
.RxMaxCopy
);
1338 UNSERIALIZE_SCALAR(regs
.TxMaxCopy
);
1339 UNSERIALIZE_SCALAR(regs
.RxMaxIntr
);
1340 UNSERIALIZE_SCALAR(regs
.RxData
);
1341 UNSERIALIZE_SCALAR(regs
.RxDone
);
1342 UNSERIALIZE_SCALAR(regs
.TxData
);
1343 UNSERIALIZE_SCALAR(regs
.TxDone
);
1346 * Unserialize rx state machine
1349 UNSERIALIZE_SCALAR(rxState
);
1350 UNSERIALIZE_SCALAR(rxEmpty
);
1351 this->rxState
= (RxState
) rxState
;
1352 rxFifo
.unserialize("rxFifo", cp
, section
);
1353 bool rxPacketExists
;
1354 UNSERIALIZE_SCALAR(rxPacketExists
);
1356 if (rxPacketExists
) {
1357 rxPacket
= new PacketData(16384);
1358 rxPacket
->unserialize("rxPacket", cp
, section
);
1359 uint32_t rxPktBufPtr
;
1360 UNSERIALIZE_SCALAR(rxPktBufPtr
);
1361 this->rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
1362 UNSERIALIZE_SCALAR(rxPktBytes
);
1364 UNSERIALIZE_SCALAR(rxDoneData
);
1367 * Unserialize tx state machine
1370 UNSERIALIZE_SCALAR(txState
);
1371 UNSERIALIZE_SCALAR(txFull
);
1372 this->txState
= (TxState
) txState
;
1373 txFifo
.unserialize("txFifo", cp
, section
);
1374 bool txPacketExists
;
1375 UNSERIALIZE_SCALAR(txPacketExists
);
1377 if (txPacketExists
) {
1378 txPacket
= new PacketData(16384);
1379 txPacket
->unserialize("txPacket", cp
, section
);
1380 uint32_t txPktBufPtr
;
1381 UNSERIALIZE_SCALAR(txPktBufPtr
);
1382 this->txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
1383 UNSERIALIZE_SCALAR(txPktBytes
);
1387 * If there's a pending transmit, reschedule it now
1390 UNSERIALIZE_SCALAR(transmitTick
);
1392 txEvent
.schedule(curTick
+ transmitTick
);
1395 * re-add addrRanges to bus bridges
1398 pioInterface
->addAddrRange(RangeSize(BARAddrs
[0], BARSize
[0]));
1399 pioInterface
->addAddrRange(RangeSize(BARAddrs
[1], BARSize
[1]));
1404 Device::cacheAccess(MemReqPtr
&req
)
1408 if (!getBAR(req
->paddr
, daddr
, bar
))
1409 panic("address does not map to a BAR pa=%#x va=%#x size=%d",
1410 req
->paddr
, req
->vaddr
, req
->size
);
1412 DPRINTF(EthernetPIO
, "timing %s to paddr=%#x bar=%d daddr=%#x\n",
1413 req
->cmd
.toString(), req
->paddr
, bar
, daddr
);
1415 if (!pioDelayWrite
|| !req
->cmd
.isWrite())
1416 return curTick
+ pioLatency
;
1419 int cpu
= (req
->xc
->regs
.ipr
[TheISA::IPR_PALtemp16
] >> 8) & 0xff;
1420 std::list
<RegWriteData
> &wq
= writeQueue
[cpu
];
1422 panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu
, daddr
);
1424 const RegWriteData
&data
= wq
.front();
1425 if (data
.daddr
!= daddr
)
1426 panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x",
1427 cpu
, data
.daddr
, daddr
);
1429 const Regs::Info
&info
= regInfo(data
.daddr
);
1430 if (info
.delay_write
)
1431 regWrite(daddr
, cpu
, (uint8_t *)&data
.value
);
1436 return curTick
+ pioLatency
;
1439 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1441 SimObjectParam
<EtherInt
*> peer
;
1442 SimObjectParam
<Device
*> device
;
1444 END_DECLARE_SIM_OBJECT_PARAMS(Interface
)
1446 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface
)
1448 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1449 INIT_PARAM(device
, "Ethernet device of this interface")
1451 END_INIT_SIM_OBJECT_PARAMS(Interface
)
1453 CREATE_SIM_OBJECT(Interface
)
1455 Interface
*dev_int
= new Interface(getInstanceName(), device
);
1457 EtherInt
*p
= (EtherInt
*)peer
;
1459 dev_int
->setPeer(p
);
1460 p
->setPeer(dev_int
);
1466 REGISTER_SIM_OBJECT("SinicInt", Interface
)
1469 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device
)
1474 SimObjectParam
<MemoryController
*> mmu
;
1475 SimObjectParam
<PhysicalMemory
*> physmem
;
1476 SimObjectParam
<PciConfigAll
*> configspace
;
1477 SimObjectParam
<PciConfigData
*> configdata
;
1478 SimObjectParam
<Platform
*> platform
;
1479 Param
<uint32_t> pci_bus
;
1480 Param
<uint32_t> pci_dev
;
1481 Param
<uint32_t> pci_func
;
1483 SimObjectParam
<HierParams
*> hier
;
1484 SimObjectParam
<Bus
*> pio_bus
;
1485 SimObjectParam
<Bus
*> dma_bus
;
1486 SimObjectParam
<Bus
*> payload_bus
;
1487 Param
<Tick
> dma_read_delay
;
1488 Param
<Tick
> dma_read_factor
;
1489 Param
<Tick
> dma_write_delay
;
1490 Param
<Tick
> dma_write_factor
;
1491 Param
<bool> dma_no_allocate
;
1492 Param
<Tick
> pio_latency
;
1493 Param
<bool> pio_delay_write
;
1494 Param
<Tick
> intr_delay
;
1496 Param
<Tick
> rx_delay
;
1497 Param
<Tick
> tx_delay
;
1498 Param
<uint32_t> rx_max_copy
;
1499 Param
<uint32_t> tx_max_copy
;
1500 Param
<uint32_t> rx_max_intr
;
1501 Param
<uint32_t> rx_fifo_size
;
1502 Param
<uint32_t> tx_fifo_size
;
1503 Param
<uint32_t> rx_fifo_threshold
;
1504 Param
<uint32_t> tx_fifo_threshold
;
1506 Param
<bool> rx_filter
;
1507 Param
<string
> hardware_address
;
1508 Param
<bool> dedicated
;
1510 END_DECLARE_SIM_OBJECT_PARAMS(Device
)
1512 BEGIN_INIT_SIM_OBJECT_PARAMS(Device
)
1514 INIT_PARAM(clock
, "State machine cycle time"),
1516 INIT_PARAM(addr
, "Device Address"),
1517 INIT_PARAM(mmu
, "Memory Controller"),
1518 INIT_PARAM(physmem
, "Physical Memory"),
1519 INIT_PARAM(configspace
, "PCI Configspace"),
1520 INIT_PARAM(configdata
, "PCI Config data"),
1521 INIT_PARAM(platform
, "Platform"),
1522 INIT_PARAM(pci_bus
, "PCI bus"),
1523 INIT_PARAM(pci_dev
, "PCI device number"),
1524 INIT_PARAM(pci_func
, "PCI function code"),
1526 INIT_PARAM(hier
, "Hierarchy global variables"),
1527 INIT_PARAM(pio_bus
, ""),
1528 INIT_PARAM(dma_bus
, ""),
1529 INIT_PARAM(payload_bus
, "The IO Bus to attach to for payload"),
1530 INIT_PARAM(dma_read_delay
, "fixed delay for dma reads"),
1531 INIT_PARAM(dma_read_factor
, "multiplier for dma reads"),
1532 INIT_PARAM(dma_write_delay
, "fixed delay for dma writes"),
1533 INIT_PARAM(dma_write_factor
, "multiplier for dma writes"),
1534 INIT_PARAM(dma_no_allocate
, "Should we allocat on read in cache"),
1535 INIT_PARAM(pio_latency
, "Programmed IO latency in bus cycles"),
1536 INIT_PARAM(pio_delay_write
, ""),
1537 INIT_PARAM(intr_delay
, "Interrupt Delay"),
1539 INIT_PARAM(rx_delay
, "Receive Delay"),
1540 INIT_PARAM(tx_delay
, "Transmit Delay"),
1541 INIT_PARAM(rx_max_copy
, "rx max copy"),
1542 INIT_PARAM(tx_max_copy
, "rx max copy"),
1543 INIT_PARAM(rx_max_intr
, "rx max intr"),
1544 INIT_PARAM(rx_fifo_size
, "max size in bytes of rxFifo"),
1545 INIT_PARAM(tx_fifo_size
, "max size in bytes of txFifo"),
1546 INIT_PARAM(rx_fifo_threshold
, "max size in bytes of rxFifo"),
1547 INIT_PARAM(tx_fifo_threshold
, "max size in bytes of txFifo"),
1549 INIT_PARAM(rx_filter
, "Enable Receive Filter"),
1550 INIT_PARAM(hardware_address
, "Ethernet Hardware Address"),
1551 INIT_PARAM(dedicated
, "dedicate a kernel thread to the driver")
1553 END_INIT_SIM_OBJECT_PARAMS(Device
)
1556 CREATE_SIM_OBJECT(Device
)
1558 Device::Params
*params
= new Device::Params
;
1560 params
->name
= getInstanceName();
1562 params
->clock
= clock
;
1565 params
->physmem
= physmem
;
1566 params
->configSpace
= configspace
;
1567 params
->configData
= configdata
;
1568 params
->plat
= platform
;
1569 params
->busNum
= pci_bus
;
1570 params
->deviceNum
= pci_dev
;
1571 params
->functionNum
= pci_func
;
1573 params
->hier
= hier
;
1574 params
->pio_bus
= pio_bus
;
1575 params
->header_bus
= dma_bus
;
1576 params
->payload_bus
= payload_bus
;
1577 params
->dma_read_delay
= dma_read_delay
;
1578 params
->dma_read_factor
= dma_read_factor
;
1579 params
->dma_write_delay
= dma_write_delay
;
1580 params
->dma_write_factor
= dma_write_factor
;
1581 params
->dma_no_allocate
= dma_no_allocate
;
1582 params
->pio_latency
= pio_latency
;
1583 params
->pio_delay_write
= pio_delay_write
;
1584 params
->intr_delay
= intr_delay
;
1586 params
->tx_delay
= tx_delay
;
1587 params
->rx_delay
= rx_delay
;
1588 params
->rx_max_copy
= rx_max_copy
;
1589 params
->tx_max_copy
= tx_max_copy
;
1590 params
->rx_max_intr
= rx_max_intr
;
1591 params
->rx_fifo_size
= rx_fifo_size
;
1592 params
->tx_fifo_size
= tx_fifo_size
;
1593 params
->rx_fifo_threshold
= rx_fifo_threshold
;
1594 params
->tx_fifo_threshold
= tx_fifo_threshold
;
1596 params
->rx_filter
= rx_filter
;
1597 params
->eaddr
= hardware_address
;
1598 params
->dedicated
= dedicated
;
1600 return new Device(params
);
1603 REGISTER_SIM_OBJECT("Sinic", Device
)
1605 /* namespace Sinic */ }