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.
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 ///////////////////////////////////////////////////////////////////////
93 NSGigE::NSGigE(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])
101 : PciDev(name
, mmu
, cf
, cd
, bus
, dev
, func
), tsunami(t
),
102 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 tsunami
->ethernet
= this;
121 pioInterface
= newPioInterface(name
, hier
, header_bus
, this,
122 &NSGigE::cacheAccess
);
125 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
126 header_bus
, payload_bus
, 1);
128 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
129 header_bus
, header_bus
, 1);
130 } else if (payload_bus
) {
131 pioInterface
= newPioInterface(name
, hier
, payload_bus
, this,
132 &NSGigE::cacheAccess
);
134 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
135 payload_bus
, payload_bus
, 1);
140 intrDelay
= US2Ticks(intr_delay
);
141 dmaReadDelay
= dma_read_delay
;
142 dmaWriteDelay
= dma_write_delay
;
143 dmaReadFactor
= dma_read_factor
;
144 dmaWriteFactor
= dma_write_factor
;
146 memset(®s
, 0, sizeof(regs
));
148 rom
.perfectMatch
[0] = eaddr
[0];
149 rom
.perfectMatch
[1] = eaddr
[1];
150 rom
.perfectMatch
[2] = eaddr
[2];
151 rom
.perfectMatch
[3] = eaddr
[3];
152 rom
.perfectMatch
[4] = eaddr
[4];
153 rom
.perfectMatch
[5] = eaddr
[5];
163 .name(name() + ".txBytes")
164 .desc("Bytes Transmitted")
169 .name(name() + ".rxBytes")
170 .desc("Bytes Received")
175 .name(name() + ".txPackets")
176 .desc("Number of Packets Transmitted")
181 .name(name() + ".rxPackets")
182 .desc("Number of Packets Received")
187 .name(name() + ".txBandwidth")
188 .desc("Transmit Bandwidth (bits/s)")
194 .name(name() + ".rxBandwidth")
195 .desc("Receive Bandwidth (bits/s)")
201 .name(name() + ".txPPS")
202 .desc("Packet Tranmission Rate (packets/s)")
208 .name(name() + ".rxPPS")
209 .desc("Packet Reception Rate (packets/s)")
214 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
215 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
216 txPacketRate
= txPackets
/ simSeconds
;
217 rxPacketRate
= rxPackets
/ simSeconds
;
221 * This is to read the PCI general configuration registers
224 NSGigE::ReadConfig(int offset
, int size
, uint8_t *data
)
226 if (offset
< PCI_DEVICE_SPECIFIC
)
227 PciDev::ReadConfig(offset
, size
, data
);
229 panic("Device specific PCI config space not implemented!\n");
233 * This is to write to the PCI general configuration registers
236 NSGigE::WriteConfig(int offset
, int size
, uint32_t data
)
238 if (offset
< PCI_DEVICE_SPECIFIC
)
239 PciDev::WriteConfig(offset
, size
, data
);
241 panic("Device specific PCI config space not implemented!\n");
243 // Need to catch writes to BARs to update the PIO interface
245 case PCI0_BASE_ADDR0
:
246 if (BARAddrs
[0] != 0) {
250 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
252 addr
&= PA_UNCACHED_MASK
;
259 * This reads the device registers, which are detailed in the NS83820
263 NSGigE::read(MemReqPtr
&req
, uint8_t *data
)
265 //The mask is to give you only the offset into the device register file
266 Addr daddr
= req
->paddr
& 0xfff;
267 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x va=%#x size=%d\n",
268 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
271 //there are some reserved registers, you can see ns_gige_reg.h and
272 //the spec sheet for details
273 if (daddr
> LAST
&& daddr
<= RESERVED
) {
274 panic("Accessing reserved register");
275 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
276 ReadConfig(daddr
& 0xff, req
->size
, data
);
278 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
279 // don't implement all the MIB's. hopefully the kernel
280 // doesn't actually DEPEND upon their values
281 // MIB are just hardware stats keepers
282 uint32_t ®
= *(uint32_t *) data
;
285 } else if (daddr
> 0x3FC)
286 panic("Something is messed up!\n");
289 case sizeof(uint32_t):
291 uint32_t ®
= *(uint32_t *)data
;
296 //these are supposed to be cleared on a read
297 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
314 devIntrClear(ISR_ALL
);
369 //see the spec sheet for how RFCR and RFDR work
370 //basically, you write to RFCR to tell the machine what you want to do next
371 //then you act upon RFDR, and the device will be prepared b/c
372 //of what you wrote to RFCR
378 switch (regs
.rfcr
& RFCR_RFADDR
) {
380 reg
= rom
.perfectMatch
[1];
382 reg
+= rom
.perfectMatch
[0];
385 reg
= rom
.perfectMatch
[3] << 8;
386 reg
+= rom
.perfectMatch
[2];
389 reg
= rom
.perfectMatch
[5] << 8;
390 reg
+= rom
.perfectMatch
[4];
393 panic("reading from RFDR for something for other than PMATCH!\n");
394 //didn't implement other RFDR functionality b/c driver didn't use
404 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
448 panic("reading unimplemented register: addr = %#x", daddr
);
451 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n",
457 panic("accessing register with invalid size: addr=%#x, size=%d",
465 NSGigE::write(MemReqPtr
&req
, const uint8_t *data
)
467 Addr daddr
= req
->paddr
& 0xfff;
468 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x va=%#x size=%d\n",
469 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
471 if (daddr
> LAST
&& daddr
<= RESERVED
) {
472 panic("Accessing reserved register");
473 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
474 WriteConfig(daddr
& 0xff, req
->size
, *(uint32_t *)data
);
476 } else if (daddr
> 0x3FC)
477 panic("Something is messed up!\n");
479 if (req
->size
== sizeof(uint32_t)) {
480 uint32_t reg
= *(uint32_t *)data
;
481 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
486 if ((reg
& (CR_TXE
| CR_TXD
)) == (CR_TXE
| CR_TXD
)) {
488 } else if (reg
& CR_TXE
) {
489 //the kernel is enabling the transmit machine
490 if (txState
== txIdle
)
492 } else if (reg
& CR_TXD
) {
496 if ((reg
& (CR_RXE
| CR_RXD
)) == (CR_RXE
| CR_RXD
)) {
498 } else if (reg
& CR_RXE
) {
499 if (rxState
== rxIdle
) {
502 } else if (reg
& CR_RXD
) {
513 devIntrPost(ISR_SWI
);
524 if (reg
& CFG_LNKSTS
|| reg
& CFG_SPDSTS
|| reg
& CFG_DUPSTS
525 || reg
& CFG_RESERVED
|| reg
& CFG_T64ADDR
526 || reg
& CFG_PCI64_DET
)
527 panic("writing to read-only or reserved CFG bits!\n");
529 regs
.config
|= reg
& ~(CFG_LNKSTS
| CFG_SPDSTS
| CFG_DUPSTS
| CFG_RESERVED
|
530 CFG_T64ADDR
| CFG_PCI64_DET
);
532 // all these #if 0's are because i don't THINK the kernel needs to have these implemented
533 // if there is a problem relating to one of these, you may need to add functionality in
535 if (reg
& CFG_TBI_EN
) ;
536 if (reg
& CFG_MODE_1000
) ;
539 if (reg
& CFG_AUTO_1000
)
540 panic("CFG_AUTO_1000 not implemented!\n");
543 if (reg
& CFG_PINT_DUPSTS
|| reg
& CFG_PINT_LNKSTS
|| reg
& CFG_PINT_SPDSTS
) ;
544 if (reg
& CFG_TMRTEST
) ;
545 if (reg
& CFG_MRM_DIS
) ;
546 if (reg
& CFG_MWI_DIS
) ;
548 if (reg
& CFG_T64ADDR
)
549 panic("CFG_T64ADDR is read only register!\n");
551 if (reg
& CFG_PCI64_DET
)
552 panic("CFG_PCI64_DET is read only register!\n");
554 if (reg
& CFG_DATA64_EN
) ;
555 if (reg
& CFG_M64ADDR
) ;
556 if (reg
& CFG_PHY_RST
) ;
557 if (reg
& CFG_PHY_DIS
) ;
560 if (reg
& CFG_EXTSTS_EN
)
563 extstsEnable
= false;
566 if (reg
& CFG_REQALG
) ;
570 if (reg
& CFG_PESEL
) ;
571 if (reg
& CFG_BROM_DIS
) ;
572 if (reg
& CFG_EXT_125
) ;
579 /* since phy is completely faked, MEAR_MD* don't matter
580 and since the driver never uses MEAR_EE*, they don't matter */
582 if (reg
& MEAR_EEDI
) ;
583 if (reg
& MEAR_EEDO
) ; //this one is read only
584 if (reg
& MEAR_EECLK
) ;
585 if (reg
& MEAR_EESEL
) ;
586 if (reg
& MEAR_MDIO
) ;
587 if (reg
& MEAR_MDDIR
) ;
588 if (reg
& MEAR_MDC
) ;
593 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
594 /* these control BISTs for various parts of chip - we don't care or do
595 just fake that the BIST is done */
596 if (reg
& PTSCR_RBIST_EN
)
597 regs
.ptscr
|= PTSCR_RBIST_DONE
;
598 if (reg
& PTSCR_EEBIST_EN
)
599 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
600 if (reg
& PTSCR_EELOAD_EN
)
601 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
604 case ISR
: /* writing to the ISR has no effect */
605 panic("ISR is a read only register!\n");
618 /* not going to implement real interrupt holdoff */
622 regs
.txdp
= (reg
& 0xFFFFFFFC);
623 assert(txState
== txIdle
);
634 if (reg
& TXCFG_CSI
) ;
635 if (reg
& TXCFG_HBI
) ;
636 if (reg
& TXCFG_MLB
) ;
637 if (reg
& TXCFG_ATP
) ;
638 if (reg
& TXCFG_ECRETRY
) ; /* this could easily be implemented, but
639 considering the network is just a fake
640 pipe, wouldn't make sense to do this */
642 if (reg
& TXCFG_BRST_DIS
) ;
646 /* we handle our own DMA, ignore the kernel's exhortations */
647 if (reg
& TXCFG_MXDMA
) ;
653 /* these just control general purpose i/o pins, don't matter */
667 if (reg
& RXCFG_AEP
) ;
668 if (reg
& RXCFG_ARP
) ;
669 if (reg
& RXCFG_STRIPCRC
) ;
670 if (reg
& RXCFG_RX_RD
) ;
671 if (reg
& RXCFG_ALP
) ;
672 if (reg
& RXCFG_AIRL
) ;
675 /* we handle our own DMA, ignore what kernel says about it */
676 if (reg
& RXCFG_MXDMA
) ;
679 if (reg
& (RXCFG_DRTH
| RXCFG_DRTH0
)) ;
684 /* there is no priority queueing used in the linux 2.6 driver */
689 /* not going to implement wake on LAN */
694 /* not going to implement pause control */
701 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
703 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
705 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
707 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
709 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
711 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
713 if (reg
& RFCR_APAT
) ;
714 // panic("RFCR_APAT not implemented!\n");
716 if (reg
& RFCR_MHEN
|| reg
& RFCR_UHEN
)
717 panic("hash filtering not implemented!\n");
720 panic("RFCR_ULM not implemented!\n");
725 panic("the driver never writes to RFDR, something is wrong!\n");
728 panic("the driver never uses BRAR, something is wrong!\n");
731 panic("the driver never uses BRDR, something is wrong!\n");
734 panic("SRR is read only register!\n");
737 panic("the driver never uses MIBC, something is wrong!\n");
748 panic("the driver never uses VDR, something is wrong!\n");
752 /* not going to implement clockrun stuff */
758 if (reg
& TBICR_MR_LOOPBACK
)
759 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
761 if (reg
& TBICR_MR_AN_ENABLE
) {
762 regs
.tanlpar
= regs
.tanar
;
763 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
767 if (reg
& TBICR_MR_RESTART_AN
) ;
773 panic("TBISR is read only register!\n");
778 panic("this isn't used in driver, something wrong!\n");
781 panic("this isn't used in driver, something wrong!\n");
785 panic("this should only be written to by the fake phy!\n");
788 panic("TANER is read only register!\n");
795 panic("thought i covered all the register, what is this? addr=%#x",
799 panic("Invalid Request Size");
805 NSGigE::devIntrPost(uint32_t interrupts
)
809 if (interrupts
& ISR_RESERVE
)
810 panic("Cannot set a reserved interrupt");
812 if (interrupts
& ISR_TXRCMP
)
813 regs
.isr
|= ISR_TXRCMP
;
815 if (interrupts
& ISR_RXRCMP
)
816 regs
.isr
|= ISR_RXRCMP
;
818 //ISR_DPERR not implemented
819 //ISR_SSERR not implemented
820 //ISR_RMABT not implemented
821 //ISR_RXSOVR not implemented
822 //ISR_HIBINT not implemented
823 //ISR_PHY not implemented
824 //ISR_PME not implemented
826 if (interrupts
& ISR_SWI
)
829 //ISR_MIB not implemented
830 //ISR_TXURN not implemented
832 if (interrupts
& ISR_TXIDLE
)
833 regs
.isr
|= ISR_TXIDLE
;
835 if (interrupts
& ISR_TXERR
)
836 regs
.isr
|= ISR_TXERR
;
838 if (interrupts
& ISR_TXDESC
)
839 regs
.isr
|= ISR_TXDESC
;
841 if (interrupts
& ISR_TXOK
) {
842 regs
.isr
|= ISR_TXOK
;
846 if (interrupts
& ISR_RXORN
)
847 regs
.isr
|= ISR_RXORN
;
849 if (interrupts
& ISR_RXIDLE
)
850 regs
.isr
|= ISR_RXIDLE
;
852 //ISR_RXEARLY not implemented
854 if (interrupts
& ISR_RXERR
)
855 regs
.isr
|= ISR_RXERR
;
857 if (interrupts
& ISR_RXDESC
)
858 regs
.isr
|= ISR_RXDESC
;
860 if (interrupts
& ISR_RXOK
) {
862 regs
.isr
|= ISR_RXOK
;
865 if ((regs
.isr
& regs
.imr
)) {
872 DPRINTF(Ethernet
, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
873 interrupts
, regs
.isr
, regs
.imr
);
877 NSGigE::devIntrClear(uint32_t interrupts
)
879 if (interrupts
& ISR_RESERVE
)
880 panic("Cannot clear a reserved interrupt");
882 if (interrupts
& ISR_TXRCMP
)
883 regs
.isr
&= ~ISR_TXRCMP
;
885 if (interrupts
& ISR_RXRCMP
)
886 regs
.isr
&= ~ISR_RXRCMP
;
888 //ISR_DPERR not implemented
889 //ISR_SSERR not implemented
890 //ISR_RMABT not implemented
891 //ISR_RXSOVR not implemented
892 //ISR_HIBINT not implemented
893 //ISR_PHY not implemented
894 //ISR_PME not implemented
896 if (interrupts
& ISR_SWI
)
897 regs
.isr
&= ~ISR_SWI
;
899 //ISR_MIB not implemented
900 //ISR_TXURN not implemented
902 if (interrupts
& ISR_TXIDLE
)
903 regs
.isr
&= ~ISR_TXIDLE
;
905 if (interrupts
& ISR_TXERR
)
906 regs
.isr
&= ~ISR_TXERR
;
908 if (interrupts
& ISR_TXDESC
)
909 regs
.isr
&= ~ISR_TXDESC
;
911 if (interrupts
& ISR_TXOK
)
912 regs
.isr
&= ~ISR_TXOK
;
914 if (interrupts
& ISR_RXORN
)
915 regs
.isr
&= ~ISR_RXORN
;
917 if (interrupts
& ISR_RXIDLE
)
918 regs
.isr
&= ~ISR_RXIDLE
;
920 //ISR_RXEARLY not implemented
922 if (interrupts
& ISR_RXERR
)
923 regs
.isr
&= ~ISR_RXERR
;
925 if (interrupts
& ISR_RXDESC
)
926 regs
.isr
&= ~ISR_RXDESC
;
928 if (interrupts
& ISR_RXOK
)
929 regs
.isr
&= ~ISR_RXOK
;
931 if (!(regs
.isr
& regs
.imr
))
934 DPRINTF(Ethernet
, "interrupt cleared intr=%x isr=%x imr=%x\n",
935 interrupts
, regs
.isr
, regs
.imr
);
939 NSGigE::devIntrChangeMask()
941 DPRINTF(Ethernet
, "interrupt mask changed\n");
943 if (regs
.isr
& regs
.imr
)
944 cpuIntrPost(curTick
);
950 NSGigE::cpuIntrPost(Tick when
)
952 if (when
> intrTick
&& intrTick
!= 0)
962 if (when
< curTick
) {
965 intrEvent
= new IntrEvent(this, true);
966 intrEvent
->schedule(intrTick
);
971 NSGigE::cpuInterrupt()
973 // Don't send an interrupt if there's already one
977 // Don't send an interrupt if it's supposed to be delayed
978 if (intrTick
> curTick
)
981 // Whether or not there's a pending interrupt, we don't care about
987 cpuPendingIntr
= true;
988 /** @todo rework the intctrl to be tsunami ok */
989 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
990 tsunami
->cchip
->postDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
994 NSGigE::cpuIntrClear()
996 if (cpuPendingIntr
) {
997 cpuPendingIntr
= false;
998 /** @todo rework the intctrl to be tsunami ok */
999 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
1000 tsunami
->cchip
->clearDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
1005 NSGigE::cpuIntrPending() const
1006 { return cpuPendingIntr
; }
1012 DPRINTF(Ethernet
, "transmit reset\n");
1016 txFifoAvail
= MAX_TX_FIFO_SIZE
;
1019 assert(txDescCnt
== 0);
1021 regs
.command
&= ~CR_TXE
;
1023 assert(txDmaState
== dmaIdle
);
1029 DPRINTF(Ethernet
, "receive reset\n");
1032 assert(rxPktBytes
== 0);
1036 assert(rxDescCnt
== 0);
1037 assert(rxDmaState
== dmaIdle
);
1039 regs
.command
&= ~CR_RXE
;
1044 NSGigE::rxDmaReadCopy()
1046 assert(rxDmaState
== dmaReading
);
1048 memcpy(rxDmaData
, physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaLen
);
1049 rxDmaState
= dmaIdle
;
1051 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1052 rxDmaAddr
, rxDmaLen
);
1053 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1057 NSGigE::doRxDmaRead()
1059 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1060 rxDmaState
= dmaReading
;
1062 if (dmaInterface
&& !rxDmaFree
) {
1063 if (dmaInterface
->busy())
1064 rxDmaState
= dmaReadWaiting
;
1066 dmaInterface
->doDMA(Read
, rxDmaAddr
, rxDmaLen
, curTick
,
1071 if (dmaReadDelay
== 0 && dmaReadFactor
== 0) {
1076 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1077 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1078 rxDmaReadEvent
.schedule(start
);
1083 NSGigE::rxDmaReadDone()
1085 assert(rxDmaState
== dmaReading
);
1088 // If the transmit state machine has a pending DMA, let it go first
1089 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1096 NSGigE::rxDmaWriteCopy()
1098 assert(rxDmaState
== dmaWriting
);
1100 memcpy(physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaData
, rxDmaLen
);
1101 rxDmaState
= dmaIdle
;
1103 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1104 rxDmaAddr
, rxDmaLen
);
1105 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1109 NSGigE::doRxDmaWrite()
1111 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1112 rxDmaState
= dmaWriting
;
1114 if (dmaInterface
&& !rxDmaFree
) {
1115 if (dmaInterface
->busy())
1116 rxDmaState
= dmaWriteWaiting
;
1118 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
, curTick
,
1123 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0) {
1128 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1129 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1130 rxDmaWriteEvent
.schedule(start
);
1135 NSGigE::rxDmaWriteDone()
1137 assert(rxDmaState
== dmaWriting
);
1140 // If the transmit state machine has a pending DMA, let it go first
1141 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1150 DPRINTF(Ethernet
, "receive kick state=%s (rxBuf.size=%d)\n",
1151 NsRxStateStrings
[rxState
], rxFifo
.size());
1153 if (rxKickTick
> curTick
) {
1154 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1160 switch(rxDmaState
) {
1161 case dmaReadWaiting
:
1165 case dmaWriteWaiting
:
1173 // see state machine from spec for details
1174 // the way this works is, if you finish work on one state and can go directly to
1175 // another, you do that through jumping to the label "next". however, if you have
1176 // intermediate work, like DMA so that you can't go to the next state yet, you go to
1177 // exit and exit the loop. however, when the DMA is done it will trigger an
1178 // event and come back to this loop.
1181 if (!regs
.command
& CR_RXE
) {
1182 DPRINTF(Ethernet
, "Receive Disabled! Nothing to do.\n");
1187 rxState
= rxDescRefr
;
1189 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1190 rxDmaData
= &rxDescCache
+ offsetof(ns_desc
, link
);
1191 rxDmaLen
= sizeof(rxDescCache
.link
);
1192 rxDmaFree
= dmaDescFree
;
1197 rxState
= rxDescRead
;
1199 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1200 rxDmaData
= &rxDescCache
;
1201 rxDmaLen
= sizeof(ns_desc
);
1202 rxDmaFree
= dmaDescFree
;
1210 if (rxDmaState
!= dmaIdle
)
1213 rxState
= rxAdvance
;
1217 if (rxDmaState
!= dmaIdle
)
1221 "rxDescCache:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1222 ,rxDescCache
.link
, rxDescCache
.bufptr
, rxDescCache
.cmdsts
,
1223 rxDescCache
.extsts
);
1225 if (rxDescCache
.cmdsts
& CMDSTS_OWN
) {
1228 rxState
= rxFifoBlock
;
1229 rxFragPtr
= rxDescCache
.bufptr
;
1230 rxDescCnt
= rxDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1237 * @todo in reality, we should be able to start processing
1238 * the packet as it arrives, and not have to wait for the
1239 * full packet ot be in the receive fifo.
1244 // If we don't have a packet, grab a new one from the fifo.
1245 rxPacket
= rxFifo
.front();
1246 rxPktBytes
= rxPacket
->length
;
1247 rxPacketBufPtr
= rxPacket
->data
;
1249 // sanity check - i think the driver behaves like this
1250 assert(rxDescCnt
>= rxPktBytes
);
1252 // Must clear the value before popping to decrement the
1254 rxFifo
.front() = NULL
;
1259 // dont' need the && rxDescCnt > 0 if driver sanity check above holds
1260 if (rxPktBytes
> 0) {
1261 rxState
= rxFragWrite
;
1262 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds
1263 rxXferLen
= rxPktBytes
;
1265 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1266 rxDmaData
= rxPacketBufPtr
;
1267 rxDmaLen
= rxXferLen
;
1268 rxDmaFree
= dmaDataFree
;
1274 rxState
= rxDescWrite
;
1276 //if (rxPktBytes == 0) { /* packet is done */
1277 assert(rxPktBytes
== 0);
1279 rxDescCache
.cmdsts
|= CMDSTS_OWN
;
1280 rxDescCache
.cmdsts
&= ~CMDSTS_MORE
;
1281 rxDescCache
.cmdsts
|= CMDSTS_OK
;
1282 rxDescCache
.cmdsts
&= 0xffff0000;
1283 rxDescCache
.cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1286 /* all the driver uses these are for its own stats keeping
1287 which we don't care about, aren't necessary for functionality
1288 and doing this would just slow us down. if they end up using
1289 this in a later version for functional purposes, just undef
1291 if (rxFilterEnable
) {
1292 rxDescCache
.cmdsts
&= ~CMDSTS_DEST_MASK
;
1293 if (rxFifo
.front()->IsUnicast())
1294 rxDescCache
.cmdsts
|= CMDSTS_DEST_SELF
;
1295 if (rxFifo
.front()->IsMulticast())
1296 rxDescCache
.cmdsts
|= CMDSTS_DEST_MULTI
;
1297 if (rxFifo
.front()->IsBroadcast())
1298 rxDescCache
.cmdsts
|= CMDSTS_DEST_MASK
;
1302 if (rxPacket
->isIpPkt() && extstsEnable
) { rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1303 if (!ipChecksum(rxPacket
, false))
1304 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1306 if (rxPacket
->isTcpPkt()) {
1307 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1308 if (!tcpChecksum(rxPacket
, false))
1309 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1310 } else if (rxPacket
->isUdpPkt()) {
1311 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1312 if (!udpChecksum(rxPacket
, false))
1313 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1317 rxFifoCnt
-= rxPacket
->length
;
1320 /* the driver seems to always receive into desc buffers
1321 of size 1514, so you never have a pkt that is split
1322 into multiple descriptors on the receive side, so
1323 i don't implement that case, hence the assert above.
1326 DPRINTF(Ethernet
, "rxDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1327 rxDescCache
.cmdsts
, rxDescCache
.extsts
);
1329 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1330 rxDmaData
= &(rxDescCache
.cmdsts
);
1331 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1332 rxDmaFree
= dmaDescFree
;
1340 if (rxDmaState
!= dmaIdle
)
1343 rxPacketBufPtr
+= rxXferLen
;
1344 rxFragPtr
+= rxXferLen
;
1345 rxPktBytes
-= rxXferLen
;
1347 rxState
= rxFifoBlock
;
1351 if (rxDmaState
!= dmaIdle
)
1354 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1356 assert(rxPacket
== 0);
1357 devIntrPost(ISR_RXOK
);
1359 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1360 devIntrPost(ISR_RXDESC
);
1366 rxState
= rxAdvance
;
1370 if (rxDescCache
.link
== 0) {
1374 rxState
= rxDescRead
;
1375 regs
.rxdp
= rxDescCache
.link
;
1378 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1379 rxDmaData
= &rxDescCache
;
1380 rxDmaLen
= sizeof(ns_desc
);
1381 rxDmaFree
= dmaDescFree
;
1389 panic("Invalid rxState!");
1393 DPRINTF(Ethernet
, "entering next rx state = %s\n",
1394 NsRxStateStrings
[rxState
]);
1396 if (rxState
== rxIdle
) {
1397 regs
.command
&= ~CR_RXE
;
1398 devIntrPost(ISR_RXIDLE
);
1406 * @todo do we want to schedule a future kick?
1408 DPRINTF(Ethernet
, "rx state machine exited state=%s\n",
1409 NsRxStateStrings
[rxState
]);
1415 if (txFifo
.empty()) {
1416 DPRINTF(Ethernet
, "nothing to transmit\n");
1420 if (interface
->sendPacket(txFifo
.front())) {
1421 DPRINTF(Ethernet
, "transmit packet\n");
1422 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1423 txBytes
+= txFifo
.front()->length
;
1426 txFifoCnt
-= (txFifo
.front()->length
- txPktXmitted
);
1428 txFifo
.front() = NULL
;
1431 /* normally do a writeback of the descriptor here, and ONLY after that is
1432 done, send this interrupt. but since our stuff never actually fails,
1433 just do this interrupt here, otherwise the code has to stray from this
1434 nice format. besides, it's functionally the same.
1436 devIntrPost(ISR_TXOK
);
1439 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1440 DPRINTF(Ethernet
, "reschedule transmit\n");
1441 txEvent
.schedule(curTick
+ 1000);
1446 NSGigE::txDmaReadCopy()
1448 assert(txDmaState
== dmaReading
);
1450 memcpy(txDmaData
, physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaLen
);
1451 txDmaState
= dmaIdle
;
1453 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1454 txDmaAddr
, txDmaLen
);
1455 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1459 NSGigE::doTxDmaRead()
1461 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1462 txDmaState
= dmaReading
;
1464 if (dmaInterface
&& !txDmaFree
) {
1465 if (dmaInterface
->busy())
1466 txDmaState
= dmaReadWaiting
;
1468 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1473 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1478 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1479 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1480 txDmaReadEvent
.schedule(start
);
1485 NSGigE::txDmaReadDone()
1487 assert(txDmaState
== dmaReading
);
1490 // If the receive state machine has a pending DMA, let it go first
1491 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1498 NSGigE::txDmaWriteCopy()
1500 assert(txDmaState
== dmaWriting
);
1502 memcpy(physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaData
, txDmaLen
);
1503 txDmaState
= dmaIdle
;
1505 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1506 txDmaAddr
, txDmaLen
);
1507 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1511 NSGigE::doTxDmaWrite()
1513 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1514 txDmaState
= dmaWriting
;
1516 if (dmaInterface
&& !txDmaFree
) {
1517 if (dmaInterface
->busy())
1518 txDmaState
= dmaWriteWaiting
;
1520 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1525 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1530 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1531 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1532 txDmaWriteEvent
.schedule(start
);
1537 NSGigE::txDmaWriteDone()
1539 assert(txDmaState
== dmaWriting
);
1542 // If the receive state machine has a pending DMA, let it go first
1543 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1552 DPRINTF(Ethernet
, "transmit kick state=%s\n", NsTxStateStrings
[txState
]);
1554 if (rxKickTick
> curTick
) {
1555 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1562 switch(txDmaState
) {
1563 case dmaReadWaiting
:
1567 case dmaWriteWaiting
:
1577 if (!regs
.command
& CR_TXE
) {
1578 DPRINTF(Ethernet
, "Transmit disabled. Nothing to do.\n");
1583 txState
= txDescRefr
;
1585 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1586 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1587 txDmaLen
= sizeof(txDescCache
.link
);
1588 txDmaFree
= dmaDescFree
;
1594 txState
= txDescRead
;
1596 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1597 txDmaData
= &txDescCache
;
1598 txDmaLen
= sizeof(ns_desc
);
1599 txDmaFree
= dmaDescFree
;
1607 if (txDmaState
!= dmaIdle
)
1610 txState
= txAdvance
;
1614 if (txDmaState
!= dmaIdle
)
1618 "txDescCache data:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1619 ,txDescCache
.link
, txDescCache
.bufptr
, txDescCache
.cmdsts
,
1620 txDescCache
.extsts
);
1622 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1623 txState
= txFifoBlock
;
1624 txFragPtr
= txDescCache
.bufptr
;
1625 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1633 DPRINTF(Ethernet
, "starting the tx of a new packet\n");
1634 txPacket
= new EtherPacket
;
1635 txPacket
->data
= new uint8_t[16384];
1636 txPacketBufPtr
= txPacket
->data
;
1639 if (txDescCnt
== 0) {
1640 DPRINTF(Ethernet
, "the txDescCnt == 0, done with descriptor\n");
1641 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1642 DPRINTF(Ethernet
, "there are more descriptors to come\n");
1643 txState
= txDescWrite
;
1645 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1647 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1648 txDmaData
= &(txDescCache
.cmdsts
);
1649 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1650 txDmaFree
= dmaDescFree
;
1655 } else { /* this packet is totally done */
1656 DPRINTF(Ethernet
, "This packet is done, let's wrap it up\n");
1657 /* deal with the the packet that just finished */
1658 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1659 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1660 udpChecksum(txPacket
, true);
1661 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1662 tcpChecksum(txPacket
, true);
1663 } else if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1664 ipChecksum(txPacket
, true);
1668 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1669 /* this is just because the receive can't handle a packet bigger
1670 want to make sure */
1671 assert(txPacket
->length
<= 1514);
1672 txFifo
.push_back(txPacket
);
1675 /* this following section is not to spec, but functionally shouldn't
1676 be any different. normally, the chip will wait til the transmit has
1677 occurred before writing back the descriptor because it has to wait
1678 to see that it was successfully transmitted to decide whether to set
1679 CMDSTS_OK or not. however, in the simulator since it is always
1680 successfully transmitted, and writing it exactly to spec would
1681 complicate the code, we just do it here
1683 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1684 txDescCache
.cmdsts
|= CMDSTS_OK
;
1687 "txDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1688 txDescCache
.cmdsts
, txDescCache
.extsts
);
1690 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1691 txDmaData
= &(txDescCache
.cmdsts
);
1692 txDmaLen
= sizeof(txDescCache
.cmdsts
) + sizeof(txDescCache
.extsts
);
1693 txDmaFree
= dmaDescFree
;
1705 txState
= txAdvance
;
1708 DPRINTF(Ethernet
, "this descriptor isn't done yet\n");
1709 /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
1710 value, shift left by 5 to get the real number of bytes */
1711 if (txFifoAvail
< ((regs
.txcfg
& TXCFG_FLTH_MASK
) >> 3)) {
1712 DPRINTF(Ethernet
, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
1713 txFifoAvail
, regs
.txcfg
& TXCFG_FLTH_MASK
);
1717 txState
= txFragRead
;
1719 /* The number of bytes transferred is either whatever is left
1720 in the descriptor (txDescCnt), or if there is not enough
1721 room in the fifo, just whatever room is left in the fifo
1723 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1725 txDmaAddr
= txFragPtr
& 0x3fffffff;
1726 txDmaData
= txPacketBufPtr
;
1727 txDmaLen
= txXferLen
;
1728 txDmaFree
= dmaDataFree
;
1736 if (txDmaState
!= dmaIdle
)
1739 txPacketBufPtr
+= txXferLen
;
1740 txFragPtr
+= txXferLen
;
1741 txFifoCnt
+= txXferLen
;
1742 txDescCnt
-= txXferLen
;
1744 txState
= txFifoBlock
;
1748 if (txDmaState
!= dmaIdle
)
1751 if (txFifoCnt
>= ((regs
.txcfg
& TXCFG_DRTH_MASK
) << 5)) {
1752 if (txFifo
.empty()) {
1753 uint32_t xmitted
= (uint32_t) (txPacketBufPtr
- txPacket
->data
- txPktXmitted
);
1754 txFifoCnt
-= xmitted
;
1755 txPktXmitted
+= xmitted
;
1761 if (txDescCache
.cmdsts
& CMDSTS_INTR
) {
1762 devIntrPost(ISR_TXDESC
);
1765 txState
= txAdvance
;
1769 if (txDescCache
.link
== 0) {
1772 txState
= txDescRead
;
1773 regs
.txdp
= txDescCache
.link
;
1776 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1777 txDmaData
= &txDescCache
;
1778 txDmaLen
= sizeof(ns_desc
);
1779 txDmaFree
= dmaDescFree
;
1787 panic("invalid state");
1790 DPRINTF(Ethernet
, "entering next tx state=%s\n",
1791 NsTxStateStrings
[txState
]);
1793 if (txState
== txIdle
) {
1794 regs
.command
&= ~CR_TXE
;
1795 devIntrPost(ISR_TXIDLE
);
1803 * @todo do we want to schedule a future kick?
1805 DPRINTF(Ethernet
, "tx state machine exited state=%s\n",
1806 NsTxStateStrings
[txState
]);
1810 NSGigE::transferDone()
1815 DPRINTF(Ethernet
, "schedule transmit\n");
1817 if (txEvent
.scheduled())
1818 txEvent
.reschedule(curTick
+ 1);
1820 txEvent
.schedule(curTick
+ 1);
1824 NSGigE::rxFilter(PacketPtr packet
)
1829 if (packet
->IsUnicast()) {
1832 // If we're accepting all unicast addresses
1836 // If we make a perfect match
1838 && (memcmp(rom
.perfectMatch
, packet
->data
, sizeof(rom
.perfectMatch
)) == 0))
1841 eth_header
*eth
= (eth_header
*) packet
->data
;
1842 if ((acceptArp
) && (eth
->type
== 0x806))
1845 } else if (packet
->IsBroadcast()) {
1848 // if we're accepting broadcasts
1849 if (acceptBroadcast
)
1852 } else if (packet
->IsMulticast()) {
1855 // if we're accepting all multicasts
1856 if (acceptMulticast
)
1862 // oh well, punt on this one
1866 DPRINTF(Ethernet
, "rxFilter drop\n");
1867 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1874 NSGigE::recvPacket(PacketPtr packet
)
1876 rxBytes
+= packet
->length
;
1879 if (rxState
== rxIdle
) {
1880 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1881 interface
->recvDone();
1885 if (rxFilterEnable
&& rxFilter(packet
)) {
1886 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1887 interface
->recvDone();
1891 if (rxFifoCnt
+ packet
->length
>= MAX_RX_FIFO_SIZE
) {
1893 "packet will not fit in receive buffer...packet dropped\n");
1894 devIntrPost(ISR_RXORN
);
1898 rxFifo
.push_back(packet
);
1899 rxFifoCnt
+= packet
->length
;
1900 interface
->recvDone();
1907 * does a udp checksum. if gen is true, then it generates it and puts it in the right place
1908 * else, it just checks what it calculates against the value in the header in packet
1911 NSGigE::udpChecksum(PacketPtr packet
, bool gen
)
1913 ip_header
*ip
= packet
->getIpHdr();
1914 udp_header
*hdr
= packet
->getUdpHdr(ip
);
1916 pseudo_header
*pseudo
= new pseudo_header
;
1918 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1919 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1920 pseudo
->protocol
= ip
->protocol
;
1921 pseudo
->len
= hdr
->len
;
1923 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1924 (uint32_t) hdr
->len
);
1928 hdr
->chksum
= cksum
;
1937 NSGigE::tcpChecksum(PacketPtr packet
, bool gen
)
1939 ip_header
*ip
= packet
->getIpHdr();
1940 tcp_header
*hdr
= packet
->getTcpHdr(ip
);
1942 pseudo_header
*pseudo
= new pseudo_header
;
1944 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1945 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1946 pseudo
->protocol
= ip
->protocol
;
1947 pseudo
->len
= ip
->dgram_len
- (ip
->vers_len
& 0xf);
1949 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1950 (uint32_t) pseudo
->len
);
1954 hdr
->chksum
= cksum
;
1963 NSGigE::ipChecksum(PacketPtr packet
, bool gen
)
1965 ip_header
*hdr
= packet
->getIpHdr();
1967 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
, (hdr
->vers_len
& 0xf));
1970 hdr
->hdr_chksum
= cksum
;
1979 NSGigE::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
1983 uint16_t last_pad
= 0;
1985 last_pad
= buf
[len
/2] & 0xff;
1991 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
1992 pseudo
[3] + pseudo
[4] + pseudo
[5];
1995 for (int i
=0; i
< (len
/2); ++i
) {
2000 sum
= (sum
>> 16) + (sum
& 0xffff);
2005 //=====================================================================
2009 NSGigE::serialize(ostream
&os
)
2011 // Serialize the PciDev base class
2012 PciDev::serialize(os
);
2015 * Finalize any DMA events now.
2017 if (rxDmaReadEvent
.scheduled())
2019 if (rxDmaWriteEvent
.scheduled())
2021 if (txDmaReadEvent
.scheduled())
2023 if (txDmaWriteEvent
.scheduled())
2027 * Serialize the device registers
2029 SERIALIZE_SCALAR(regs
.command
);
2030 SERIALIZE_SCALAR(regs
.config
);
2031 SERIALIZE_SCALAR(regs
.mear
);
2032 SERIALIZE_SCALAR(regs
.ptscr
);
2033 SERIALIZE_SCALAR(regs
.isr
);
2034 SERIALIZE_SCALAR(regs
.imr
);
2035 SERIALIZE_SCALAR(regs
.ier
);
2036 SERIALIZE_SCALAR(regs
.ihr
);
2037 SERIALIZE_SCALAR(regs
.txdp
);
2038 SERIALIZE_SCALAR(regs
.txdp_hi
);
2039 SERIALIZE_SCALAR(regs
.txcfg
);
2040 SERIALIZE_SCALAR(regs
.gpior
);
2041 SERIALIZE_SCALAR(regs
.rxdp
);
2042 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2043 SERIALIZE_SCALAR(regs
.rxcfg
);
2044 SERIALIZE_SCALAR(regs
.pqcr
);
2045 SERIALIZE_SCALAR(regs
.wcsr
);
2046 SERIALIZE_SCALAR(regs
.pcr
);
2047 SERIALIZE_SCALAR(regs
.rfcr
);
2048 SERIALIZE_SCALAR(regs
.rfdr
);
2049 SERIALIZE_SCALAR(regs
.srr
);
2050 SERIALIZE_SCALAR(regs
.mibc
);
2051 SERIALIZE_SCALAR(regs
.vrcr
);
2052 SERIALIZE_SCALAR(regs
.vtcr
);
2053 SERIALIZE_SCALAR(regs
.vdr
);
2054 SERIALIZE_SCALAR(regs
.ccsr
);
2055 SERIALIZE_SCALAR(regs
.tbicr
);
2056 SERIALIZE_SCALAR(regs
.tbisr
);
2057 SERIALIZE_SCALAR(regs
.tanar
);
2058 SERIALIZE_SCALAR(regs
.tanlpar
);
2059 SERIALIZE_SCALAR(regs
.taner
);
2060 SERIALIZE_SCALAR(regs
.tesr
);
2062 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2065 * Serialize the various helper variables
2067 uint32_t txPktBufPtr
= (uint32_t) txPacketBufPtr
;
2068 SERIALIZE_SCALAR(txPktBufPtr
);
2069 uint32_t rxPktBufPtr
= (uint32_t) rxPktBufPtr
;
2070 SERIALIZE_SCALAR(rxPktBufPtr
);
2071 SERIALIZE_SCALAR(txXferLen
);
2072 SERIALIZE_SCALAR(rxXferLen
);
2073 SERIALIZE_SCALAR(txPktXmitted
);
2075 bool txPacketExists
= txPacket
;
2076 SERIALIZE_SCALAR(txPacketExists
);
2077 bool rxPacketExists
= rxPacket
;
2078 SERIALIZE_SCALAR(rxPacketExists
);
2081 * Serialize DescCaches
2083 SERIALIZE_SCALAR(txDescCache
.link
);
2084 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2085 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2086 SERIALIZE_SCALAR(txDescCache
.extsts
);
2087 SERIALIZE_SCALAR(rxDescCache
.link
);
2088 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2089 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2090 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2093 * Serialize tx state machine
2095 int txNumPkts
= txFifo
.size();
2096 SERIALIZE_SCALAR(txNumPkts
);
2097 int txState
= this->txState
;
2098 SERIALIZE_SCALAR(txState
);
2099 SERIALIZE_SCALAR(CTDD
);
2100 SERIALIZE_SCALAR(txFifoCnt
);
2101 SERIALIZE_SCALAR(txFifoAvail
);
2102 SERIALIZE_SCALAR(txHalt
);
2103 SERIALIZE_SCALAR(txFragPtr
);
2104 SERIALIZE_SCALAR(txDescCnt
);
2105 int txDmaState
= this->txDmaState
;
2106 SERIALIZE_SCALAR(txDmaState
);
2109 * Serialize rx state machine
2111 int rxNumPkts
= rxFifo
.size();
2112 SERIALIZE_SCALAR(rxNumPkts
);
2113 int rxState
= this->rxState
;
2114 SERIALIZE_SCALAR(rxState
);
2115 SERIALIZE_SCALAR(CRDD
);
2116 SERIALIZE_SCALAR(rxPktBytes
);
2117 SERIALIZE_SCALAR(rxFifoCnt
);
2118 SERIALIZE_SCALAR(rxHalt
);
2119 SERIALIZE_SCALAR(rxDescCnt
);
2120 int rxDmaState
= this->rxDmaState
;
2121 SERIALIZE_SCALAR(rxDmaState
);
2123 SERIALIZE_SCALAR(extstsEnable
);
2126 * If there's a pending transmit, store the time so we can
2127 * reschedule it later
2129 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2130 SERIALIZE_SCALAR(transmitTick
);
2133 * Keep track of pending interrupt status.
2135 SERIALIZE_SCALAR(intrTick
);
2136 SERIALIZE_SCALAR(cpuPendingIntr
);
2137 Tick intrEventTick
= 0;
2139 intrEventTick
= intrEvent
->when();
2140 SERIALIZE_SCALAR(intrEventTick
);
2143 for (pktiter_t p
= rxFifo
.begin(); p
!= rxFifo
.end(); ++p
) {
2144 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2145 (*p
)->serialize(os
);
2147 if (rxPacketExists
) {
2148 nameOut(os
, csprintf("%s.rxPacket", name()));
2149 rxPacket
->serialize(os
);
2152 for (pktiter_t p
= txFifo
.begin(); p
!= txFifo
.end(); ++p
) {
2153 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2154 (*p
)->serialize(os
);
2156 if (txPacketExists
) {
2157 nameOut(os
, csprintf("%s.txPacket", name()));
2158 txPacket
->serialize(os
);
2163 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2165 // Unserialize the PciDev base class
2166 PciDev::unserialize(cp
, section
);
2168 UNSERIALIZE_SCALAR(regs
.command
);
2169 UNSERIALIZE_SCALAR(regs
.config
);
2170 UNSERIALIZE_SCALAR(regs
.mear
);
2171 UNSERIALIZE_SCALAR(regs
.ptscr
);
2172 UNSERIALIZE_SCALAR(regs
.isr
);
2173 UNSERIALIZE_SCALAR(regs
.imr
);
2174 UNSERIALIZE_SCALAR(regs
.ier
);
2175 UNSERIALIZE_SCALAR(regs
.ihr
);
2176 UNSERIALIZE_SCALAR(regs
.txdp
);
2177 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2178 UNSERIALIZE_SCALAR(regs
.txcfg
);
2179 UNSERIALIZE_SCALAR(regs
.gpior
);
2180 UNSERIALIZE_SCALAR(regs
.rxdp
);
2181 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2182 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2183 UNSERIALIZE_SCALAR(regs
.pqcr
);
2184 UNSERIALIZE_SCALAR(regs
.wcsr
);
2185 UNSERIALIZE_SCALAR(regs
.pcr
);
2186 UNSERIALIZE_SCALAR(regs
.rfcr
);
2187 UNSERIALIZE_SCALAR(regs
.rfdr
);
2188 UNSERIALIZE_SCALAR(regs
.srr
);
2189 UNSERIALIZE_SCALAR(regs
.mibc
);
2190 UNSERIALIZE_SCALAR(regs
.vrcr
);
2191 UNSERIALIZE_SCALAR(regs
.vtcr
);
2192 UNSERIALIZE_SCALAR(regs
.vdr
);
2193 UNSERIALIZE_SCALAR(regs
.ccsr
);
2194 UNSERIALIZE_SCALAR(regs
.tbicr
);
2195 UNSERIALIZE_SCALAR(regs
.tbisr
);
2196 UNSERIALIZE_SCALAR(regs
.tanar
);
2197 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2198 UNSERIALIZE_SCALAR(regs
.taner
);
2199 UNSERIALIZE_SCALAR(regs
.tesr
);
2201 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2204 * unserialize the various helper variables
2206 uint32_t txPktBufPtr
;
2207 UNSERIALIZE_SCALAR(txPktBufPtr
);
2208 txPacketBufPtr
= (uint8_t *) txPktBufPtr
;
2209 uint32_t rxPktBufPtr
;
2210 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2211 rxPacketBufPtr
= (uint8_t *) rxPktBufPtr
;
2212 UNSERIALIZE_SCALAR(txXferLen
);
2213 UNSERIALIZE_SCALAR(rxXferLen
);
2214 UNSERIALIZE_SCALAR(txPktXmitted
);
2216 bool txPacketExists
;
2217 UNSERIALIZE_SCALAR(txPacketExists
);
2218 bool rxPacketExists
;
2219 UNSERIALIZE_SCALAR(rxPacketExists
);
2222 * Unserialize DescCaches
2224 UNSERIALIZE_SCALAR(txDescCache
.link
);
2225 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2226 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2227 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2228 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2229 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2230 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2231 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2234 * unserialize tx state machine
2237 UNSERIALIZE_SCALAR(txNumPkts
);
2239 UNSERIALIZE_SCALAR(txState
);
2240 this->txState
= (TxState
) txState
;
2241 UNSERIALIZE_SCALAR(CTDD
);
2242 UNSERIALIZE_SCALAR(txFifoCnt
);
2243 UNSERIALIZE_SCALAR(txFifoAvail
);
2244 UNSERIALIZE_SCALAR(txHalt
);
2245 UNSERIALIZE_SCALAR(txFragPtr
);
2246 UNSERIALIZE_SCALAR(txDescCnt
);
2248 UNSERIALIZE_SCALAR(txDmaState
);
2249 this->txDmaState
= (DmaState
) txDmaState
;
2252 * unserialize rx state machine
2255 UNSERIALIZE_SCALAR(rxNumPkts
);
2257 UNSERIALIZE_SCALAR(rxState
);
2258 this->rxState
= (RxState
) rxState
;
2259 UNSERIALIZE_SCALAR(CRDD
);
2260 UNSERIALIZE_SCALAR(rxPktBytes
);
2261 UNSERIALIZE_SCALAR(rxFifoCnt
);
2262 UNSERIALIZE_SCALAR(rxHalt
);
2263 UNSERIALIZE_SCALAR(rxDescCnt
);
2265 UNSERIALIZE_SCALAR(rxDmaState
);
2266 this->rxDmaState
= (DmaState
) rxDmaState
;
2268 UNSERIALIZE_SCALAR(extstsEnable
);
2271 * If there's a pending transmit, store the time so we can
2272 * reschedule it later
2275 UNSERIALIZE_SCALAR(transmitTick
);
2277 txEvent
.schedule(curTick
+ transmitTick
);
2280 * Keep track of pending interrupt status.
2282 UNSERIALIZE_SCALAR(intrTick
);
2283 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2285 UNSERIALIZE_SCALAR(intrEventTick
);
2286 if (intrEventTick
) {
2287 intrEvent
= new IntrEvent(this, true);
2288 intrEvent
->schedule(intrEventTick
);
2291 for (int i
= 0; i
< rxNumPkts
; ++i
) {
2292 PacketPtr p
= new EtherPacket
;
2293 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2294 rxFifo
.push_back(p
);
2297 if (rxPacketExists
) {
2298 rxPacket
= new EtherPacket
;
2299 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2301 for (int i
= 0; i
< txNumPkts
; ++i
) {
2302 PacketPtr p
= new EtherPacket
;
2303 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2304 txFifo
.push_back(p
);
2306 if (txPacketExists
) {
2307 txPacket
= new EtherPacket
;
2308 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2314 NSGigE::cacheAccess(MemReqPtr
&req
)
2316 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2317 req
->paddr
, req
->paddr
- addr
);
2318 return curTick
+ pioLatency
;
2320 //=====================================================================
2323 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2325 SimObjectParam
<EtherInt
*> peer
;
2326 SimObjectParam
<NSGigE
*> device
;
2328 END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2330 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2332 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2333 INIT_PARAM(device
, "Ethernet device of this interface")
2335 END_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2337 CREATE_SIM_OBJECT(NSGigEInt
)
2339 NSGigEInt
*dev_int
= new NSGigEInt(getInstanceName(), device
);
2341 EtherInt
*p
= (EtherInt
*)peer
;
2343 dev_int
->setPeer(p
);
2344 p
->setPeer(dev_int
);
2350 REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt
)
2353 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2355 Param
<Tick
> tx_delay
;
2356 Param
<Tick
> rx_delay
;
2357 SimObjectParam
<IntrControl
*> intr_ctrl
;
2358 Param
<Tick
> intr_delay
;
2359 SimObjectParam
<MemoryController
*> mmu
;
2360 SimObjectParam
<PhysicalMemory
*> physmem
;
2361 Param
<bool> rx_filter
;
2362 Param
<string
> hardware_address
;
2363 SimObjectParam
<Bus
*> header_bus
;
2364 SimObjectParam
<Bus
*> payload_bus
;
2365 SimObjectParam
<HierParams
*> hier
;
2366 Param
<Tick
> pio_latency
;
2367 Param
<bool> dma_desc_free
;
2368 Param
<bool> dma_data_free
;
2369 Param
<Tick
> dma_read_delay
;
2370 Param
<Tick
> dma_write_delay
;
2371 Param
<Tick
> dma_read_factor
;
2372 Param
<Tick
> dma_write_factor
;
2373 SimObjectParam
<PciConfigAll
*> configspace
;
2374 SimObjectParam
<PciConfigData
*> configdata
;
2375 SimObjectParam
<Tsunami
*> tsunami
;
2376 Param
<uint32_t> pci_bus
;
2377 Param
<uint32_t> pci_dev
;
2378 Param
<uint32_t> pci_func
;
2380 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2382 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2384 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2385 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2386 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2387 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2388 INIT_PARAM(mmu
, "Memory Controller"),
2389 INIT_PARAM(physmem
, "Physical Memory"),
2390 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2391 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2392 "00:99:00:00:00:01"),
2393 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2394 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2395 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2396 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000),
2397 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2398 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2399 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2400 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2401 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2402 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2403 INIT_PARAM(configspace
, "PCI Configspace"),
2404 INIT_PARAM(configdata
, "PCI Config data"),
2405 INIT_PARAM(tsunami
, "Tsunami"),
2406 INIT_PARAM(pci_bus
, "PCI bus"),
2407 INIT_PARAM(pci_dev
, "PCI device number"),
2408 INIT_PARAM(pci_func
, "PCI function code")
2410 END_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2413 CREATE_SIM_OBJECT(NSGigE
)
2416 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2417 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2419 return new NSGigE(getInstanceName(), intr_ctrl
, intr_delay
,
2420 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2421 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2422 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2423 dma_write_factor
, configspace
, configdata
,
2424 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
);
2427 REGISTER_SIM_OBJECT("NSGigE", NSGigE
)