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 eth_header
*eth
= (eth_header
*) rxPacket
->data
;
1303 // eth->type 0x800 indicated that it's an ip packet.
1304 if (eth
->type
== 0x800 && extstsEnable
) {
1305 rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1306 if (!ipChecksum(rxPacket
, false))
1307 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1308 ip_header
*ip
= rxFifo
.front()->getIpHdr();
1310 if (ip
->protocol
== 6) {
1311 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1312 if (!tcpChecksum(rxPacket
, false))
1313 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1314 } else if (ip
->protocol
== 17) {
1315 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1316 if (!udpChecksum(rxPacket
, false))
1317 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1321 rxFifoCnt
-= rxPacket
->length
;
1324 /* the driver seems to always receive into desc buffers
1325 of size 1514, so you never have a pkt that is split
1326 into multiple descriptors on the receive side, so
1327 i don't implement that case, hence the assert above.
1330 DPRINTF(Ethernet
, "rxDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1331 rxDescCache
.cmdsts
, rxDescCache
.extsts
);
1333 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1334 rxDmaData
= &(rxDescCache
.cmdsts
);
1335 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1336 rxDmaFree
= dmaDescFree
;
1344 if (rxDmaState
!= dmaIdle
)
1347 rxPacketBufPtr
+= rxXferLen
;
1348 rxFragPtr
+= rxXferLen
;
1349 rxPktBytes
-= rxXferLen
;
1351 rxState
= rxFifoBlock
;
1355 if (rxDmaState
!= dmaIdle
)
1358 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1360 assert(rxPacket
== 0);
1361 devIntrPost(ISR_RXOK
);
1363 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1364 devIntrPost(ISR_RXDESC
);
1370 rxState
= rxAdvance
;
1374 if (rxDescCache
.link
== 0) {
1378 rxState
= rxDescRead
;
1379 regs
.rxdp
= rxDescCache
.link
;
1382 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1383 rxDmaData
= &rxDescCache
;
1384 rxDmaLen
= sizeof(ns_desc
);
1385 rxDmaFree
= dmaDescFree
;
1393 panic("Invalid rxState!");
1397 DPRINTF(Ethernet
, "entering next rx state = %s\n",
1398 NsRxStateStrings
[rxState
]);
1400 if (rxState
== rxIdle
) {
1401 regs
.command
&= ~CR_RXE
;
1402 devIntrPost(ISR_RXIDLE
);
1410 * @todo do we want to schedule a future kick?
1412 DPRINTF(Ethernet
, "rx state machine exited state=%s\n",
1413 NsRxStateStrings
[rxState
]);
1419 if (txFifo
.empty()) {
1420 DPRINTF(Ethernet
, "nothing to transmit\n");
1424 if (interface
->sendPacket(txFifo
.front())) {
1425 DPRINTF(Ethernet
, "transmit packet\n");
1426 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1427 txBytes
+= txFifo
.front()->length
;
1430 txFifoCnt
-= (txFifo
.front()->length
- txPktXmitted
);
1432 txFifo
.front() = NULL
;
1435 /* normally do a writeback of the descriptor here, and ONLY after that is
1436 done, send this interrupt. but since our stuff never actually fails,
1437 just do this interrupt here, otherwise the code has to stray from this
1438 nice format. besides, it's functionally the same.
1440 devIntrPost(ISR_TXOK
);
1443 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1444 DPRINTF(Ethernet
, "reschedule transmit\n");
1445 txEvent
.schedule(curTick
+ 1000);
1450 NSGigE::txDmaReadCopy()
1452 assert(txDmaState
== dmaReading
);
1454 memcpy(txDmaData
, physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaLen
);
1455 txDmaState
= dmaIdle
;
1457 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1458 txDmaAddr
, txDmaLen
);
1459 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1463 NSGigE::doTxDmaRead()
1465 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1466 txDmaState
= dmaReading
;
1468 if (dmaInterface
&& !txDmaFree
) {
1469 if (dmaInterface
->busy())
1470 txDmaState
= dmaReadWaiting
;
1472 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1477 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1482 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1483 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1484 txDmaReadEvent
.schedule(start
);
1489 NSGigE::txDmaReadDone()
1491 assert(txDmaState
== dmaReading
);
1494 // If the receive state machine has a pending DMA, let it go first
1495 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1502 NSGigE::txDmaWriteCopy()
1504 assert(txDmaState
== dmaWriting
);
1506 memcpy(physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaData
, txDmaLen
);
1507 txDmaState
= dmaIdle
;
1509 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1510 txDmaAddr
, txDmaLen
);
1511 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1515 NSGigE::doTxDmaWrite()
1517 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1518 txDmaState
= dmaWriting
;
1520 if (dmaInterface
&& !txDmaFree
) {
1521 if (dmaInterface
->busy())
1522 txDmaState
= dmaWriteWaiting
;
1524 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1529 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1534 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1535 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1536 txDmaWriteEvent
.schedule(start
);
1541 NSGigE::txDmaWriteDone()
1543 assert(txDmaState
== dmaWriting
);
1546 // If the receive state machine has a pending DMA, let it go first
1547 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1556 DPRINTF(Ethernet
, "transmit kick state=%s\n", NsTxStateStrings
[txState
]);
1558 if (rxKickTick
> curTick
) {
1559 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1566 switch(txDmaState
) {
1567 case dmaReadWaiting
:
1571 case dmaWriteWaiting
:
1581 if (!regs
.command
& CR_TXE
) {
1582 DPRINTF(Ethernet
, "Transmit disabled. Nothing to do.\n");
1587 txState
= txDescRefr
;
1589 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1590 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1591 txDmaLen
= sizeof(txDescCache
.link
);
1592 txDmaFree
= dmaDescFree
;
1598 txState
= txDescRead
;
1600 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1601 txDmaData
= &txDescCache
;
1602 txDmaLen
= sizeof(ns_desc
);
1603 txDmaFree
= dmaDescFree
;
1611 if (txDmaState
!= dmaIdle
)
1614 txState
= txAdvance
;
1618 if (txDmaState
!= dmaIdle
)
1622 "txDescCache data:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1623 ,txDescCache
.link
, txDescCache
.bufptr
, txDescCache
.cmdsts
,
1624 txDescCache
.extsts
);
1626 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1627 txState
= txFifoBlock
;
1628 txFragPtr
= txDescCache
.bufptr
;
1629 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1637 DPRINTF(Ethernet
, "starting the tx of a new packet\n");
1638 txPacket
= new EtherPacket
;
1639 txPacket
->data
= new uint8_t[16384];
1640 txPacketBufPtr
= txPacket
->data
;
1643 if (txDescCnt
== 0) {
1644 DPRINTF(Ethernet
, "the txDescCnt == 0, done with descriptor\n");
1645 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1646 DPRINTF(Ethernet
, "there are more descriptors to come\n");
1647 txState
= txDescWrite
;
1649 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1651 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1652 txDmaData
= &(txDescCache
.cmdsts
);
1653 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1654 txDmaFree
= dmaDescFree
;
1659 } else { /* this packet is totally done */
1660 DPRINTF(Ethernet
, "This packet is done, let's wrap it up\n");
1661 /* deal with the the packet that just finished */
1662 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1663 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1664 udpChecksum(txPacket
, true);
1665 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1666 tcpChecksum(txPacket
, true);
1667 } else if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1668 ipChecksum(txPacket
, true);
1672 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1673 /* this is just because the receive can't handle a packet bigger
1674 want to make sure */
1675 assert(txPacket
->length
<= 1514);
1676 txFifo
.push_back(txPacket
);
1679 /* this following section is not to spec, but functionally shouldn't
1680 be any different. normally, the chip will wait til the transmit has
1681 occurred before writing back the descriptor because it has to wait
1682 to see that it was successfully transmitted to decide whether to set
1683 CMDSTS_OK or not. however, in the simulator since it is always
1684 successfully transmitted, and writing it exactly to spec would
1685 complicate the code, we just do it here
1687 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1688 txDescCache
.cmdsts
|= CMDSTS_OK
;
1691 "txDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1692 txDescCache
.cmdsts
, txDescCache
.extsts
);
1694 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1695 txDmaData
= &(txDescCache
.cmdsts
);
1696 txDmaLen
= sizeof(txDescCache
.cmdsts
) + sizeof(txDescCache
.extsts
);
1697 txDmaFree
= dmaDescFree
;
1709 txState
= txAdvance
;
1712 DPRINTF(Ethernet
, "this descriptor isn't done yet\n");
1713 /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
1714 value, shift left by 5 to get the real number of bytes */
1715 if (txFifoAvail
< ((regs
.txcfg
& TXCFG_FLTH_MASK
) >> 3)) {
1716 DPRINTF(Ethernet
, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
1717 txFifoAvail
, regs
.txcfg
& TXCFG_FLTH_MASK
);
1721 txState
= txFragRead
;
1723 /* The number of bytes transferred is either whatever is left
1724 in the descriptor (txDescCnt), or if there is not enough
1725 room in the fifo, just whatever room is left in the fifo
1727 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1729 txDmaAddr
= txFragPtr
& 0x3fffffff;
1730 txDmaData
= txPacketBufPtr
;
1731 txDmaLen
= txXferLen
;
1732 txDmaFree
= dmaDataFree
;
1740 if (txDmaState
!= dmaIdle
)
1743 txPacketBufPtr
+= txXferLen
;
1744 txFragPtr
+= txXferLen
;
1745 txFifoCnt
+= txXferLen
;
1746 txDescCnt
-= txXferLen
;
1748 txState
= txFifoBlock
;
1752 if (txDmaState
!= dmaIdle
)
1755 if (txFifoCnt
>= ((regs
.txcfg
& TXCFG_DRTH_MASK
) << 5)) {
1756 if (txFifo
.empty()) {
1757 uint32_t xmitted
= (uint32_t) (txPacketBufPtr
- txPacket
->data
- txPktXmitted
);
1758 txFifoCnt
-= xmitted
;
1759 txPktXmitted
+= xmitted
;
1765 if (txDescCache
.cmdsts
& CMDSTS_INTR
) {
1766 devIntrPost(ISR_TXDESC
);
1769 txState
= txAdvance
;
1773 if (txDescCache
.link
== 0) {
1776 txState
= txDescRead
;
1777 regs
.txdp
= txDescCache
.link
;
1780 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1781 txDmaData
= &txDescCache
;
1782 txDmaLen
= sizeof(ns_desc
);
1783 txDmaFree
= dmaDescFree
;
1791 panic("invalid state");
1794 DPRINTF(Ethernet
, "entering next tx state=%s\n",
1795 NsTxStateStrings
[txState
]);
1797 if (txState
== txIdle
) {
1798 regs
.command
&= ~CR_TXE
;
1799 devIntrPost(ISR_TXIDLE
);
1807 * @todo do we want to schedule a future kick?
1809 DPRINTF(Ethernet
, "tx state machine exited state=%s\n",
1810 NsTxStateStrings
[txState
]);
1814 NSGigE::transferDone()
1819 DPRINTF(Ethernet
, "schedule transmit\n");
1821 if (txEvent
.scheduled())
1822 txEvent
.reschedule(curTick
+ 1);
1824 txEvent
.schedule(curTick
+ 1);
1828 NSGigE::rxFilter(PacketPtr packet
)
1833 if (packet
->IsUnicast()) {
1836 // If we're accepting all unicast addresses
1840 // If we make a perfect match
1842 && (memcmp(rom
.perfectMatch
, packet
->data
, sizeof(rom
.perfectMatch
)) == 0))
1845 eth_header
*eth
= (eth_header
*) packet
->data
;
1846 if ((acceptArp
) && (eth
->type
== 0x806))
1849 } else if (packet
->IsBroadcast()) {
1852 // if we're accepting broadcasts
1853 if (acceptBroadcast
)
1856 } else if (packet
->IsMulticast()) {
1859 // if we're accepting all multicasts
1860 if (acceptMulticast
)
1866 // oh well, punt on this one
1870 DPRINTF(Ethernet
, "rxFilter drop\n");
1871 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1878 NSGigE::recvPacket(PacketPtr packet
)
1880 rxBytes
+= packet
->length
;
1883 if (rxState
== rxIdle
) {
1884 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1885 interface
->recvDone();
1889 if (rxFilterEnable
&& rxFilter(packet
)) {
1890 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1891 interface
->recvDone();
1895 if (rxFifoCnt
+ packet
->length
>= MAX_RX_FIFO_SIZE
) {
1897 "packet will not fit in receive buffer...packet dropped\n");
1898 devIntrPost(ISR_RXORN
);
1902 rxFifo
.push_back(packet
);
1903 rxFifoCnt
+= packet
->length
;
1904 interface
->recvDone();
1911 * does a udp checksum. if gen is true, then it generates it and puts it in the right place
1912 * else, it just checks what it calculates against the value in the header in packet
1915 NSGigE::udpChecksum(PacketPtr packet
, bool gen
)
1917 udp_header
*hdr
= (udp_header
*) packet
->getTransportHdr();
1919 ip_header
*ip
= packet
->getIpHdr();
1921 pseudo_header
*pseudo
= new pseudo_header
;
1923 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1924 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1925 pseudo
->protocol
= ip
->protocol
;
1926 pseudo
->len
= hdr
->len
;
1928 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1929 (uint32_t) hdr
->len
);
1933 hdr
->chksum
= cksum
;
1942 NSGigE::tcpChecksum(PacketPtr packet
, bool gen
)
1944 tcp_header
*hdr
= (tcp_header
*) packet
->getTransportHdr();
1946 ip_header
*ip
= packet
->getIpHdr();
1948 pseudo_header
*pseudo
= new pseudo_header
;
1950 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1951 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1952 pseudo
->protocol
= ip
->protocol
;
1953 pseudo
->len
= ip
->dgram_len
- (ip
->vers_len
& 0xf);
1955 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1956 (uint32_t) pseudo
->len
);
1960 hdr
->chksum
= cksum
;
1969 NSGigE::ipChecksum(PacketPtr packet
, bool gen
)
1971 ip_header
*hdr
= packet
->getIpHdr();
1973 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
, (hdr
->vers_len
& 0xf));
1976 hdr
->hdr_chksum
= cksum
;
1985 NSGigE::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
1989 uint16_t last_pad
= 0;
1991 last_pad
= buf
[len
/2] & 0xff;
1997 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
1998 pseudo
[3] + pseudo
[4] + pseudo
[5];
2001 for (int i
=0; i
< (len
/2); ++i
) {
2006 sum
= (sum
>> 16) + (sum
& 0xffff);
2011 //=====================================================================
2015 NSGigE::serialize(ostream
&os
)
2017 // Serialize the PciDev base class
2018 PciDev::serialize(os
);
2021 * Finalize any DMA events now.
2023 if (rxDmaReadEvent
.scheduled())
2025 if (rxDmaWriteEvent
.scheduled())
2027 if (txDmaReadEvent
.scheduled())
2029 if (txDmaWriteEvent
.scheduled())
2033 * Serialize the device registers
2035 SERIALIZE_SCALAR(regs
.command
);
2036 SERIALIZE_SCALAR(regs
.config
);
2037 SERIALIZE_SCALAR(regs
.mear
);
2038 SERIALIZE_SCALAR(regs
.ptscr
);
2039 SERIALIZE_SCALAR(regs
.isr
);
2040 SERIALIZE_SCALAR(regs
.imr
);
2041 SERIALIZE_SCALAR(regs
.ier
);
2042 SERIALIZE_SCALAR(regs
.ihr
);
2043 SERIALIZE_SCALAR(regs
.txdp
);
2044 SERIALIZE_SCALAR(regs
.txdp_hi
);
2045 SERIALIZE_SCALAR(regs
.txcfg
);
2046 SERIALIZE_SCALAR(regs
.gpior
);
2047 SERIALIZE_SCALAR(regs
.rxdp
);
2048 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2049 SERIALIZE_SCALAR(regs
.rxcfg
);
2050 SERIALIZE_SCALAR(regs
.pqcr
);
2051 SERIALIZE_SCALAR(regs
.wcsr
);
2052 SERIALIZE_SCALAR(regs
.pcr
);
2053 SERIALIZE_SCALAR(regs
.rfcr
);
2054 SERIALIZE_SCALAR(regs
.rfdr
);
2055 SERIALIZE_SCALAR(regs
.srr
);
2056 SERIALIZE_SCALAR(regs
.mibc
);
2057 SERIALIZE_SCALAR(regs
.vrcr
);
2058 SERIALIZE_SCALAR(regs
.vtcr
);
2059 SERIALIZE_SCALAR(regs
.vdr
);
2060 SERIALIZE_SCALAR(regs
.ccsr
);
2061 SERIALIZE_SCALAR(regs
.tbicr
);
2062 SERIALIZE_SCALAR(regs
.tbisr
);
2063 SERIALIZE_SCALAR(regs
.tanar
);
2064 SERIALIZE_SCALAR(regs
.tanlpar
);
2065 SERIALIZE_SCALAR(regs
.taner
);
2066 SERIALIZE_SCALAR(regs
.tesr
);
2068 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2071 * Serialize the various helper variables
2073 uint32_t txPktBufPtr
= (uint32_t) txPacketBufPtr
;
2074 SERIALIZE_SCALAR(txPktBufPtr
);
2075 uint32_t rxPktBufPtr
= (uint32_t) rxPktBufPtr
;
2076 SERIALIZE_SCALAR(rxPktBufPtr
);
2077 SERIALIZE_SCALAR(txXferLen
);
2078 SERIALIZE_SCALAR(rxXferLen
);
2079 SERIALIZE_SCALAR(txPktXmitted
);
2081 bool txPacketExists
= txPacket
;
2082 SERIALIZE_SCALAR(txPacketExists
);
2083 bool rxPacketExists
= rxPacket
;
2084 SERIALIZE_SCALAR(rxPacketExists
);
2087 * Serialize DescCaches
2089 SERIALIZE_SCALAR(txDescCache
.link
);
2090 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2091 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2092 SERIALIZE_SCALAR(txDescCache
.extsts
);
2093 SERIALIZE_SCALAR(rxDescCache
.link
);
2094 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2095 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2096 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2099 * Serialize tx state machine
2101 int txNumPkts
= txFifo
.size();
2102 SERIALIZE_SCALAR(txNumPkts
);
2103 int txState
= this->txState
;
2104 SERIALIZE_SCALAR(txState
);
2105 SERIALIZE_SCALAR(CTDD
);
2106 SERIALIZE_SCALAR(txFifoCnt
);
2107 SERIALIZE_SCALAR(txFifoAvail
);
2108 SERIALIZE_SCALAR(txHalt
);
2109 SERIALIZE_SCALAR(txFragPtr
);
2110 SERIALIZE_SCALAR(txDescCnt
);
2111 int txDmaState
= this->txDmaState
;
2112 SERIALIZE_SCALAR(txDmaState
);
2115 * Serialize rx state machine
2117 int rxNumPkts
= rxFifo
.size();
2118 SERIALIZE_SCALAR(rxNumPkts
);
2119 int rxState
= this->rxState
;
2120 SERIALIZE_SCALAR(rxState
);
2121 SERIALIZE_SCALAR(CRDD
);
2122 SERIALIZE_SCALAR(rxPktBytes
);
2123 SERIALIZE_SCALAR(rxFifoCnt
);
2124 SERIALIZE_SCALAR(rxHalt
);
2125 SERIALIZE_SCALAR(rxDescCnt
);
2126 int rxDmaState
= this->rxDmaState
;
2127 SERIALIZE_SCALAR(rxDmaState
);
2129 SERIALIZE_SCALAR(extstsEnable
);
2132 * If there's a pending transmit, store the time so we can
2133 * reschedule it later
2135 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2136 SERIALIZE_SCALAR(transmitTick
);
2139 * Keep track of pending interrupt status.
2141 SERIALIZE_SCALAR(intrTick
);
2142 SERIALIZE_SCALAR(cpuPendingIntr
);
2143 Tick intrEventTick
= 0;
2145 intrEventTick
= intrEvent
->when();
2146 SERIALIZE_SCALAR(intrEventTick
);
2149 for (pktiter_t p
= rxFifo
.begin(); p
!= rxFifo
.end(); ++p
) {
2150 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2151 (*p
)->serialize(os
);
2153 if (rxPacketExists
) {
2154 nameOut(os
, csprintf("%s.rxPacket", name()));
2155 rxPacket
->serialize(os
);
2158 for (pktiter_t p
= txFifo
.begin(); p
!= txFifo
.end(); ++p
) {
2159 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2160 (*p
)->serialize(os
);
2162 if (txPacketExists
) {
2163 nameOut(os
, csprintf("%s.txPacket", name()));
2164 txPacket
->serialize(os
);
2169 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2171 // Unserialize the PciDev base class
2172 PciDev::unserialize(cp
, section
);
2174 UNSERIALIZE_SCALAR(regs
.command
);
2175 UNSERIALIZE_SCALAR(regs
.config
);
2176 UNSERIALIZE_SCALAR(regs
.mear
);
2177 UNSERIALIZE_SCALAR(regs
.ptscr
);
2178 UNSERIALIZE_SCALAR(regs
.isr
);
2179 UNSERIALIZE_SCALAR(regs
.imr
);
2180 UNSERIALIZE_SCALAR(regs
.ier
);
2181 UNSERIALIZE_SCALAR(regs
.ihr
);
2182 UNSERIALIZE_SCALAR(regs
.txdp
);
2183 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2184 UNSERIALIZE_SCALAR(regs
.txcfg
);
2185 UNSERIALIZE_SCALAR(regs
.gpior
);
2186 UNSERIALIZE_SCALAR(regs
.rxdp
);
2187 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2188 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2189 UNSERIALIZE_SCALAR(regs
.pqcr
);
2190 UNSERIALIZE_SCALAR(regs
.wcsr
);
2191 UNSERIALIZE_SCALAR(regs
.pcr
);
2192 UNSERIALIZE_SCALAR(regs
.rfcr
);
2193 UNSERIALIZE_SCALAR(regs
.rfdr
);
2194 UNSERIALIZE_SCALAR(regs
.srr
);
2195 UNSERIALIZE_SCALAR(regs
.mibc
);
2196 UNSERIALIZE_SCALAR(regs
.vrcr
);
2197 UNSERIALIZE_SCALAR(regs
.vtcr
);
2198 UNSERIALIZE_SCALAR(regs
.vdr
);
2199 UNSERIALIZE_SCALAR(regs
.ccsr
);
2200 UNSERIALIZE_SCALAR(regs
.tbicr
);
2201 UNSERIALIZE_SCALAR(regs
.tbisr
);
2202 UNSERIALIZE_SCALAR(regs
.tanar
);
2203 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2204 UNSERIALIZE_SCALAR(regs
.taner
);
2205 UNSERIALIZE_SCALAR(regs
.tesr
);
2207 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2210 * unserialize the various helper variables
2212 uint32_t txPktBufPtr
;
2213 UNSERIALIZE_SCALAR(txPktBufPtr
);
2214 txPacketBufPtr
= (uint8_t *) txPktBufPtr
;
2215 uint32_t rxPktBufPtr
;
2216 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2217 rxPacketBufPtr
= (uint8_t *) rxPktBufPtr
;
2218 UNSERIALIZE_SCALAR(txXferLen
);
2219 UNSERIALIZE_SCALAR(rxXferLen
);
2220 UNSERIALIZE_SCALAR(txPktXmitted
);
2222 bool txPacketExists
;
2223 UNSERIALIZE_SCALAR(txPacketExists
);
2224 bool rxPacketExists
;
2225 UNSERIALIZE_SCALAR(rxPacketExists
);
2228 * Unserialize DescCaches
2230 UNSERIALIZE_SCALAR(txDescCache
.link
);
2231 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2232 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2233 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2234 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2235 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2236 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2237 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2240 * unserialize tx state machine
2243 UNSERIALIZE_SCALAR(txNumPkts
);
2245 UNSERIALIZE_SCALAR(txState
);
2246 this->txState
= (TxState
) txState
;
2247 UNSERIALIZE_SCALAR(CTDD
);
2248 UNSERIALIZE_SCALAR(txFifoCnt
);
2249 UNSERIALIZE_SCALAR(txFifoAvail
);
2250 UNSERIALIZE_SCALAR(txHalt
);
2251 UNSERIALIZE_SCALAR(txFragPtr
);
2252 UNSERIALIZE_SCALAR(txDescCnt
);
2254 UNSERIALIZE_SCALAR(txDmaState
);
2255 this->txDmaState
= (DmaState
) txDmaState
;
2258 * unserialize rx state machine
2261 UNSERIALIZE_SCALAR(rxNumPkts
);
2263 UNSERIALIZE_SCALAR(rxState
);
2264 this->rxState
= (RxState
) rxState
;
2265 UNSERIALIZE_SCALAR(CRDD
);
2266 UNSERIALIZE_SCALAR(rxPktBytes
);
2267 UNSERIALIZE_SCALAR(rxFifoCnt
);
2268 UNSERIALIZE_SCALAR(rxHalt
);
2269 UNSERIALIZE_SCALAR(rxDescCnt
);
2271 UNSERIALIZE_SCALAR(rxDmaState
);
2272 this->rxDmaState
= (DmaState
) rxDmaState
;
2274 UNSERIALIZE_SCALAR(extstsEnable
);
2277 * If there's a pending transmit, store the time so we can
2278 * reschedule it later
2281 UNSERIALIZE_SCALAR(transmitTick
);
2283 txEvent
.schedule(curTick
+ transmitTick
);
2286 * Keep track of pending interrupt status.
2288 UNSERIALIZE_SCALAR(intrTick
);
2289 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2291 UNSERIALIZE_SCALAR(intrEventTick
);
2292 if (intrEventTick
) {
2293 intrEvent
= new IntrEvent(this, true);
2294 intrEvent
->schedule(intrEventTick
);
2297 for (int i
= 0; i
< rxNumPkts
; ++i
) {
2298 PacketPtr p
= new EtherPacket
;
2299 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2300 rxFifo
.push_back(p
);
2303 if (rxPacketExists
) {
2304 rxPacket
= new EtherPacket
;
2305 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2307 for (int i
= 0; i
< txNumPkts
; ++i
) {
2308 PacketPtr p
= new EtherPacket
;
2309 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2310 txFifo
.push_back(p
);
2312 if (txPacketExists
) {
2313 txPacket
= new EtherPacket
;
2314 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2320 NSGigE::cacheAccess(MemReqPtr
&req
)
2322 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2323 req
->paddr
, req
->paddr
- addr
);
2324 return curTick
+ pioLatency
;
2326 //=====================================================================
2329 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2331 SimObjectParam
<EtherInt
*> peer
;
2332 SimObjectParam
<NSGigE
*> device
;
2334 END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2336 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2338 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2339 INIT_PARAM(device
, "Ethernet device of this interface")
2341 END_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2343 CREATE_SIM_OBJECT(NSGigEInt
)
2345 NSGigEInt
*dev_int
= new NSGigEInt(getInstanceName(), device
);
2347 EtherInt
*p
= (EtherInt
*)peer
;
2349 dev_int
->setPeer(p
);
2350 p
->setPeer(dev_int
);
2356 REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt
)
2359 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2361 Param
<Tick
> tx_delay
;
2362 Param
<Tick
> rx_delay
;
2363 SimObjectParam
<IntrControl
*> intr_ctrl
;
2364 Param
<Tick
> intr_delay
;
2365 SimObjectParam
<MemoryController
*> mmu
;
2366 SimObjectParam
<PhysicalMemory
*> physmem
;
2367 Param
<bool> rx_filter
;
2368 Param
<string
> hardware_address
;
2369 SimObjectParam
<Bus
*> header_bus
;
2370 SimObjectParam
<Bus
*> payload_bus
;
2371 SimObjectParam
<HierParams
*> hier
;
2372 Param
<Tick
> pio_latency
;
2373 Param
<bool> dma_desc_free
;
2374 Param
<bool> dma_data_free
;
2375 Param
<Tick
> dma_read_delay
;
2376 Param
<Tick
> dma_write_delay
;
2377 Param
<Tick
> dma_read_factor
;
2378 Param
<Tick
> dma_write_factor
;
2379 SimObjectParam
<PciConfigAll
*> configspace
;
2380 SimObjectParam
<PciConfigData
*> configdata
;
2381 SimObjectParam
<Tsunami
*> tsunami
;
2382 Param
<uint32_t> pci_bus
;
2383 Param
<uint32_t> pci_dev
;
2384 Param
<uint32_t> pci_func
;
2386 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2388 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2390 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2391 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2392 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2393 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2394 INIT_PARAM(mmu
, "Memory Controller"),
2395 INIT_PARAM(physmem
, "Physical Memory"),
2396 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2397 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2398 "00:99:00:00:00:01"),
2399 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2400 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2401 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2402 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000),
2403 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2404 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2405 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2406 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2407 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2408 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2409 INIT_PARAM(configspace
, "PCI Configspace"),
2410 INIT_PARAM(configdata
, "PCI Config data"),
2411 INIT_PARAM(tsunami
, "Tsunami"),
2412 INIT_PARAM(pci_bus
, "PCI bus"),
2413 INIT_PARAM(pci_dev
, "PCI device number"),
2414 INIT_PARAM(pci_func
, "PCI function code")
2416 END_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2419 CREATE_SIM_OBJECT(NSGigE
)
2422 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2423 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2425 return new NSGigE(getInstanceName(), intr_ctrl
, intr_delay
,
2426 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2427 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2428 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2429 dma_write_factor
, configspace
, configdata
,
2430 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
);
2433 REGISTER_SIM_OBJECT("NSGigE", NSGigE
)