2 * Copyright (c) 2003 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.
30 * Device module for modelling the National Semiconductor
31 * DP83820 ethernet controller. Does not support priority queueing
37 #include "base/inet.hh"
38 #include "cpu/exec_context.hh"
39 #include "cpu/intr_control.hh"
41 #include "dev/ns_gige.hh"
42 #include "dev/etherlink.hh"
43 #include "mem/bus/bus.hh"
44 #include "mem/bus/dma_interface.hh"
45 #include "mem/bus/pio_interface.hh"
46 #include "mem/bus/pio_interface_impl.hh"
47 #include "mem/functional_mem/memory_control.hh"
48 #include "mem/functional_mem/physical_memory.hh"
49 #include "sim/builder.hh"
50 #include "sim/host.hh"
51 #include "sim/sim_stats.hh"
52 #include "targetarch/vtophys.hh"
53 #include "dev/pciconfigall.hh"
54 #include "dev/tsunami_cchip.hh"
56 const char *NsRxStateStrings
[] =
67 const char *NsTxStateStrings
[] =
78 const char *NsDmaState
[] =
89 ///////////////////////////////////////////////////////////////////////
91 // EtherDev PCI Device
93 EtherDev::EtherDev(const std::string
&name
, IntrControl
*i
, Tick intr_delay
,
94 PhysicalMemory
*pmem
, Tick tx_delay
, Tick rx_delay
,
95 MemoryController
*mmu
, HierParams
*hier
, Bus
*header_bus
,
96 Bus
*payload_bus
, Tick pio_latency
, bool dma_desc_free
,
97 bool dma_data_free
, Tick dma_read_delay
, Tick dma_write_delay
,
98 Tick dma_read_factor
, Tick dma_write_factor
, PciConfigAll
*cf
,
99 PciConfigData
*cd
, Tsunami
*t
, uint32_t bus
, uint32_t dev
,
100 uint32_t func
, bool rx_filter
, const int eaddr
[6], Addr addr
)
101 : PciDev(name
, mmu
, cf
, cd
, bus
, dev
, func
), tsunami(t
),
102 addr(addr
), txPacketBufPtr(NULL
), rxPacketBufPtr(NULL
),
103 txXferLen(0), rxXferLen(0), txPktXmitted(0), txState(txIdle
), CTDD(false),
104 txFifoCnt(0), txFifoAvail(MAX_TX_FIFO_SIZE
), txHalt(false),
105 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle
), rxState(rxIdle
),
106 CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false),
107 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle
), extstsEnable(false),
108 rxDmaReadEvent(this), rxDmaWriteEvent(this),
109 txDmaReadEvent(this), txDmaWriteEvent(this),
110 dmaDescFree(dma_desc_free
), dmaDataFree(dma_data_free
),
111 txDelay(tx_delay
), rxDelay(rx_delay
), rxKickTick(0), txKickTick(0),
112 txEvent(this), rxFilterEnable(rx_filter
), acceptBroadcast(false),
113 acceptMulticast(false), acceptUnicast(false),
114 acceptPerfect(false), acceptArp(false),
115 physmem(pmem
), intctrl(i
), intrTick(0),
116 cpuPendingIntr(false), intrEvent(0), interface(0), pioLatency(pio_latency
)
118 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
119 tsunami
->ethernet
= this;
122 pioInterface
= newPioInterface(name
, hier
, header_bus
, this,
123 &EtherDev::cacheAccess
);
124 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
126 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
127 header_bus
, payload_bus
, 1);
129 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
130 header_bus
, header_bus
, 1);
131 } else if (payload_bus
) {
132 pioInterface
= newPioInterface(name
, hier
, payload_bus
, this,
133 &EtherDev::cacheAccess
);
134 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
135 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
136 payload_bus
, payload_bus
, 1);
141 intrDelay
= US2Ticks(intr_delay
);
142 dmaReadDelay
= dma_read_delay
;
143 dmaWriteDelay
= dma_write_delay
;
144 dmaReadFactor
= dma_read_factor
;
145 dmaWriteFactor
= dma_write_factor
;
147 memset(®s
, 0, sizeof(regs
));
149 rom
.perfectMatch
[0] = eaddr
[0];
150 rom
.perfectMatch
[1] = eaddr
[1];
151 rom
.perfectMatch
[2] = eaddr
[2];
152 rom
.perfectMatch
[3] = eaddr
[3];
153 rom
.perfectMatch
[4] = eaddr
[4];
154 rom
.perfectMatch
[5] = eaddr
[5];
157 EtherDev::~EtherDev()
164 .name(name() + ".txBytes")
165 .desc("Bytes Transmitted")
170 .name(name() + ".rxBytes")
171 .desc("Bytes Received")
176 .name(name() + ".txPackets")
177 .desc("Number of Packets Transmitted")
182 .name(name() + ".rxPackets")
183 .desc("Number of Packets Received")
188 .name(name() + ".txBandwidth")
189 .desc("Transmit Bandwidth (bits/s)")
195 .name(name() + ".rxBandwidth")
196 .desc("Receive Bandwidth (bits/s)")
202 .name(name() + ".txPPS")
203 .desc("Packet Tranmission Rate (packets/s)")
209 .name(name() + ".rxPPS")
210 .desc("Packet Reception Rate (packets/s)")
215 txBandwidth
= txBytes
* Statistics::constant(8) / simSeconds
;
216 rxBandwidth
= rxBytes
* Statistics::constant(8) / simSeconds
;
217 txPacketRate
= txPackets
/ simSeconds
;
218 rxPacketRate
= rxPackets
/ simSeconds
;
222 * This is to read the PCI general configuration registers
225 EtherDev::ReadConfig(int offset
, int size
, uint8_t *data
)
227 if (offset
< PCI_DEVICE_SPECIFIC
)
228 PciDev::ReadConfig(offset
, size
, data
);
230 panic("need to do this\n");
235 * This is to write to the PCI general configuration registers
238 EtherDev::WriteConfig(int offset
, int size
, uint32_t data
)
240 if (offset
< PCI_DEVICE_SPECIFIC
)
241 PciDev::WriteConfig(offset
, size
, data
);
243 panic("Need to do that\n");
247 * This reads the device registers, which are detailed in the NS83820
251 EtherDev::read(MemReqPtr
&req
, uint8_t *data
)
253 //The mask is to give you only the offset into the device register file
254 Addr daddr
= req
->paddr
& 0xfff;
255 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x va=%#x size=%d\n",
256 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
259 //there are some reserved registers, you can see ns_gige_reg.h and
260 //the spec sheet for details
261 if (daddr
> LAST
&& daddr
<= RESERVED
) {
262 panic("Accessing reserved register");
263 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
264 ReadConfig(daddr
& 0xff, req
->size
, data
);
266 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
267 // don't implement all the MIB's. hopefully the kernel
268 // doesn't actually DEPEND upon their values
269 // MIB are just hardware stats keepers
270 uint32_t ®
= *(uint32_t *) data
;
273 } else if (daddr
> 0x3FC)
274 panic("Something is messed up!\n");
277 case sizeof(uint32_t):
279 uint32_t ®
= *(uint32_t *)data
;
284 //these are supposed to be cleared on a read
285 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
357 //see the spec sheet for how RFCR and RFDR work
358 //basically, you write to RFCR to tell the machine what you want to do next
359 //then you act upon RFDR, and the device will be prepared b/c
360 //of what you wrote to RFCR
366 DPRINTF(Ethernet
, "reading from RFDR\n");
367 switch (regs
.rfcr
& RFCR_RFADDR
) {
369 reg
= rom
.perfectMatch
[1];
371 reg
+= rom
.perfectMatch
[0];
374 reg
= rom
.perfectMatch
[3] << 8;
375 reg
+= rom
.perfectMatch
[2];
378 reg
= rom
.perfectMatch
[5] << 8;
379 reg
+= rom
.perfectMatch
[4];
382 panic("reading from RFDR for something for other than PMATCH!\n");
383 //didn't implement other RFDR functionality b/c driver didn't use
393 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
437 panic("reading unimplemented register: addr = %#x", daddr
);
440 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n", daddr
, reg
, reg
);
445 panic("accessing register with invalid size: addr=%#x, size=%d",
453 EtherDev::write(MemReqPtr
&req
, const uint8_t *data
)
455 Addr daddr
= req
->paddr
& 0xfff;
456 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x va=%#x size=%d\n",
457 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
459 if (daddr
> LAST
&& daddr
<= RESERVED
) {
460 panic("Accessing reserved register");
461 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
462 WriteConfig(daddr
& 0xff, req
->size
, *(uint32_t *)data
);
464 } else if (daddr
> 0x3FC)
465 panic("Something is messed up!\n");
467 if (req
->size
== sizeof(uint32_t)) {
468 uint32_t reg
= *(uint32_t *)data
;
469 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
474 if ((reg
& (CR_TXE
| CR_TXD
)) == (CR_TXE
| CR_TXD
)) {
476 } else if (reg
& CR_TXE
) {
477 //the kernel is enabling the transmit machine
478 if (txState
== txIdle
)
480 } else if (reg
& CR_TXD
) {
484 if ((reg
& (CR_RXE
| CR_RXD
)) == (CR_RXE
| CR_RXD
)) {
486 } else if (reg
& CR_RXE
) {
487 if (rxState
== rxIdle
) {
490 } else if (reg
& CR_RXD
) {
501 devIntrPost(ISR_SWI
);
512 if (reg
& CFG_LNKSTS
|| reg
& CFG_SPDSTS
|| reg
& CFG_DUPSTS
513 || reg
& CFG_RESERVED
|| reg
& CFG_T64ADDR
514 || reg
& CFG_PCI64_DET
)
515 panic("writing to read-only or reserved CFG bits!\n");
517 regs
.config
|= reg
& ~(CFG_LNKSTS
| CFG_SPDSTS
| CFG_DUPSTS
| CFG_RESERVED
|
518 CFG_T64ADDR
| CFG_PCI64_DET
);
520 // all these #if 0's are because i don't THINK the kernel needs to have these implemented
521 // if there is a problem relating to one of these, you may need to add functionality in
523 if (reg
& CFG_TBI_EN
) ;
524 if (reg
& CFG_MODE_1000
) ;
527 if (reg
& CFG_AUTO_1000
)
528 panic("CFG_AUTO_1000 not implemented!\n");
531 if (reg
& CFG_PINT_DUPSTS
|| reg
& CFG_PINT_LNKSTS
|| reg
& CFG_PINT_SPDSTS
) ;
532 if (reg
& CFG_TMRTEST
) ;
533 if (reg
& CFG_MRM_DIS
) ;
534 if (reg
& CFG_MWI_DIS
) ;
536 if (reg
& CFG_T64ADDR
)
537 panic("CFG_T64ADDR is read only register!\n");
539 if (reg
& CFG_PCI64_DET
)
540 panic("CFG_PCI64_DET is read only register!\n");
542 if (reg
& CFG_DATA64_EN
) ;
543 if (reg
& CFG_M64ADDR
) ;
544 if (reg
& CFG_PHY_RST
) ;
545 if (reg
& CFG_PHY_DIS
) ;
548 if (reg
& CFG_EXTSTS_EN
)
551 extstsEnable
= false;
554 if (reg
& CFG_REQALG
) ;
558 if (reg
& CFG_PESEL
) ;
559 if (reg
& CFG_BROM_DIS
) ;
560 if (reg
& CFG_EXT_125
) ;
567 /* since phy is completely faked, MEAR_MD* don't matter
568 and since the driver never uses MEAR_EE*, they don't matter */
570 if (reg
& MEAR_EEDI
) ;
571 if (reg
& MEAR_EEDO
) ; //this one is read only
572 if (reg
& MEAR_EECLK
) ;
573 if (reg
& MEAR_EESEL
) ;
574 if (reg
& MEAR_MDIO
) ;
575 if (reg
& MEAR_MDDIR
) ;
576 if (reg
& MEAR_MDC
) ;
581 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
582 /* these control BISTs for various parts of chip - we don't care or do
583 just fake that the BIST is done */
584 if (reg
& PTSCR_RBIST_EN
)
585 regs
.ptscr
|= PTSCR_RBIST_DONE
;
586 if (reg
& PTSCR_EEBIST_EN
)
587 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
588 if (reg
& PTSCR_EELOAD_EN
)
589 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
592 case ISR
: /* writing to the ISR has no effect */
593 panic("ISR is a read only register!\n");
606 /* not going to implement real interrupt holdoff */
610 regs
.txdp
= (reg
& 0xFFFFFFFC);
611 assert(txState
== txIdle
);
622 if (reg
& TXCFG_CSI
) ;
623 if (reg
& TXCFG_HBI
) ;
624 if (reg
& TXCFG_MLB
) ;
625 if (reg
& TXCFG_ATP
) ;
626 if (reg
& TXCFG_ECRETRY
) ; /* this could easily be implemented, but
627 considering the network is just a fake
628 pipe, wouldn't make sense to do this */
630 if (reg
& TXCFG_BRST_DIS
) ;
634 /* we handle our own DMA, ignore the kernel's exhortations */
635 if (reg
& TXCFG_MXDMA
) ;
641 /* these just control general purpose i/o pins, don't matter */
655 if (reg
& RXCFG_AEP
) ;
656 if (reg
& RXCFG_ARP
) ;
657 if (reg
& RXCFG_STRIPCRC
) ;
658 if (reg
& RXCFG_RX_RD
) ;
659 if (reg
& RXCFG_ALP
) ;
660 if (reg
& RXCFG_AIRL
) ;
663 /* we handle our own DMA, ignore what kernel says about it */
664 if (reg
& RXCFG_MXDMA
) ;
667 if (reg
& (RXCFG_DRTH
| RXCFG_DRTH0
)) ;
672 /* there is no priority queueing used in the linux 2.6 driver */
677 /* not going to implement wake on LAN */
682 /* not going to implement pause control */
688 DPRINTF(Ethernet
, "Writing to RFCR, RFADDR is %#x\n", reg
& RFCR_RFADDR
);
690 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
692 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
694 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
696 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
698 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
700 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
702 if (reg
& RFCR_APAT
) ;
703 // panic("RFCR_APAT not implemented!\n");
705 if (reg
& RFCR_MHEN
|| reg
& RFCR_UHEN
)
706 panic("hash filtering not implemented!\n");
709 panic("RFCR_ULM not implemented!\n");
714 panic("the driver never writes to RFDR, something is wrong!\n");
717 panic("the driver never uses BRAR, something is wrong!\n");
720 panic("the driver never uses BRDR, something is wrong!\n");
723 panic("SRR is read only register!\n");
726 panic("the driver never uses MIBC, something is wrong!\n");
737 panic("the driver never uses VDR, something is wrong!\n");
741 /* not going to implement clockrun stuff */
747 if (reg
& TBICR_MR_LOOPBACK
)
748 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
750 if (reg
& TBICR_MR_AN_ENABLE
) {
751 regs
.tanlpar
= regs
.tanar
;
752 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
756 if (reg
& TBICR_MR_RESTART_AN
) ;
762 panic("TBISR is read only register!\n");
767 panic("this isn't used in driver, something wrong!\n");
770 panic("this isn't used in driver, something wrong!\n");
774 panic("this should only be written to by the fake phy!\n");
777 panic("TANER is read only register!\n");
784 panic("thought i covered all the register, what is this? addr=%#x",
788 panic("Invalid Request Size");
794 EtherDev::devIntrPost(uint32_t interrupts
)
796 DPRINTF(Ethernet
, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
797 interrupts
, regs
.isr
, regs
.imr
);
801 if (interrupts
& ISR_RESERVE
)
802 panic("Cannot set a reserved interrupt");
804 if (interrupts
& ISR_TXRCMP
)
805 regs
.isr
|= ISR_TXRCMP
;
807 if (interrupts
& ISR_RXRCMP
)
808 regs
.isr
|= ISR_RXRCMP
;
810 //ISR_DPERR not implemented
811 //ISR_SSERR not implemented
812 //ISR_RMABT not implemented
813 //ISR_RXSOVR not implemented
814 //ISR_HIBINT not implemented
815 //ISR_PHY not implemented
816 //ISR_PME not implemented
818 if (interrupts
& ISR_SWI
)
821 //ISR_MIB not implemented
822 //ISR_TXURN not implemented
824 if (interrupts
& ISR_TXIDLE
)
825 regs
.isr
|= ISR_TXIDLE
;
827 if (interrupts
& ISR_TXERR
)
828 regs
.isr
|= ISR_TXERR
;
830 if (interrupts
& ISR_TXDESC
)
831 regs
.isr
|= ISR_TXDESC
;
833 if (interrupts
& ISR_TXOK
) {
834 regs
.isr
|= ISR_TXOK
;
838 if (interrupts
& ISR_RXORN
)
839 regs
.isr
|= ISR_RXORN
;
841 if (interrupts
& ISR_RXIDLE
)
842 regs
.isr
|= ISR_RXIDLE
;
844 //ISR_RXEARLY not implemented
846 if (interrupts
& ISR_RXERR
)
847 regs
.isr
|= ISR_RXERR
;
849 if (interrupts
& ISR_RXOK
) {
851 regs
.isr
|= ISR_RXOK
;
854 if ((regs
.isr
& regs
.imr
)) {
863 EtherDev::devIntrClear(uint32_t interrupts
)
865 DPRINTF(Ethernet
, "interrupt cleared intr=%x isr=%x imr=%x\n",
866 interrupts
, regs
.isr
, regs
.imr
);
868 if (interrupts
& ISR_RESERVE
)
869 panic("Cannot clear a reserved interrupt");
871 if (interrupts
& ISR_TXRCMP
)
872 regs
.isr
&= ~ISR_TXRCMP
;
874 if (interrupts
& ISR_RXRCMP
)
875 regs
.isr
&= ~ISR_RXRCMP
;
877 //ISR_DPERR not implemented
878 //ISR_SSERR not implemented
879 //ISR_RMABT not implemented
880 //ISR_RXSOVR not implemented
881 //ISR_HIBINT not implemented
882 //ISR_PHY not implemented
883 //ISR_PME not implemented
885 if (interrupts
& ISR_SWI
)
886 regs
.isr
&= ~ISR_SWI
;
888 //ISR_MIB not implemented
889 //ISR_TXURN not implemented
891 if (interrupts
& ISR_TXIDLE
)
892 regs
.isr
&= ~ISR_TXIDLE
;
894 if (interrupts
& ISR_TXERR
)
895 regs
.isr
&= ~ISR_TXERR
;
897 if (interrupts
& ISR_TXDESC
)
898 regs
.isr
&= ~ISR_TXDESC
;
900 if (interrupts
& ISR_TXOK
)
901 regs
.isr
&= ~ISR_TXOK
;
903 if (interrupts
& ISR_RXORN
)
904 regs
.isr
&= ~ISR_RXORN
;
906 if (interrupts
& ISR_RXIDLE
)
907 regs
.isr
&= ~ISR_RXIDLE
;
909 //ISR_RXEARLY not implemented
911 if (interrupts
& ISR_RXERR
)
912 regs
.isr
&= ~ISR_RXERR
;
914 if (interrupts
& ISR_RXOK
)
915 regs
.isr
&= ~ISR_RXOK
;
917 if (!(regs
.isr
& regs
.imr
))
922 EtherDev::devIntrChangeMask()
924 DPRINTF(Ethernet
, "interrupt mask changed\n");
926 if (regs
.isr
& regs
.imr
)
927 cpuIntrPost(curTick
);
933 EtherDev::cpuIntrPost(Tick when
)
935 if (when
> intrTick
&& intrTick
!= 0)
945 if (when
< curTick
) {
948 intrEvent
= new IntrEvent(this, true);
949 intrEvent
->schedule(intrTick
);
954 EtherDev::cpuInterrupt()
956 // Don't send an interrupt if there's already one
960 // Don't send an interrupt if it's supposed to be delayed
961 if (intrTick
> curTick
)
964 // Whether or not there's a pending interrupt, we don't care about
970 cpuPendingIntr
= true;
971 /** @todo rework the intctrl to be tsunami ok */
972 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
973 tsunami
->cchip
->postDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
977 EtherDev::cpuIntrClear()
979 if (cpuPendingIntr
) {
980 cpuPendingIntr
= false;
981 /** @todo rework the intctrl to be tsunami ok */
982 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
983 tsunami
->cchip
->clearDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
988 EtherDev::cpuIntrPending() const
989 { return cpuPendingIntr
; }
995 DPRINTF(Ethernet
, "transmit reset\n");
999 txFifoAvail
= MAX_TX_FIFO_SIZE
;
1002 assert(txDescCnt
== 0);
1004 regs
.command
&= ~CR_TXE
;
1006 assert(txDmaState
== dmaIdle
);
1012 DPRINTF(Ethernet
, "receive reset\n");
1015 assert(rxPktBytes
== 0);
1019 assert(rxDescCnt
== 0);
1020 assert(rxDmaState
== dmaIdle
);
1022 regs
.command
&= ~CR_RXE
;
1027 EtherDev::rxDmaReadCopy()
1029 assert(rxDmaState
== dmaReading
);
1031 memcpy(rxDmaData
, physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaLen
);
1032 rxDmaState
= dmaIdle
;
1034 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1035 rxDmaAddr
, rxDmaLen
);
1036 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1040 EtherDev::doRxDmaRead()
1042 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1043 rxDmaState
= dmaReading
;
1045 if (dmaInterface
&& !rxDmaFree
) {
1046 if (dmaInterface
->busy())
1047 rxDmaState
= dmaReadWaiting
;
1049 dmaInterface
->doDMA(Read
, rxDmaAddr
, rxDmaLen
, curTick
,
1054 if (dmaReadDelay
== 0 && dmaReadFactor
== 0) {
1059 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1060 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1061 rxDmaReadEvent
.schedule(start
);
1066 EtherDev::rxDmaReadDone()
1068 assert(rxDmaState
== dmaReading
);
1071 // If the transmit state machine has a pending DMA, let it go first
1072 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1079 EtherDev::rxDmaWriteCopy()
1081 assert(rxDmaState
== dmaWriting
);
1083 memcpy(physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaData
, rxDmaLen
);
1084 rxDmaState
= dmaIdle
;
1086 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1087 rxDmaAddr
, rxDmaLen
);
1088 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1092 EtherDev::doRxDmaWrite()
1094 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1095 rxDmaState
= dmaWriting
;
1097 if (dmaInterface
&& !rxDmaFree
) {
1098 if (dmaInterface
->busy())
1099 rxDmaState
= dmaWriteWaiting
;
1101 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
, curTick
,
1106 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0) {
1111 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1112 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1113 rxDmaWriteEvent
.schedule(start
);
1118 EtherDev::rxDmaWriteDone()
1120 assert(rxDmaState
== dmaWriting
);
1123 // If the transmit state machine has a pending DMA, let it go first
1124 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1133 DPRINTF(Ethernet
, "receive kick state=%s (rxBuf.size=%d)\n",
1134 NsRxStateStrings
[rxState
], rxFifo
.size());
1136 if (rxKickTick
> curTick
) {
1137 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1143 switch(rxDmaState
) {
1144 case dmaReadWaiting
:
1148 case dmaWriteWaiting
:
1156 // see state machine from spec for details
1157 // the way this works is, if you finish work on one state and can go directly to
1158 // another, you do that through jumping to the label "next". however, if you have
1159 // intermediate work, like DMA so that you can't go to the next state yet, you go to
1160 // exit and exit the loop. however, when the DMA is done it will trigger an
1161 // event and come back to this loop.
1164 if (!regs
.command
& CR_RXE
) {
1165 DPRINTF(Ethernet
, "Receive Disabled! Nothing to do.\n");
1170 rxState
= rxDescRefr
;
1172 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1173 rxDmaData
= &rxDescCache
+ offsetof(ns_desc
, link
);
1174 rxDmaLen
= sizeof(rxDescCache
.link
);
1175 rxDmaFree
= dmaDescFree
;
1180 rxState
= rxDescRead
;
1182 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1183 rxDmaData
= &rxDescCache
;
1184 rxDmaLen
= sizeof(ns_desc
);
1185 rxDmaFree
= dmaDescFree
;
1193 if (rxDmaState
!= dmaIdle
)
1196 rxState
= rxAdvance
;
1200 if (rxDmaState
!= dmaIdle
)
1203 if (rxDescCache
.cmdsts
& CMDSTS_OWN
) {
1206 rxState
= rxFifoBlock
;
1207 rxFragPtr
= rxDescCache
.bufptr
;
1208 rxDescCnt
= rxDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1215 * @todo in reality, we should be able to start processing
1216 * the packet as it arrives, and not have to wait for the
1217 * full packet ot be in the receive fifo.
1222 // If we don't have a packet, grab a new one from the fifo.
1223 rxPacket
= rxFifo
.front();
1224 rxPktBytes
= rxPacket
->length
;
1225 rxPacketBufPtr
= rxPacket
->data
;
1227 // sanity check - i think the driver behaves like this
1228 assert(rxDescCnt
>= rxPktBytes
);
1230 // Must clear the value before popping to decrement the
1232 rxFifo
.front() = NULL
;
1237 // dont' need the && rxDescCnt > 0 if driver sanity check above holds
1238 if (rxPktBytes
> 0) {
1239 rxState
= rxFragWrite
;
1240 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds
1241 rxXferLen
= rxPktBytes
;
1243 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1244 rxDmaData
= rxPacketBufPtr
;
1245 rxDmaLen
= rxXferLen
;
1246 rxDmaFree
= dmaDataFree
;
1252 rxState
= rxDescWrite
;
1254 //if (rxPktBytes == 0) { /* packet is done */
1255 assert(rxPktBytes
== 0);
1257 rxFifoCnt
-= rxPacket
->length
;
1260 rxDescCache
.cmdsts
|= CMDSTS_OWN
;
1261 rxDescCache
.cmdsts
&= ~CMDSTS_MORE
;
1262 rxDescCache
.cmdsts
|= CMDSTS_OK
;
1263 rxDescCache
.cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1266 /* all the driver uses these are for its own stats keeping
1267 which we don't care about, aren't necessary for functionality
1268 and doing this would just slow us down. if they end up using
1269 this in a later version for functional purposes, just undef
1271 if (rxFilterEnable
) {
1272 rxDescCache
.cmdsts
&= ~CMDSTS_DEST_MASK
;
1273 if (rxFifo
.front()->IsUnicast())
1274 rxDescCache
.cmdsts
|= CMDSTS_DEST_SELF
;
1275 if (rxFifo
.front()->IsMulticast())
1276 rxDescCache
.cmdsts
|= CMDSTS_DEST_MULTI
;
1277 if (rxFifo
.front()->IsBroadcast())
1278 rxDescCache
.cmdsts
|= CMDSTS_DEST_MASK
;
1282 eth_header
*eth
= (eth_header
*) rxPacket
->data
;
1283 // eth->type 0x800 indicated that it's an ip packet.
1284 if (eth
->type
== 0x800 && extstsEnable
) {
1285 rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1286 if (!ipChecksum(rxPacket
, false))
1287 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1288 ip_header
*ip
= rxFifo
.front()->getIpHdr();
1290 if (ip
->protocol
== 6) {
1291 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1292 if (!tcpChecksum(rxPacket
, false))
1293 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1294 } else if (ip
->protocol
== 17) {
1295 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1296 if (!udpChecksum(rxPacket
, false))
1297 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1301 /* the driver seems to always receive into desc buffers
1302 of size 1514, so you never have a pkt that is split
1303 into multiple descriptors on the receive side, so
1304 i don't implement that case, hence the assert above.
1307 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1308 rxDmaData
= &(rxDescCache
.cmdsts
);
1309 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1310 rxDmaFree
= dmaDescFree
;
1318 if (rxDmaState
!= dmaIdle
)
1321 rxPacketBufPtr
+= rxXferLen
;
1322 rxFragPtr
+= rxXferLen
;
1323 rxPktBytes
-= rxXferLen
;
1325 rxState
= rxFifoBlock
;
1329 if (rxDmaState
!= dmaIdle
)
1332 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1334 assert(rxPacket
== 0);
1335 devIntrPost(ISR_RXOK
);
1337 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1338 devIntrPost(ISR_RXDESC
);
1344 rxState
= rxAdvance
;
1348 if (rxDescCache
.link
== 0) {
1352 rxState
= rxDescRead
;
1353 regs
.rxdp
= rxDescCache
.link
;
1356 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1357 rxDmaData
= &rxDescCache
;
1358 rxDmaLen
= sizeof(ns_desc
);
1359 rxDmaFree
= dmaDescFree
;
1367 panic("Invalid rxState!");
1371 DPRINTF(Ethernet
, "entering next rx state = %s\n",
1372 NsRxStateStrings
[rxState
]);
1374 if (rxState
== rxIdle
) {
1375 regs
.command
&= ~CR_RXE
;
1376 devIntrPost(ISR_RXIDLE
);
1384 * @todo do we want to schedule a future kick?
1386 DPRINTF(Ethernet
, "rx state machine exited state=%s\n",
1387 NsRxStateStrings
[rxState
]);
1391 EtherDev::transmit()
1393 if (txFifo
.empty()) {
1394 DPRINTF(Ethernet
, "nothing to transmit\n");
1398 if (interface
->sendPacket(txFifo
.front())) {
1399 DPRINTF(Ethernet
, "transmit packet\n");
1400 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1401 txBytes
+= txFifo
.front()->length
;
1404 txFifoCnt
-= (txFifo
.front()->length
- txPktXmitted
);
1406 txFifo
.front() = NULL
;
1409 /* normally do a writeback of the descriptor here, and ONLY after that is
1410 done, send this interrupt. but since our stuff never actually fails,
1411 just do this interrupt here, otherwise the code has to stray from this
1412 nice format. besides, it's functionally the same.
1414 devIntrPost(ISR_TXOK
);
1417 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1418 DPRINTF(Ethernet
, "reschedule transmit\n");
1419 txEvent
.schedule(curTick
+ 1000);
1424 EtherDev::txDmaReadCopy()
1426 assert(txDmaState
== dmaReading
);
1428 memcpy(txDmaData
, physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaLen
);
1429 txDmaState
= dmaIdle
;
1431 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1432 txDmaAddr
, txDmaLen
);
1433 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1437 EtherDev::doTxDmaRead()
1439 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1440 txDmaState
= dmaReading
;
1442 if (dmaInterface
&& !txDmaFree
) {
1443 if (dmaInterface
->busy())
1444 txDmaState
= dmaReadWaiting
;
1446 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1451 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1456 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1457 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1458 txDmaReadEvent
.schedule(start
);
1463 EtherDev::txDmaReadDone()
1465 assert(txDmaState
== dmaReading
);
1468 // If the receive state machine has a pending DMA, let it go first
1469 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1476 EtherDev::txDmaWriteCopy()
1478 assert(txDmaState
== dmaWriting
);
1480 memcpy(physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaData
, txDmaLen
);
1481 txDmaState
= dmaIdle
;
1483 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1484 txDmaAddr
, txDmaLen
);
1485 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1489 EtherDev::doTxDmaWrite()
1491 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1492 txDmaState
= dmaWriting
;
1494 if (dmaInterface
&& !txDmaFree
) {
1495 if (dmaInterface
->busy())
1496 txDmaState
= dmaWriteWaiting
;
1498 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1503 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1508 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1509 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1510 txDmaWriteEvent
.schedule(start
);
1515 EtherDev::txDmaWriteDone()
1517 assert(txDmaState
== dmaWriting
);
1520 // If the receive state machine has a pending DMA, let it go first
1521 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1530 DPRINTF(Ethernet
, "transmit kick state=%s\n", NsTxStateStrings
[txState
]);
1532 if (rxKickTick
> curTick
) {
1533 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1540 switch(txDmaState
) {
1541 case dmaReadWaiting
:
1545 case dmaWriteWaiting
:
1555 if (!regs
.command
& CR_TXE
) {
1556 DPRINTF(Ethernet
, "Transmit disabled. Nothing to do.\n");
1561 txState
= txDescRefr
;
1563 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1564 txDmaData
= &txDescCache
;
1565 txDmaLen
= sizeof(txDescCache
.link
);
1566 txDmaFree
= dmaDescFree
;
1572 txState
= txDescRead
;
1574 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1575 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1576 txDmaLen
= sizeof(ns_desc
);
1577 txDmaFree
= dmaDescFree
;
1585 if (txDmaState
!= dmaIdle
)
1588 txState
= txAdvance
;
1592 if (txDmaState
!= dmaIdle
)
1595 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1596 txState
= txFifoBlock
;
1597 txFragPtr
= txDescCache
.bufptr
;
1598 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1606 DPRINTF(Ethernet
, "starting the tx of a new packet\n");
1607 txPacket
= new EtherPacket
;
1608 txPacket
->data
= new uint8_t[16384];
1609 txPacketBufPtr
= txPacket
->data
;
1612 if (txDescCnt
== 0) {
1613 DPRINTF(Ethernet
, "the txDescCnt == 0, done with descriptor\n");
1614 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1615 DPRINTF(Ethernet
, "there are more descriptors to come\n");
1616 txState
= txDescWrite
;
1618 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1620 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1621 txDmaData
= &(txDescCache
.cmdsts
);
1622 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1623 txDmaFree
= dmaDescFree
;
1628 } else { /* this packet is totally done */
1629 DPRINTF(Ethernet
, "This packet is done, let's wrap it up\n");
1630 /* deal with the the packet that just finished */
1631 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1632 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1633 udpChecksum(txPacket
, true);
1634 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1635 tcpChecksum(txPacket
, true);
1636 } else if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1637 ipChecksum(txPacket
, true);
1641 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1642 /* this is just because the receive can't handle a packet bigger
1643 want to make sure */
1644 assert(txPacket
->length
<= 1514);
1645 txFifo
.push_back(txPacket
);
1648 /* this following section is not to spec, but functionally shouldn't
1649 be any different. normally, the chip will wait til the transmit has
1650 occurred before writing back the descriptor because it has to wait
1651 to see that it was successfully transmitted to decide whether to set
1652 CMDSTS_OK or not. however, in the simulator since it is always
1653 successfully transmitted, and writing it exactly to spec would
1654 complicate the code, we just do it here
1656 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1657 txDescCache
.cmdsts
|= CMDSTS_OK
;
1659 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1660 txDmaData
= &txDescCache
+ offsetof(ns_desc
, cmdsts
);
1661 txDmaLen
= sizeof(txDescCache
.cmdsts
) + sizeof(txDescCache
.extsts
);
1662 txDmaFree
= dmaDescFree
;
1675 txState
= txAdvance
;
1678 DPRINTF(Ethernet
, "this descriptor isn't done yet\n");
1679 /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
1680 value, shift left by 5 to get the real number of bytes */
1681 if (txFifoAvail
< ((regs
.txcfg
& TXCFG_FLTH_MASK
) >> 3)) {
1682 DPRINTF(Ethernet
, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
1683 txFifoAvail
, regs
.txcfg
& TXCFG_FLTH_MASK
);
1687 txState
= txFragRead
;
1689 /* The number of bytes transferred is either whatever is left
1690 in the descriptor (txDescCnt), or if there is not enough
1691 room in the fifo, just whatever room is left in the fifo
1693 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1695 txDmaAddr
= txFragPtr
& 0x3fffffff;
1696 txDmaData
= txPacketBufPtr
;
1697 txDmaLen
= txXferLen
;
1698 txDmaFree
= dmaDataFree
;
1706 if (txDmaState
!= dmaIdle
)
1709 txPacketBufPtr
+= txXferLen
;
1710 txFragPtr
+= txXferLen
;
1711 txFifoCnt
+= txXferLen
;
1712 txDescCnt
-= txXferLen
;
1714 txState
= txFifoBlock
;
1718 if (txDmaState
!= dmaIdle
)
1721 if (txFifoCnt
>= ((regs
.txcfg
& TXCFG_DRTH_MASK
) << 5)) {
1722 if (txFifo
.empty()) {
1723 uint32_t xmitted
= (uint32_t) (txPacketBufPtr
- txPacket
->data
- txPktXmitted
);
1724 txFifoCnt
-= xmitted
;
1725 txPktXmitted
+= xmitted
;
1731 if (txDescCache
.cmdsts
& CMDSTS_INTR
) {
1732 devIntrPost(ISR_TXDESC
);
1735 txState
= txAdvance
;
1739 if (txDescCache
.link
== 0) {
1742 txState
= txDescRead
;
1743 regs
.txdp
= txDescCache
.link
;
1746 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1747 txDmaData
= &txDescCache
;
1748 txDmaLen
= sizeof(ns_desc
);
1749 txDmaFree
= dmaDescFree
;
1757 panic("invalid state");
1760 DPRINTF(Ethernet
, "entering next tx state=%s\n",
1761 NsTxStateStrings
[txState
]);
1763 if (txState
== txIdle
) {
1764 regs
.command
&= ~CR_TXE
;
1765 devIntrPost(ISR_TXIDLE
);
1773 * @todo do we want to schedule a future kick?
1775 DPRINTF(Ethernet
, "tx state machine exited state=%s\n",
1776 NsTxStateStrings
[txState
]);
1780 EtherDev::transferDone()
1785 DPRINTF(Ethernet
, "schedule transmit\n");
1787 if (txEvent
.scheduled())
1788 txEvent
.reschedule(curTick
+ 1);
1790 txEvent
.schedule(curTick
+ 1);
1794 EtherDev::rxFilter(PacketPtr packet
)
1799 if (packet
->IsUnicast()) {
1802 // If we're accepting all unicast addresses
1806 // If we make a perfect match
1808 && (memcmp(rom
.perfectMatch
, packet
->data
, sizeof(rom
.perfectMatch
)) == 0))
1811 eth_header
*eth
= (eth_header
*) packet
->data
;
1812 if ((acceptArp
) && (eth
->type
== 0x806))
1815 } else if (packet
->IsBroadcast()) {
1818 // if we're accepting broadcasts
1819 if (acceptBroadcast
)
1822 } else if (packet
->IsMulticast()) {
1825 // if we're accepting all multicasts
1826 if (acceptMulticast
)
1832 // oh well, punt on this one
1836 DPRINTF(Ethernet
, "rxFilter drop\n");
1837 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1844 EtherDev::recvPacket(PacketPtr packet
)
1846 rxBytes
+= packet
->length
;
1849 if (rxState
== rxIdle
) {
1850 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1851 interface
->recvDone();
1855 if (rxFilterEnable
&& rxFilter(packet
)) {
1856 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1857 interface
->recvDone();
1861 if (rxFifoCnt
+ packet
->length
>= MAX_RX_FIFO_SIZE
) {
1863 "packet will not fit in receive buffer...packet dropped\n");
1864 devIntrPost(ISR_RXORN
);
1868 rxFifo
.push_back(packet
);
1869 rxFifoCnt
+= packet
->length
;
1870 interface
->recvDone();
1877 * does a udp checksum. if gen is true, then it generates it and puts it in the right place
1878 * else, it just checks what it calculates against the value in the header in packet
1881 EtherDev::udpChecksum(PacketPtr packet
, bool gen
)
1883 udp_header
*hdr
= (udp_header
*) packet
->getTransportHdr();
1885 ip_header
*ip
= packet
->getIpHdr();
1887 pseudo_header
*pseudo
= new pseudo_header
;
1889 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1890 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1891 pseudo
->protocol
= ip
->protocol
;
1892 pseudo
->len
= hdr
->len
;
1894 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1895 (uint32_t) hdr
->len
);
1899 hdr
->chksum
= cksum
;
1908 EtherDev::tcpChecksum(PacketPtr packet
, bool gen
)
1910 tcp_header
*hdr
= (tcp_header
*) packet
->getTransportHdr();
1912 ip_header
*ip
= packet
->getIpHdr();
1914 pseudo_header
*pseudo
= new pseudo_header
;
1916 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1917 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1918 pseudo
->protocol
= ip
->protocol
;
1919 pseudo
->len
= ip
->dgram_len
- (ip
->vers_len
& 0xf);
1921 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1922 (uint32_t) pseudo
->len
);
1926 hdr
->chksum
= cksum
;
1935 EtherDev::ipChecksum(PacketPtr packet
, bool gen
)
1937 ip_header
*hdr
= packet
->getIpHdr();
1939 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
, (hdr
->vers_len
& 0xf));
1942 hdr
->hdr_chksum
= cksum
;
1951 EtherDev::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
1955 uint16_t last_pad
= 0;
1957 last_pad
= buf
[len
/2] & 0xff;
1963 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
1964 pseudo
[3] + pseudo
[4] + pseudo
[5];
1967 for (int i
=0; i
< (len
/2); ++i
) {
1972 sum
= (sum
>> 16) + (sum
& 0xffff);
1977 //=====================================================================
1981 EtherDev::serialize(ostream
&os
)
1984 * Finalize any DMA events now.
1986 if (rxDmaReadEvent
.scheduled())
1988 if (rxDmaWriteEvent
.scheduled())
1990 if (txDmaReadEvent
.scheduled())
1992 if (txDmaWriteEvent
.scheduled())
1996 * Serialize the device registers
1998 SERIALIZE_SCALAR(regs
.command
);
1999 SERIALIZE_SCALAR(regs
.config
);
2000 SERIALIZE_SCALAR(regs
.mear
);
2001 SERIALIZE_SCALAR(regs
.ptscr
);
2002 SERIALIZE_SCALAR(regs
.isr
);
2003 SERIALIZE_SCALAR(regs
.imr
);
2004 SERIALIZE_SCALAR(regs
.ier
);
2005 SERIALIZE_SCALAR(regs
.ihr
);
2006 SERIALIZE_SCALAR(regs
.txdp
);
2007 SERIALIZE_SCALAR(regs
.txdp_hi
);
2008 SERIALIZE_SCALAR(regs
.txcfg
);
2009 SERIALIZE_SCALAR(regs
.gpior
);
2010 SERIALIZE_SCALAR(regs
.rxdp
);
2011 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2012 SERIALIZE_SCALAR(regs
.rxcfg
);
2013 SERIALIZE_SCALAR(regs
.pqcr
);
2014 SERIALIZE_SCALAR(regs
.wcsr
);
2015 SERIALIZE_SCALAR(regs
.pcr
);
2016 SERIALIZE_SCALAR(regs
.rfcr
);
2017 SERIALIZE_SCALAR(regs
.rfdr
);
2018 SERIALIZE_SCALAR(regs
.srr
);
2019 SERIALIZE_SCALAR(regs
.mibc
);
2020 SERIALIZE_SCALAR(regs
.vrcr
);
2021 SERIALIZE_SCALAR(regs
.vtcr
);
2022 SERIALIZE_SCALAR(regs
.vdr
);
2023 SERIALIZE_SCALAR(regs
.ccsr
);
2024 SERIALIZE_SCALAR(regs
.tbicr
);
2025 SERIALIZE_SCALAR(regs
.tbisr
);
2026 SERIALIZE_SCALAR(regs
.tanar
);
2027 SERIALIZE_SCALAR(regs
.tanlpar
);
2028 SERIALIZE_SCALAR(regs
.taner
);
2029 SERIALIZE_SCALAR(regs
.tesr
);
2031 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2034 * Serialize the various helper variables
2036 uint32_t txPktBufPtr
= (uint32_t) txPacketBufPtr
;
2037 SERIALIZE_SCALAR(txPktBufPtr
);
2038 uint32_t rxPktBufPtr
= (uint32_t) rxPktBufPtr
;
2039 SERIALIZE_SCALAR(rxPktBufPtr
);
2040 SERIALIZE_SCALAR(txXferLen
);
2041 SERIALIZE_SCALAR(rxXferLen
);
2042 SERIALIZE_SCALAR(txPktXmitted
);
2044 bool txPacketExists
= txPacket
;
2045 SERIALIZE_SCALAR(txPacketExists
);
2046 bool rxPacketExists
= rxPacket
;
2047 SERIALIZE_SCALAR(rxPacketExists
);
2050 * Serialize DescCaches
2052 SERIALIZE_SCALAR(txDescCache
.link
);
2053 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2054 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2055 SERIALIZE_SCALAR(txDescCache
.extsts
);
2056 SERIALIZE_SCALAR(rxDescCache
.link
);
2057 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2058 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2059 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2062 * Serialize tx state machine
2064 int txNumPkts
= txFifo
.size();
2065 SERIALIZE_SCALAR(txNumPkts
);
2066 int txState
= this->txState
;
2067 SERIALIZE_SCALAR(txState
);
2068 SERIALIZE_SCALAR(CTDD
);
2069 SERIALIZE_SCALAR(txFifoCnt
);
2070 SERIALIZE_SCALAR(txFifoAvail
);
2071 SERIALIZE_SCALAR(txHalt
);
2072 SERIALIZE_SCALAR(txFragPtr
);
2073 SERIALIZE_SCALAR(txDescCnt
);
2074 int txDmaState
= this->txDmaState
;
2075 SERIALIZE_SCALAR(txDmaState
);
2078 * Serialize rx state machine
2080 int rxNumPkts
= rxFifo
.size();
2081 SERIALIZE_SCALAR(rxNumPkts
);
2082 int rxState
= this->rxState
;
2083 SERIALIZE_SCALAR(rxState
);
2084 SERIALIZE_SCALAR(CRDD
);
2085 SERIALIZE_SCALAR(rxPktBytes
);
2086 SERIALIZE_SCALAR(rxFifoCnt
);
2087 SERIALIZE_SCALAR(rxHalt
);
2088 SERIALIZE_SCALAR(rxDescCnt
);
2089 int rxDmaState
= this->rxDmaState
;
2090 SERIALIZE_SCALAR(rxDmaState
);
2092 SERIALIZE_SCALAR(extstsEnable
);
2095 * If there's a pending transmit, store the time so we can
2096 * reschedule it later
2098 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2099 SERIALIZE_SCALAR(transmitTick
);
2102 * Keep track of pending interrupt status.
2104 SERIALIZE_SCALAR(intrTick
);
2105 SERIALIZE_SCALAR(cpuPendingIntr
);
2106 Tick intrEventTick
= 0;
2108 intrEventTick
= intrEvent
->when();
2109 SERIALIZE_SCALAR(intrEventTick
);
2112 for (pktiter_t p
= rxFifo
.begin(); p
!= rxFifo
.end(); ++p
) {
2113 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2114 (*p
)->serialize(os
);
2116 if (rxPacketExists
) {
2117 nameOut(os
, csprintf("%s.rxPacket", name()));
2118 rxPacket
->serialize(os
);
2121 for (pktiter_t p
= txFifo
.begin(); p
!= txFifo
.end(); ++p
) {
2122 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2123 (*p
)->serialize(os
);
2125 if (txPacketExists
) {
2126 nameOut(os
, csprintf("%s.txPacket", name()));
2127 txPacket
->serialize(os
);
2132 EtherDev::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2134 UNSERIALIZE_SCALAR(regs
.command
);
2135 UNSERIALIZE_SCALAR(regs
.config
);
2136 UNSERIALIZE_SCALAR(regs
.mear
);
2137 UNSERIALIZE_SCALAR(regs
.ptscr
);
2138 UNSERIALIZE_SCALAR(regs
.isr
);
2139 UNSERIALIZE_SCALAR(regs
.imr
);
2140 UNSERIALIZE_SCALAR(regs
.ier
);
2141 UNSERIALIZE_SCALAR(regs
.ihr
);
2142 UNSERIALIZE_SCALAR(regs
.txdp
);
2143 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2144 UNSERIALIZE_SCALAR(regs
.txcfg
);
2145 UNSERIALIZE_SCALAR(regs
.gpior
);
2146 UNSERIALIZE_SCALAR(regs
.rxdp
);
2147 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2148 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2149 UNSERIALIZE_SCALAR(regs
.pqcr
);
2150 UNSERIALIZE_SCALAR(regs
.wcsr
);
2151 UNSERIALIZE_SCALAR(regs
.pcr
);
2152 UNSERIALIZE_SCALAR(regs
.rfcr
);
2153 UNSERIALIZE_SCALAR(regs
.rfdr
);
2154 UNSERIALIZE_SCALAR(regs
.srr
);
2155 UNSERIALIZE_SCALAR(regs
.mibc
);
2156 UNSERIALIZE_SCALAR(regs
.vrcr
);
2157 UNSERIALIZE_SCALAR(regs
.vtcr
);
2158 UNSERIALIZE_SCALAR(regs
.vdr
);
2159 UNSERIALIZE_SCALAR(regs
.ccsr
);
2160 UNSERIALIZE_SCALAR(regs
.tbicr
);
2161 UNSERIALIZE_SCALAR(regs
.tbisr
);
2162 UNSERIALIZE_SCALAR(regs
.tanar
);
2163 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2164 UNSERIALIZE_SCALAR(regs
.taner
);
2165 UNSERIALIZE_SCALAR(regs
.tesr
);
2167 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2170 * unserialize the various helper variables
2172 uint32_t txPktBufPtr
;
2173 UNSERIALIZE_SCALAR(txPktBufPtr
);
2174 txPacketBufPtr
= (uint8_t *) txPktBufPtr
;
2175 uint32_t rxPktBufPtr
;
2176 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2177 rxPacketBufPtr
= (uint8_t *) rxPktBufPtr
;
2178 UNSERIALIZE_SCALAR(txXferLen
);
2179 UNSERIALIZE_SCALAR(rxXferLen
);
2180 UNSERIALIZE_SCALAR(txPktXmitted
);
2182 bool txPacketExists
;
2183 UNSERIALIZE_SCALAR(txPacketExists
);
2184 bool rxPacketExists
;
2185 UNSERIALIZE_SCALAR(rxPacketExists
);
2188 * Unserialize DescCaches
2190 UNSERIALIZE_SCALAR(txDescCache
.link
);
2191 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2192 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2193 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2194 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2195 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2196 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2197 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2200 * unserialize tx state machine
2203 UNSERIALIZE_SCALAR(txNumPkts
);
2205 UNSERIALIZE_SCALAR(txState
);
2206 this->txState
= (TxState
) txState
;
2207 UNSERIALIZE_SCALAR(CTDD
);
2208 UNSERIALIZE_SCALAR(txFifoCnt
);
2209 UNSERIALIZE_SCALAR(txFifoAvail
);
2210 UNSERIALIZE_SCALAR(txHalt
);
2211 UNSERIALIZE_SCALAR(txFragPtr
);
2212 UNSERIALIZE_SCALAR(txDescCnt
);
2214 UNSERIALIZE_SCALAR(txDmaState
);
2215 this->txDmaState
= (DmaState
) txDmaState
;
2218 * unserialize rx state machine
2221 UNSERIALIZE_SCALAR(rxNumPkts
);
2223 UNSERIALIZE_SCALAR(rxState
);
2224 this->rxState
= (RxState
) rxState
;
2225 UNSERIALIZE_SCALAR(CRDD
);
2226 UNSERIALIZE_SCALAR(rxPktBytes
);
2227 UNSERIALIZE_SCALAR(rxFifoCnt
);
2228 UNSERIALIZE_SCALAR(rxHalt
);
2229 UNSERIALIZE_SCALAR(rxDescCnt
);
2231 UNSERIALIZE_SCALAR(rxDmaState
);
2232 this->rxDmaState
= (DmaState
) rxDmaState
;
2234 UNSERIALIZE_SCALAR(extstsEnable
);
2237 * If there's a pending transmit, store the time so we can
2238 * reschedule it later
2241 UNSERIALIZE_SCALAR(transmitTick
);
2243 txEvent
.schedule(curTick
+ transmitTick
);
2246 * Keep track of pending interrupt status.
2248 UNSERIALIZE_SCALAR(intrTick
);
2249 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2251 UNSERIALIZE_SCALAR(intrEventTick
);
2252 if (intrEventTick
) {
2253 intrEvent
= new IntrEvent(this, true);
2254 intrEvent
->schedule(intrEventTick
);
2257 for (int i
= 0; i
< rxNumPkts
; ++i
) {
2258 PacketPtr p
= new EtherPacket
;
2259 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2260 rxFifo
.push_back(p
);
2263 if (rxPacketExists
) {
2264 rxPacket
= new EtherPacket
;
2265 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2267 for (int i
= 0; i
< txNumPkts
; ++i
) {
2268 PacketPtr p
= new EtherPacket
;
2269 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2270 txFifo
.push_back(p
);
2272 if (txPacketExists
) {
2273 txPacket
= new EtherPacket
;
2274 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2280 EtherDev::cacheAccess(MemReqPtr
&req
)
2282 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2283 req
->paddr
, req
->paddr
- addr
);
2284 return curTick
+ pioLatency
;
2286 //=====================================================================
2289 BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt
)
2291 SimObjectParam
<EtherInt
*> peer
;
2292 SimObjectParam
<EtherDev
*> device
;
2294 END_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt
)
2296 BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDevInt
)
2298 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2299 INIT_PARAM(device
, "Ethernet device of this interface")
2301 END_INIT_SIM_OBJECT_PARAMS(EtherDevInt
)
2303 CREATE_SIM_OBJECT(EtherDevInt
)
2305 EtherDevInt
*dev_int
= new EtherDevInt(getInstanceName(), device
);
2307 EtherInt
*p
= (EtherInt
*)peer
;
2309 dev_int
->setPeer(p
);
2310 p
->setPeer(dev_int
);
2316 REGISTER_SIM_OBJECT("EtherDevInt", EtherDevInt
)
2319 BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev
)
2321 Param
<Tick
> tx_delay
;
2322 Param
<Tick
> rx_delay
;
2323 SimObjectParam
<IntrControl
*> intr_ctrl
;
2324 Param
<Tick
> intr_delay
;
2325 SimObjectParam
<MemoryController
*> mmu
;
2326 SimObjectParam
<PhysicalMemory
*> physmem
;
2328 Param
<bool> rx_filter
;
2329 Param
<string
> hardware_address
;
2330 SimObjectParam
<Bus
*> header_bus
;
2331 SimObjectParam
<Bus
*> payload_bus
;
2332 SimObjectParam
<HierParams
*> hier
;
2333 Param
<Tick
> pio_latency
;
2334 Param
<bool> dma_desc_free
;
2335 Param
<bool> dma_data_free
;
2336 Param
<Tick
> dma_read_delay
;
2337 Param
<Tick
> dma_write_delay
;
2338 Param
<Tick
> dma_read_factor
;
2339 Param
<Tick
> dma_write_factor
;
2340 SimObjectParam
<PciConfigAll
*> configspace
;
2341 SimObjectParam
<PciConfigData
*> configdata
;
2342 SimObjectParam
<Tsunami
*> tsunami
;
2343 Param
<uint32_t> pci_bus
;
2344 Param
<uint32_t> pci_dev
;
2345 Param
<uint32_t> pci_func
;
2347 END_DECLARE_SIM_OBJECT_PARAMS(EtherDev
)
2349 BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev
)
2351 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2352 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2353 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2354 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2355 INIT_PARAM(mmu
, "Memory Controller"),
2356 INIT_PARAM(physmem
, "Physical Memory"),
2357 INIT_PARAM(addr
, "Device Address"),
2358 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2359 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2360 "00:99:00:00:00:01"),
2361 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2362 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2363 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2364 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000),
2365 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2366 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2367 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2368 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2369 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2370 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2371 INIT_PARAM(configspace
, "PCI Configspace"),
2372 INIT_PARAM(configdata
, "PCI Config data"),
2373 INIT_PARAM(tsunami
, "Tsunami"),
2374 INIT_PARAM(pci_bus
, "PCI bus"),
2375 INIT_PARAM(pci_dev
, "PCI device number"),
2376 INIT_PARAM(pci_func
, "PCI function code")
2378 END_INIT_SIM_OBJECT_PARAMS(EtherDev
)
2381 CREATE_SIM_OBJECT(EtherDev
)
2384 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2385 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2387 return new EtherDev(getInstanceName(), intr_ctrl
, intr_delay
,
2388 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2389 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2390 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2391 dma_write_factor
, configspace
, configdata
,
2392 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
,
2396 REGISTER_SIM_OBJECT("EtherDev", EtherDev
)