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], Addr addr
)
101 : PciDev(name
, mmu
, cf
, cd
, bus
, dev
, func
), tsunami(t
),
102 addr(addr
), txPacketBufPtr(NULL
), rxPacketBufPtr(NULL
),
103 txXferLen(0), rxXferLen(0), txPktXmitted(0), txState(txIdle
), CTDD(false),
104 txFifoCnt(0), txFifoAvail(MAX_TX_FIFO_SIZE
), txHalt(false),
105 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle
), rxState(rxIdle
),
106 CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false),
107 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle
), extstsEnable(false),
108 rxDmaReadEvent(this), rxDmaWriteEvent(this),
109 txDmaReadEvent(this), txDmaWriteEvent(this),
110 dmaDescFree(dma_desc_free
), dmaDataFree(dma_data_free
),
111 txDelay(tx_delay
), rxDelay(rx_delay
), rxKickTick(0), txKickTick(0),
112 txEvent(this), rxFilterEnable(rx_filter
), acceptBroadcast(false),
113 acceptMulticast(false), acceptUnicast(false),
114 acceptPerfect(false), acceptArp(false),
115 physmem(pmem
), intctrl(i
), intrTick(0),
116 cpuPendingIntr(false), intrEvent(0), interface(0), pioLatency(pio_latency
)
118 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
119 tsunami
->ethernet
= this;
122 pioInterface
= newPioInterface(name
, hier
, header_bus
, this,
123 &NSGigE::cacheAccess
);
124 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
126 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
127 header_bus
, payload_bus
, 1);
129 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
130 header_bus
, header_bus
, 1);
131 } else if (payload_bus
) {
132 pioInterface
= newPioInterface(name
, hier
, payload_bus
, this,
133 &NSGigE::cacheAccess
);
134 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
135 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
136 payload_bus
, payload_bus
, 1);
141 intrDelay
= US2Ticks(intr_delay
);
142 dmaReadDelay
= dma_read_delay
;
143 dmaWriteDelay
= dma_write_delay
;
144 dmaReadFactor
= dma_read_factor
;
145 dmaWriteFactor
= dma_write_factor
;
147 memset(®s
, 0, sizeof(regs
));
149 rom
.perfectMatch
[0] = eaddr
[0];
150 rom
.perfectMatch
[1] = eaddr
[1];
151 rom
.perfectMatch
[2] = eaddr
[2];
152 rom
.perfectMatch
[3] = eaddr
[3];
153 rom
.perfectMatch
[4] = eaddr
[4];
154 rom
.perfectMatch
[5] = eaddr
[5];
164 .name(name() + ".txBytes")
165 .desc("Bytes Transmitted")
170 .name(name() + ".rxBytes")
171 .desc("Bytes Received")
176 .name(name() + ".txPackets")
177 .desc("Number of Packets Transmitted")
182 .name(name() + ".rxPackets")
183 .desc("Number of Packets Received")
188 .name(name() + ".txBandwidth")
189 .desc("Transmit Bandwidth (bits/s)")
195 .name(name() + ".rxBandwidth")
196 .desc("Receive Bandwidth (bits/s)")
202 .name(name() + ".txPPS")
203 .desc("Packet Tranmission Rate (packets/s)")
209 .name(name() + ".rxPPS")
210 .desc("Packet Reception Rate (packets/s)")
215 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
216 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
217 txPacketRate
= txPackets
/ simSeconds
;
218 rxPacketRate
= rxPackets
/ simSeconds
;
222 * This is to read the PCI general configuration registers
225 NSGigE::ReadConfig(int offset
, int size
, uint8_t *data
)
227 if (offset
< PCI_DEVICE_SPECIFIC
)
228 PciDev::ReadConfig(offset
, size
, data
);
230 panic("need to do this\n");
235 * This is to write to the PCI general configuration registers
238 NSGigE::WriteConfig(int offset
, int size
, uint32_t data
)
240 if (offset
< PCI_DEVICE_SPECIFIC
)
241 PciDev::WriteConfig(offset
, size
, data
);
243 panic("Need to do that\n");
247 * This reads the device registers, which are detailed in the NS83820
251 NSGigE::read(MemReqPtr
&req
, uint8_t *data
)
253 //The mask is to give you only the offset into the device register file
254 Addr daddr
= req
->paddr
& 0xfff;
255 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x va=%#x size=%d\n",
256 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
259 //there are some reserved registers, you can see ns_gige_reg.h and
260 //the spec sheet for details
261 if (daddr
> LAST
&& daddr
<= RESERVED
) {
262 panic("Accessing reserved register");
263 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
264 ReadConfig(daddr
& 0xff, req
->size
, data
);
266 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
267 // don't implement all the MIB's. hopefully the kernel
268 // doesn't actually DEPEND upon their values
269 // MIB are just hardware stats keepers
270 uint32_t ®
= *(uint32_t *) data
;
273 } else if (daddr
> 0x3FC)
274 panic("Something is messed up!\n");
277 case sizeof(uint32_t):
279 uint32_t ®
= *(uint32_t *)data
;
284 //these are supposed to be cleared on a read
285 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
302 devIntrClear(ISR_ALL
);
357 //see the spec sheet for how RFCR and RFDR work
358 //basically, you write to RFCR to tell the machine what you want to do next
359 //then you act upon RFDR, and the device will be prepared b/c
360 //of what you wrote to RFCR
366 switch (regs
.rfcr
& RFCR_RFADDR
) {
368 reg
= rom
.perfectMatch
[1];
370 reg
+= rom
.perfectMatch
[0];
373 reg
= rom
.perfectMatch
[3] << 8;
374 reg
+= rom
.perfectMatch
[2];
377 reg
= rom
.perfectMatch
[5] << 8;
378 reg
+= rom
.perfectMatch
[4];
381 panic("reading from RFDR for something for other than PMATCH!\n");
382 //didn't implement other RFDR functionality b/c driver didn't use
392 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
436 panic("reading unimplemented register: addr = %#x", daddr
);
439 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n",
445 panic("accessing register with invalid size: addr=%#x, size=%d",
453 NSGigE::write(MemReqPtr
&req
, const uint8_t *data
)
455 Addr daddr
= req
->paddr
& 0xfff;
456 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x va=%#x size=%d\n",
457 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
459 if (daddr
> LAST
&& daddr
<= RESERVED
) {
460 panic("Accessing reserved register");
461 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
462 WriteConfig(daddr
& 0xff, req
->size
, *(uint32_t *)data
);
464 } else if (daddr
> 0x3FC)
465 panic("Something is messed up!\n");
467 if (req
->size
== sizeof(uint32_t)) {
468 uint32_t reg
= *(uint32_t *)data
;
469 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
474 if ((reg
& (CR_TXE
| CR_TXD
)) == (CR_TXE
| CR_TXD
)) {
476 } else if (reg
& CR_TXE
) {
477 //the kernel is enabling the transmit machine
478 if (txState
== txIdle
)
480 } else if (reg
& CR_TXD
) {
484 if ((reg
& (CR_RXE
| CR_RXD
)) == (CR_RXE
| CR_RXD
)) {
486 } else if (reg
& CR_RXE
) {
487 if (rxState
== rxIdle
) {
490 } else if (reg
& CR_RXD
) {
501 devIntrPost(ISR_SWI
);
512 if (reg
& CFG_LNKSTS
|| reg
& CFG_SPDSTS
|| reg
& CFG_DUPSTS
513 || reg
& CFG_RESERVED
|| reg
& CFG_T64ADDR
514 || reg
& CFG_PCI64_DET
)
515 panic("writing to read-only or reserved CFG bits!\n");
517 regs
.config
|= reg
& ~(CFG_LNKSTS
| CFG_SPDSTS
| CFG_DUPSTS
| CFG_RESERVED
|
518 CFG_T64ADDR
| CFG_PCI64_DET
);
520 // all these #if 0's are because i don't THINK the kernel needs to have these implemented
521 // if there is a problem relating to one of these, you may need to add functionality in
523 if (reg
& CFG_TBI_EN
) ;
524 if (reg
& CFG_MODE_1000
) ;
527 if (reg
& CFG_AUTO_1000
)
528 panic("CFG_AUTO_1000 not implemented!\n");
531 if (reg
& CFG_PINT_DUPSTS
|| reg
& CFG_PINT_LNKSTS
|| reg
& CFG_PINT_SPDSTS
) ;
532 if (reg
& CFG_TMRTEST
) ;
533 if (reg
& CFG_MRM_DIS
) ;
534 if (reg
& CFG_MWI_DIS
) ;
536 if (reg
& CFG_T64ADDR
)
537 panic("CFG_T64ADDR is read only register!\n");
539 if (reg
& CFG_PCI64_DET
)
540 panic("CFG_PCI64_DET is read only register!\n");
542 if (reg
& CFG_DATA64_EN
) ;
543 if (reg
& CFG_M64ADDR
) ;
544 if (reg
& CFG_PHY_RST
) ;
545 if (reg
& CFG_PHY_DIS
) ;
548 if (reg
& CFG_EXTSTS_EN
)
551 extstsEnable
= false;
554 if (reg
& CFG_REQALG
) ;
558 if (reg
& CFG_PESEL
) ;
559 if (reg
& CFG_BROM_DIS
) ;
560 if (reg
& CFG_EXT_125
) ;
567 /* since phy is completely faked, MEAR_MD* don't matter
568 and since the driver never uses MEAR_EE*, they don't matter */
570 if (reg
& MEAR_EEDI
) ;
571 if (reg
& MEAR_EEDO
) ; //this one is read only
572 if (reg
& MEAR_EECLK
) ;
573 if (reg
& MEAR_EESEL
) ;
574 if (reg
& MEAR_MDIO
) ;
575 if (reg
& MEAR_MDDIR
) ;
576 if (reg
& MEAR_MDC
) ;
581 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
582 /* these control BISTs for various parts of chip - we don't care or do
583 just fake that the BIST is done */
584 if (reg
& PTSCR_RBIST_EN
)
585 regs
.ptscr
|= PTSCR_RBIST_DONE
;
586 if (reg
& PTSCR_EEBIST_EN
)
587 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
588 if (reg
& PTSCR_EELOAD_EN
)
589 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
592 case ISR
: /* writing to the ISR has no effect */
593 panic("ISR is a read only register!\n");
606 /* not going to implement real interrupt holdoff */
610 regs
.txdp
= (reg
& 0xFFFFFFFC);
611 assert(txState
== txIdle
);
622 if (reg
& TXCFG_CSI
) ;
623 if (reg
& TXCFG_HBI
) ;
624 if (reg
& TXCFG_MLB
) ;
625 if (reg
& TXCFG_ATP
) ;
626 if (reg
& TXCFG_ECRETRY
) ; /* this could easily be implemented, but
627 considering the network is just a fake
628 pipe, wouldn't make sense to do this */
630 if (reg
& TXCFG_BRST_DIS
) ;
634 /* we handle our own DMA, ignore the kernel's exhortations */
635 if (reg
& TXCFG_MXDMA
) ;
641 /* these just control general purpose i/o pins, don't matter */
655 if (reg
& RXCFG_AEP
) ;
656 if (reg
& RXCFG_ARP
) ;
657 if (reg
& RXCFG_STRIPCRC
) ;
658 if (reg
& RXCFG_RX_RD
) ;
659 if (reg
& RXCFG_ALP
) ;
660 if (reg
& RXCFG_AIRL
) ;
663 /* we handle our own DMA, ignore what kernel says about it */
664 if (reg
& RXCFG_MXDMA
) ;
667 if (reg
& (RXCFG_DRTH
| RXCFG_DRTH0
)) ;
672 /* there is no priority queueing used in the linux 2.6 driver */
677 /* not going to implement wake on LAN */
682 /* not going to implement pause control */
689 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
691 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
693 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
695 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
697 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
699 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
701 if (reg
& RFCR_APAT
) ;
702 // panic("RFCR_APAT not implemented!\n");
704 if (reg
& RFCR_MHEN
|| reg
& RFCR_UHEN
)
705 panic("hash filtering not implemented!\n");
708 panic("RFCR_ULM not implemented!\n");
713 panic("the driver never writes to RFDR, something is wrong!\n");
716 panic("the driver never uses BRAR, something is wrong!\n");
719 panic("the driver never uses BRDR, something is wrong!\n");
722 panic("SRR is read only register!\n");
725 panic("the driver never uses MIBC, something is wrong!\n");
736 panic("the driver never uses VDR, something is wrong!\n");
740 /* not going to implement clockrun stuff */
746 if (reg
& TBICR_MR_LOOPBACK
)
747 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
749 if (reg
& TBICR_MR_AN_ENABLE
) {
750 regs
.tanlpar
= regs
.tanar
;
751 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
755 if (reg
& TBICR_MR_RESTART_AN
) ;
761 panic("TBISR is read only register!\n");
766 panic("this isn't used in driver, something wrong!\n");
769 panic("this isn't used in driver, something wrong!\n");
773 panic("this should only be written to by the fake phy!\n");
776 panic("TANER is read only register!\n");
783 panic("thought i covered all the register, what is this? addr=%#x",
787 panic("Invalid Request Size");
793 NSGigE::devIntrPost(uint32_t interrupts
)
797 if (interrupts
& ISR_RESERVE
)
798 panic("Cannot set a reserved interrupt");
800 if (interrupts
& ISR_TXRCMP
)
801 regs
.isr
|= ISR_TXRCMP
;
803 if (interrupts
& ISR_RXRCMP
)
804 regs
.isr
|= ISR_RXRCMP
;
806 //ISR_DPERR not implemented
807 //ISR_SSERR not implemented
808 //ISR_RMABT not implemented
809 //ISR_RXSOVR not implemented
810 //ISR_HIBINT not implemented
811 //ISR_PHY not implemented
812 //ISR_PME not implemented
814 if (interrupts
& ISR_SWI
)
817 //ISR_MIB not implemented
818 //ISR_TXURN not implemented
820 if (interrupts
& ISR_TXIDLE
)
821 regs
.isr
|= ISR_TXIDLE
;
823 if (interrupts
& ISR_TXERR
)
824 regs
.isr
|= ISR_TXERR
;
826 if (interrupts
& ISR_TXDESC
)
827 regs
.isr
|= ISR_TXDESC
;
829 if (interrupts
& ISR_TXOK
) {
830 regs
.isr
|= ISR_TXOK
;
834 if (interrupts
& ISR_RXORN
)
835 regs
.isr
|= ISR_RXORN
;
837 if (interrupts
& ISR_RXIDLE
)
838 regs
.isr
|= ISR_RXIDLE
;
840 //ISR_RXEARLY not implemented
842 if (interrupts
& ISR_RXERR
)
843 regs
.isr
|= ISR_RXERR
;
845 if (interrupts
& ISR_RXDESC
)
846 regs
.isr
|= ISR_RXDESC
;
848 if (interrupts
& ISR_RXOK
) {
850 regs
.isr
|= ISR_RXOK
;
853 if ((regs
.isr
& regs
.imr
)) {
860 DPRINTF(Ethernet
, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
861 interrupts
, regs
.isr
, regs
.imr
);
865 NSGigE::devIntrClear(uint32_t interrupts
)
867 if (interrupts
& ISR_RESERVE
)
868 panic("Cannot clear a reserved interrupt");
870 if (interrupts
& ISR_TXRCMP
)
871 regs
.isr
&= ~ISR_TXRCMP
;
873 if (interrupts
& ISR_RXRCMP
)
874 regs
.isr
&= ~ISR_RXRCMP
;
876 //ISR_DPERR not implemented
877 //ISR_SSERR not implemented
878 //ISR_RMABT not implemented
879 //ISR_RXSOVR not implemented
880 //ISR_HIBINT not implemented
881 //ISR_PHY not implemented
882 //ISR_PME not implemented
884 if (interrupts
& ISR_SWI
)
885 regs
.isr
&= ~ISR_SWI
;
887 //ISR_MIB not implemented
888 //ISR_TXURN not implemented
890 if (interrupts
& ISR_TXIDLE
)
891 regs
.isr
&= ~ISR_TXIDLE
;
893 if (interrupts
& ISR_TXERR
)
894 regs
.isr
&= ~ISR_TXERR
;
896 if (interrupts
& ISR_TXDESC
)
897 regs
.isr
&= ~ISR_TXDESC
;
899 if (interrupts
& ISR_TXOK
)
900 regs
.isr
&= ~ISR_TXOK
;
902 if (interrupts
& ISR_RXORN
)
903 regs
.isr
&= ~ISR_RXORN
;
905 if (interrupts
& ISR_RXIDLE
)
906 regs
.isr
&= ~ISR_RXIDLE
;
908 //ISR_RXEARLY not implemented
910 if (interrupts
& ISR_RXERR
)
911 regs
.isr
&= ~ISR_RXERR
;
913 if (interrupts
& ISR_RXDESC
)
914 regs
.isr
&= ~ISR_RXDESC
;
916 if (interrupts
& ISR_RXOK
)
917 regs
.isr
&= ~ISR_RXOK
;
919 if (!(regs
.isr
& regs
.imr
))
922 DPRINTF(Ethernet
, "interrupt cleared intr=%x isr=%x imr=%x\n",
923 interrupts
, regs
.isr
, regs
.imr
);
927 NSGigE::devIntrChangeMask()
929 DPRINTF(Ethernet
, "interrupt mask changed\n");
931 if (regs
.isr
& regs
.imr
)
932 cpuIntrPost(curTick
);
938 NSGigE::cpuIntrPost(Tick when
)
940 if (when
> intrTick
&& intrTick
!= 0)
950 if (when
< curTick
) {
953 intrEvent
= new IntrEvent(this, true);
954 intrEvent
->schedule(intrTick
);
959 NSGigE::cpuInterrupt()
961 // Don't send an interrupt if there's already one
965 // Don't send an interrupt if it's supposed to be delayed
966 if (intrTick
> curTick
)
969 // Whether or not there's a pending interrupt, we don't care about
975 cpuPendingIntr
= true;
976 /** @todo rework the intctrl to be tsunami ok */
977 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
978 tsunami
->cchip
->postDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
982 NSGigE::cpuIntrClear()
984 if (cpuPendingIntr
) {
985 cpuPendingIntr
= false;
986 /** @todo rework the intctrl to be tsunami ok */
987 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
988 tsunami
->cchip
->clearDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
993 NSGigE::cpuIntrPending() const
994 { return cpuPendingIntr
; }
1000 DPRINTF(Ethernet
, "transmit reset\n");
1004 txFifoAvail
= MAX_TX_FIFO_SIZE
;
1007 assert(txDescCnt
== 0);
1009 regs
.command
&= ~CR_TXE
;
1011 assert(txDmaState
== dmaIdle
);
1017 DPRINTF(Ethernet
, "receive reset\n");
1020 assert(rxPktBytes
== 0);
1024 assert(rxDescCnt
== 0);
1025 assert(rxDmaState
== dmaIdle
);
1027 regs
.command
&= ~CR_RXE
;
1032 NSGigE::rxDmaReadCopy()
1034 assert(rxDmaState
== dmaReading
);
1036 memcpy(rxDmaData
, physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaLen
);
1037 rxDmaState
= dmaIdle
;
1039 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1040 rxDmaAddr
, rxDmaLen
);
1041 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1045 NSGigE::doRxDmaRead()
1047 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1048 rxDmaState
= dmaReading
;
1050 if (dmaInterface
&& !rxDmaFree
) {
1051 if (dmaInterface
->busy())
1052 rxDmaState
= dmaReadWaiting
;
1054 dmaInterface
->doDMA(Read
, rxDmaAddr
, rxDmaLen
, curTick
,
1059 if (dmaReadDelay
== 0 && dmaReadFactor
== 0) {
1064 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1065 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1066 rxDmaReadEvent
.schedule(start
);
1071 NSGigE::rxDmaReadDone()
1073 assert(rxDmaState
== dmaReading
);
1076 // If the transmit state machine has a pending DMA, let it go first
1077 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1084 NSGigE::rxDmaWriteCopy()
1086 assert(rxDmaState
== dmaWriting
);
1088 memcpy(physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaData
, rxDmaLen
);
1089 rxDmaState
= dmaIdle
;
1091 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1092 rxDmaAddr
, rxDmaLen
);
1093 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1097 NSGigE::doRxDmaWrite()
1099 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1100 rxDmaState
= dmaWriting
;
1102 if (dmaInterface
&& !rxDmaFree
) {
1103 if (dmaInterface
->busy())
1104 rxDmaState
= dmaWriteWaiting
;
1106 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
, curTick
,
1111 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0) {
1116 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1117 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1118 rxDmaWriteEvent
.schedule(start
);
1123 NSGigE::rxDmaWriteDone()
1125 assert(rxDmaState
== dmaWriting
);
1128 // If the transmit state machine has a pending DMA, let it go first
1129 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1138 DPRINTF(Ethernet
, "receive kick state=%s (rxBuf.size=%d)\n",
1139 NsRxStateStrings
[rxState
], rxFifo
.size());
1141 if (rxKickTick
> curTick
) {
1142 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1148 switch(rxDmaState
) {
1149 case dmaReadWaiting
:
1153 case dmaWriteWaiting
:
1161 // see state machine from spec for details
1162 // the way this works is, if you finish work on one state and can go directly to
1163 // another, you do that through jumping to the label "next". however, if you have
1164 // intermediate work, like DMA so that you can't go to the next state yet, you go to
1165 // exit and exit the loop. however, when the DMA is done it will trigger an
1166 // event and come back to this loop.
1169 if (!regs
.command
& CR_RXE
) {
1170 DPRINTF(Ethernet
, "Receive Disabled! Nothing to do.\n");
1175 rxState
= rxDescRefr
;
1177 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1178 rxDmaData
= &rxDescCache
+ offsetof(ns_desc
, link
);
1179 rxDmaLen
= sizeof(rxDescCache
.link
);
1180 rxDmaFree
= dmaDescFree
;
1185 rxState
= rxDescRead
;
1187 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1188 rxDmaData
= &rxDescCache
;
1189 rxDmaLen
= sizeof(ns_desc
);
1190 rxDmaFree
= dmaDescFree
;
1198 if (rxDmaState
!= dmaIdle
)
1201 rxState
= rxAdvance
;
1205 if (rxDmaState
!= dmaIdle
)
1209 "rxDescCache:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1210 ,rxDescCache
.link
, rxDescCache
.bufptr
, rxDescCache
.cmdsts
,
1211 rxDescCache
.extsts
);
1213 if (rxDescCache
.cmdsts
& CMDSTS_OWN
) {
1216 rxState
= rxFifoBlock
;
1217 rxFragPtr
= rxDescCache
.bufptr
;
1218 rxDescCnt
= rxDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1225 * @todo in reality, we should be able to start processing
1226 * the packet as it arrives, and not have to wait for the
1227 * full packet ot be in the receive fifo.
1232 // If we don't have a packet, grab a new one from the fifo.
1233 rxPacket
= rxFifo
.front();
1234 rxPktBytes
= rxPacket
->length
;
1235 rxPacketBufPtr
= rxPacket
->data
;
1237 // sanity check - i think the driver behaves like this
1238 assert(rxDescCnt
>= rxPktBytes
);
1240 // Must clear the value before popping to decrement the
1242 rxFifo
.front() = NULL
;
1247 // dont' need the && rxDescCnt > 0 if driver sanity check above holds
1248 if (rxPktBytes
> 0) {
1249 rxState
= rxFragWrite
;
1250 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds
1251 rxXferLen
= rxPktBytes
;
1253 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1254 rxDmaData
= rxPacketBufPtr
;
1255 rxDmaLen
= rxXferLen
;
1256 rxDmaFree
= dmaDataFree
;
1262 rxState
= rxDescWrite
;
1264 //if (rxPktBytes == 0) { /* packet is done */
1265 assert(rxPktBytes
== 0);
1267 rxDescCache
.cmdsts
|= CMDSTS_OWN
;
1268 rxDescCache
.cmdsts
&= ~CMDSTS_MORE
;
1269 rxDescCache
.cmdsts
|= CMDSTS_OK
;
1270 rxDescCache
.cmdsts
&= 0xffff0000;
1271 rxDescCache
.cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1274 /* all the driver uses these are for its own stats keeping
1275 which we don't care about, aren't necessary for functionality
1276 and doing this would just slow us down. if they end up using
1277 this in a later version for functional purposes, just undef
1279 if (rxFilterEnable
) {
1280 rxDescCache
.cmdsts
&= ~CMDSTS_DEST_MASK
;
1281 if (rxFifo
.front()->IsUnicast())
1282 rxDescCache
.cmdsts
|= CMDSTS_DEST_SELF
;
1283 if (rxFifo
.front()->IsMulticast())
1284 rxDescCache
.cmdsts
|= CMDSTS_DEST_MULTI
;
1285 if (rxFifo
.front()->IsBroadcast())
1286 rxDescCache
.cmdsts
|= CMDSTS_DEST_MASK
;
1290 eth_header
*eth
= (eth_header
*) rxPacket
->data
;
1291 // eth->type 0x800 indicated that it's an ip packet.
1292 if (eth
->type
== 0x800 && extstsEnable
) {
1293 rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1294 if (!ipChecksum(rxPacket
, false))
1295 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1296 ip_header
*ip
= rxFifo
.front()->getIpHdr();
1298 if (ip
->protocol
== 6) {
1299 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1300 if (!tcpChecksum(rxPacket
, false))
1301 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1302 } else if (ip
->protocol
== 17) {
1303 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1304 if (!udpChecksum(rxPacket
, false))
1305 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1309 rxFifoCnt
-= rxPacket
->length
;
1312 /* the driver seems to always receive into desc buffers
1313 of size 1514, so you never have a pkt that is split
1314 into multiple descriptors on the receive side, so
1315 i don't implement that case, hence the assert above.
1318 DPRINTF(Ethernet
, "rxDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1319 rxDescCache
.cmdsts
, rxDescCache
.extsts
);
1321 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1322 rxDmaData
= &(rxDescCache
.cmdsts
);
1323 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1324 rxDmaFree
= dmaDescFree
;
1332 if (rxDmaState
!= dmaIdle
)
1335 rxPacketBufPtr
+= rxXferLen
;
1336 rxFragPtr
+= rxXferLen
;
1337 rxPktBytes
-= rxXferLen
;
1339 rxState
= rxFifoBlock
;
1343 if (rxDmaState
!= dmaIdle
)
1346 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1348 assert(rxPacket
== 0);
1349 devIntrPost(ISR_RXOK
);
1351 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1352 devIntrPost(ISR_RXDESC
);
1358 rxState
= rxAdvance
;
1362 if (rxDescCache
.link
== 0) {
1366 rxState
= rxDescRead
;
1367 regs
.rxdp
= rxDescCache
.link
;
1370 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1371 rxDmaData
= &rxDescCache
;
1372 rxDmaLen
= sizeof(ns_desc
);
1373 rxDmaFree
= dmaDescFree
;
1381 panic("Invalid rxState!");
1385 DPRINTF(Ethernet
, "entering next rx state = %s\n",
1386 NsRxStateStrings
[rxState
]);
1388 if (rxState
== rxIdle
) {
1389 regs
.command
&= ~CR_RXE
;
1390 devIntrPost(ISR_RXIDLE
);
1398 * @todo do we want to schedule a future kick?
1400 DPRINTF(Ethernet
, "rx state machine exited state=%s\n",
1401 NsRxStateStrings
[rxState
]);
1407 if (txFifo
.empty()) {
1408 DPRINTF(Ethernet
, "nothing to transmit\n");
1412 if (interface
->sendPacket(txFifo
.front())) {
1413 DPRINTF(Ethernet
, "transmit packet\n");
1414 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1415 txBytes
+= txFifo
.front()->length
;
1418 txFifoCnt
-= (txFifo
.front()->length
- txPktXmitted
);
1420 txFifo
.front() = NULL
;
1423 /* normally do a writeback of the descriptor here, and ONLY after that is
1424 done, send this interrupt. but since our stuff never actually fails,
1425 just do this interrupt here, otherwise the code has to stray from this
1426 nice format. besides, it's functionally the same.
1428 devIntrPost(ISR_TXOK
);
1431 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1432 DPRINTF(Ethernet
, "reschedule transmit\n");
1433 txEvent
.schedule(curTick
+ 1000);
1438 NSGigE::txDmaReadCopy()
1440 assert(txDmaState
== dmaReading
);
1442 memcpy(txDmaData
, physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaLen
);
1443 txDmaState
= dmaIdle
;
1445 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1446 txDmaAddr
, txDmaLen
);
1447 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1451 NSGigE::doTxDmaRead()
1453 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1454 txDmaState
= dmaReading
;
1456 if (dmaInterface
&& !txDmaFree
) {
1457 if (dmaInterface
->busy())
1458 txDmaState
= dmaReadWaiting
;
1460 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1465 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1470 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1471 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1472 txDmaReadEvent
.schedule(start
);
1477 NSGigE::txDmaReadDone()
1479 assert(txDmaState
== dmaReading
);
1482 // If the receive state machine has a pending DMA, let it go first
1483 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1490 NSGigE::txDmaWriteCopy()
1492 assert(txDmaState
== dmaWriting
);
1494 memcpy(physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaData
, txDmaLen
);
1495 txDmaState
= dmaIdle
;
1497 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1498 txDmaAddr
, txDmaLen
);
1499 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1503 NSGigE::doTxDmaWrite()
1505 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1506 txDmaState
= dmaWriting
;
1508 if (dmaInterface
&& !txDmaFree
) {
1509 if (dmaInterface
->busy())
1510 txDmaState
= dmaWriteWaiting
;
1512 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1517 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1522 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1523 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1524 txDmaWriteEvent
.schedule(start
);
1529 NSGigE::txDmaWriteDone()
1531 assert(txDmaState
== dmaWriting
);
1534 // If the receive state machine has a pending DMA, let it go first
1535 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1544 DPRINTF(Ethernet
, "transmit kick state=%s\n", NsTxStateStrings
[txState
]);
1546 if (rxKickTick
> curTick
) {
1547 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1554 switch(txDmaState
) {
1555 case dmaReadWaiting
:
1559 case dmaWriteWaiting
:
1569 if (!regs
.command
& CR_TXE
) {
1570 DPRINTF(Ethernet
, "Transmit disabled. Nothing to do.\n");
1575 txState
= txDescRefr
;
1577 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1578 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1579 txDmaLen
= sizeof(txDescCache
.link
);
1580 txDmaFree
= dmaDescFree
;
1586 txState
= txDescRead
;
1588 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1589 txDmaData
= &txDescCache
;
1590 txDmaLen
= sizeof(ns_desc
);
1591 txDmaFree
= dmaDescFree
;
1599 if (txDmaState
!= dmaIdle
)
1602 txState
= txAdvance
;
1606 if (txDmaState
!= dmaIdle
)
1610 "txDescCache data:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1611 ,txDescCache
.link
, txDescCache
.bufptr
, txDescCache
.cmdsts
,
1612 txDescCache
.extsts
);
1614 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1615 txState
= txFifoBlock
;
1616 txFragPtr
= txDescCache
.bufptr
;
1617 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1625 DPRINTF(Ethernet
, "starting the tx of a new packet\n");
1626 txPacket
= new EtherPacket
;
1627 txPacket
->data
= new uint8_t[16384];
1628 txPacketBufPtr
= txPacket
->data
;
1631 if (txDescCnt
== 0) {
1632 DPRINTF(Ethernet
, "the txDescCnt == 0, done with descriptor\n");
1633 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1634 DPRINTF(Ethernet
, "there are more descriptors to come\n");
1635 txState
= txDescWrite
;
1637 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1639 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1640 txDmaData
= &(txDescCache
.cmdsts
);
1641 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1642 txDmaFree
= dmaDescFree
;
1647 } else { /* this packet is totally done */
1648 DPRINTF(Ethernet
, "This packet is done, let's wrap it up\n");
1649 /* deal with the the packet that just finished */
1650 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1651 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1652 udpChecksum(txPacket
, true);
1653 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1654 tcpChecksum(txPacket
, true);
1655 } else if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1656 ipChecksum(txPacket
, true);
1660 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1661 /* this is just because the receive can't handle a packet bigger
1662 want to make sure */
1663 assert(txPacket
->length
<= 1514);
1664 txFifo
.push_back(txPacket
);
1667 /* this following section is not to spec, but functionally shouldn't
1668 be any different. normally, the chip will wait til the transmit has
1669 occurred before writing back the descriptor because it has to wait
1670 to see that it was successfully transmitted to decide whether to set
1671 CMDSTS_OK or not. however, in the simulator since it is always
1672 successfully transmitted, and writing it exactly to spec would
1673 complicate the code, we just do it here
1675 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1676 txDescCache
.cmdsts
|= CMDSTS_OK
;
1679 "txDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1680 txDescCache
.cmdsts
, txDescCache
.extsts
);
1682 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1683 txDmaData
= &(txDescCache
.cmdsts
);
1684 txDmaLen
= sizeof(txDescCache
.cmdsts
) + sizeof(txDescCache
.extsts
);
1685 txDmaFree
= dmaDescFree
;
1697 txState
= txAdvance
;
1700 DPRINTF(Ethernet
, "this descriptor isn't done yet\n");
1701 /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
1702 value, shift left by 5 to get the real number of bytes */
1703 if (txFifoAvail
< ((regs
.txcfg
& TXCFG_FLTH_MASK
) >> 3)) {
1704 DPRINTF(Ethernet
, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
1705 txFifoAvail
, regs
.txcfg
& TXCFG_FLTH_MASK
);
1709 txState
= txFragRead
;
1711 /* The number of bytes transferred is either whatever is left
1712 in the descriptor (txDescCnt), or if there is not enough
1713 room in the fifo, just whatever room is left in the fifo
1715 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1717 txDmaAddr
= txFragPtr
& 0x3fffffff;
1718 txDmaData
= txPacketBufPtr
;
1719 txDmaLen
= txXferLen
;
1720 txDmaFree
= dmaDataFree
;
1728 if (txDmaState
!= dmaIdle
)
1731 txPacketBufPtr
+= txXferLen
;
1732 txFragPtr
+= txXferLen
;
1733 txFifoCnt
+= txXferLen
;
1734 txDescCnt
-= txXferLen
;
1736 txState
= txFifoBlock
;
1740 if (txDmaState
!= dmaIdle
)
1743 if (txFifoCnt
>= ((regs
.txcfg
& TXCFG_DRTH_MASK
) << 5)) {
1744 if (txFifo
.empty()) {
1745 uint32_t xmitted
= (uint32_t) (txPacketBufPtr
- txPacket
->data
- txPktXmitted
);
1746 txFifoCnt
-= xmitted
;
1747 txPktXmitted
+= xmitted
;
1753 if (txDescCache
.cmdsts
& CMDSTS_INTR
) {
1754 devIntrPost(ISR_TXDESC
);
1757 txState
= txAdvance
;
1761 if (txDescCache
.link
== 0) {
1764 txState
= txDescRead
;
1765 regs
.txdp
= txDescCache
.link
;
1768 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1769 txDmaData
= &txDescCache
;
1770 txDmaLen
= sizeof(ns_desc
);
1771 txDmaFree
= dmaDescFree
;
1779 panic("invalid state");
1782 DPRINTF(Ethernet
, "entering next tx state=%s\n",
1783 NsTxStateStrings
[txState
]);
1785 if (txState
== txIdle
) {
1786 regs
.command
&= ~CR_TXE
;
1787 devIntrPost(ISR_TXIDLE
);
1795 * @todo do we want to schedule a future kick?
1797 DPRINTF(Ethernet
, "tx state machine exited state=%s\n",
1798 NsTxStateStrings
[txState
]);
1802 NSGigE::transferDone()
1807 DPRINTF(Ethernet
, "schedule transmit\n");
1809 if (txEvent
.scheduled())
1810 txEvent
.reschedule(curTick
+ 1);
1812 txEvent
.schedule(curTick
+ 1);
1816 NSGigE::rxFilter(PacketPtr packet
)
1821 if (packet
->IsUnicast()) {
1824 // If we're accepting all unicast addresses
1828 // If we make a perfect match
1830 && (memcmp(rom
.perfectMatch
, packet
->data
, sizeof(rom
.perfectMatch
)) == 0))
1833 eth_header
*eth
= (eth_header
*) packet
->data
;
1834 if ((acceptArp
) && (eth
->type
== 0x806))
1837 } else if (packet
->IsBroadcast()) {
1840 // if we're accepting broadcasts
1841 if (acceptBroadcast
)
1844 } else if (packet
->IsMulticast()) {
1847 // if we're accepting all multicasts
1848 if (acceptMulticast
)
1854 // oh well, punt on this one
1858 DPRINTF(Ethernet
, "rxFilter drop\n");
1859 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1866 NSGigE::recvPacket(PacketPtr packet
)
1868 rxBytes
+= packet
->length
;
1871 if (rxState
== rxIdle
) {
1872 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1873 interface
->recvDone();
1877 if (rxFilterEnable
&& rxFilter(packet
)) {
1878 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1879 interface
->recvDone();
1883 if (rxFifoCnt
+ packet
->length
>= MAX_RX_FIFO_SIZE
) {
1885 "packet will not fit in receive buffer...packet dropped\n");
1886 devIntrPost(ISR_RXORN
);
1890 rxFifo
.push_back(packet
);
1891 rxFifoCnt
+= packet
->length
;
1892 interface
->recvDone();
1899 * does a udp checksum. if gen is true, then it generates it and puts it in the right place
1900 * else, it just checks what it calculates against the value in the header in packet
1903 NSGigE::udpChecksum(PacketPtr packet
, bool gen
)
1905 udp_header
*hdr
= (udp_header
*) packet
->getTransportHdr();
1907 ip_header
*ip
= packet
->getIpHdr();
1909 pseudo_header
*pseudo
= new pseudo_header
;
1911 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1912 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1913 pseudo
->protocol
= ip
->protocol
;
1914 pseudo
->len
= hdr
->len
;
1916 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1917 (uint32_t) hdr
->len
);
1921 hdr
->chksum
= cksum
;
1930 NSGigE::tcpChecksum(PacketPtr packet
, bool gen
)
1932 tcp_header
*hdr
= (tcp_header
*) packet
->getTransportHdr();
1934 ip_header
*ip
= packet
->getIpHdr();
1936 pseudo_header
*pseudo
= new pseudo_header
;
1938 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1939 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1940 pseudo
->protocol
= ip
->protocol
;
1941 pseudo
->len
= ip
->dgram_len
- (ip
->vers_len
& 0xf);
1943 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1944 (uint32_t) pseudo
->len
);
1948 hdr
->chksum
= cksum
;
1957 NSGigE::ipChecksum(PacketPtr packet
, bool gen
)
1959 ip_header
*hdr
= packet
->getIpHdr();
1961 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
, (hdr
->vers_len
& 0xf));
1964 hdr
->hdr_chksum
= cksum
;
1973 NSGigE::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
1977 uint16_t last_pad
= 0;
1979 last_pad
= buf
[len
/2] & 0xff;
1985 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
1986 pseudo
[3] + pseudo
[4] + pseudo
[5];
1989 for (int i
=0; i
< (len
/2); ++i
) {
1994 sum
= (sum
>> 16) + (sum
& 0xffff);
1999 //=====================================================================
2003 NSGigE::serialize(ostream
&os
)
2006 * Finalize any DMA events now.
2008 if (rxDmaReadEvent
.scheduled())
2010 if (rxDmaWriteEvent
.scheduled())
2012 if (txDmaReadEvent
.scheduled())
2014 if (txDmaWriteEvent
.scheduled())
2018 * Serialize the device registers
2020 SERIALIZE_SCALAR(regs
.command
);
2021 SERIALIZE_SCALAR(regs
.config
);
2022 SERIALIZE_SCALAR(regs
.mear
);
2023 SERIALIZE_SCALAR(regs
.ptscr
);
2024 SERIALIZE_SCALAR(regs
.isr
);
2025 SERIALIZE_SCALAR(regs
.imr
);
2026 SERIALIZE_SCALAR(regs
.ier
);
2027 SERIALIZE_SCALAR(regs
.ihr
);
2028 SERIALIZE_SCALAR(regs
.txdp
);
2029 SERIALIZE_SCALAR(regs
.txdp_hi
);
2030 SERIALIZE_SCALAR(regs
.txcfg
);
2031 SERIALIZE_SCALAR(regs
.gpior
);
2032 SERIALIZE_SCALAR(regs
.rxdp
);
2033 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2034 SERIALIZE_SCALAR(regs
.rxcfg
);
2035 SERIALIZE_SCALAR(regs
.pqcr
);
2036 SERIALIZE_SCALAR(regs
.wcsr
);
2037 SERIALIZE_SCALAR(regs
.pcr
);
2038 SERIALIZE_SCALAR(regs
.rfcr
);
2039 SERIALIZE_SCALAR(regs
.rfdr
);
2040 SERIALIZE_SCALAR(regs
.srr
);
2041 SERIALIZE_SCALAR(regs
.mibc
);
2042 SERIALIZE_SCALAR(regs
.vrcr
);
2043 SERIALIZE_SCALAR(regs
.vtcr
);
2044 SERIALIZE_SCALAR(regs
.vdr
);
2045 SERIALIZE_SCALAR(regs
.ccsr
);
2046 SERIALIZE_SCALAR(regs
.tbicr
);
2047 SERIALIZE_SCALAR(regs
.tbisr
);
2048 SERIALIZE_SCALAR(regs
.tanar
);
2049 SERIALIZE_SCALAR(regs
.tanlpar
);
2050 SERIALIZE_SCALAR(regs
.taner
);
2051 SERIALIZE_SCALAR(regs
.tesr
);
2053 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2056 * Serialize the various helper variables
2058 uint32_t txPktBufPtr
= (uint32_t) txPacketBufPtr
;
2059 SERIALIZE_SCALAR(txPktBufPtr
);
2060 uint32_t rxPktBufPtr
= (uint32_t) rxPktBufPtr
;
2061 SERIALIZE_SCALAR(rxPktBufPtr
);
2062 SERIALIZE_SCALAR(txXferLen
);
2063 SERIALIZE_SCALAR(rxXferLen
);
2064 SERIALIZE_SCALAR(txPktXmitted
);
2066 bool txPacketExists
= txPacket
;
2067 SERIALIZE_SCALAR(txPacketExists
);
2068 bool rxPacketExists
= rxPacket
;
2069 SERIALIZE_SCALAR(rxPacketExists
);
2072 * Serialize DescCaches
2074 SERIALIZE_SCALAR(txDescCache
.link
);
2075 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2076 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2077 SERIALIZE_SCALAR(txDescCache
.extsts
);
2078 SERIALIZE_SCALAR(rxDescCache
.link
);
2079 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2080 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2081 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2084 * Serialize tx state machine
2086 int txNumPkts
= txFifo
.size();
2087 SERIALIZE_SCALAR(txNumPkts
);
2088 int txState
= this->txState
;
2089 SERIALIZE_SCALAR(txState
);
2090 SERIALIZE_SCALAR(CTDD
);
2091 SERIALIZE_SCALAR(txFifoCnt
);
2092 SERIALIZE_SCALAR(txFifoAvail
);
2093 SERIALIZE_SCALAR(txHalt
);
2094 SERIALIZE_SCALAR(txFragPtr
);
2095 SERIALIZE_SCALAR(txDescCnt
);
2096 int txDmaState
= this->txDmaState
;
2097 SERIALIZE_SCALAR(txDmaState
);
2100 * Serialize rx state machine
2102 int rxNumPkts
= rxFifo
.size();
2103 SERIALIZE_SCALAR(rxNumPkts
);
2104 int rxState
= this->rxState
;
2105 SERIALIZE_SCALAR(rxState
);
2106 SERIALIZE_SCALAR(CRDD
);
2107 SERIALIZE_SCALAR(rxPktBytes
);
2108 SERIALIZE_SCALAR(rxFifoCnt
);
2109 SERIALIZE_SCALAR(rxHalt
);
2110 SERIALIZE_SCALAR(rxDescCnt
);
2111 int rxDmaState
= this->rxDmaState
;
2112 SERIALIZE_SCALAR(rxDmaState
);
2114 SERIALIZE_SCALAR(extstsEnable
);
2117 * If there's a pending transmit, store the time so we can
2118 * reschedule it later
2120 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2121 SERIALIZE_SCALAR(transmitTick
);
2124 * Keep track of pending interrupt status.
2126 SERIALIZE_SCALAR(intrTick
);
2127 SERIALIZE_SCALAR(cpuPendingIntr
);
2128 Tick intrEventTick
= 0;
2130 intrEventTick
= intrEvent
->when();
2131 SERIALIZE_SCALAR(intrEventTick
);
2134 for (pktiter_t p
= rxFifo
.begin(); p
!= rxFifo
.end(); ++p
) {
2135 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2136 (*p
)->serialize(os
);
2138 if (rxPacketExists
) {
2139 nameOut(os
, csprintf("%s.rxPacket", name()));
2140 rxPacket
->serialize(os
);
2143 for (pktiter_t p
= txFifo
.begin(); p
!= txFifo
.end(); ++p
) {
2144 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2145 (*p
)->serialize(os
);
2147 if (txPacketExists
) {
2148 nameOut(os
, csprintf("%s.txPacket", name()));
2149 txPacket
->serialize(os
);
2154 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2156 UNSERIALIZE_SCALAR(regs
.command
);
2157 UNSERIALIZE_SCALAR(regs
.config
);
2158 UNSERIALIZE_SCALAR(regs
.mear
);
2159 UNSERIALIZE_SCALAR(regs
.ptscr
);
2160 UNSERIALIZE_SCALAR(regs
.isr
);
2161 UNSERIALIZE_SCALAR(regs
.imr
);
2162 UNSERIALIZE_SCALAR(regs
.ier
);
2163 UNSERIALIZE_SCALAR(regs
.ihr
);
2164 UNSERIALIZE_SCALAR(regs
.txdp
);
2165 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2166 UNSERIALIZE_SCALAR(regs
.txcfg
);
2167 UNSERIALIZE_SCALAR(regs
.gpior
);
2168 UNSERIALIZE_SCALAR(regs
.rxdp
);
2169 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2170 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2171 UNSERIALIZE_SCALAR(regs
.pqcr
);
2172 UNSERIALIZE_SCALAR(regs
.wcsr
);
2173 UNSERIALIZE_SCALAR(regs
.pcr
);
2174 UNSERIALIZE_SCALAR(regs
.rfcr
);
2175 UNSERIALIZE_SCALAR(regs
.rfdr
);
2176 UNSERIALIZE_SCALAR(regs
.srr
);
2177 UNSERIALIZE_SCALAR(regs
.mibc
);
2178 UNSERIALIZE_SCALAR(regs
.vrcr
);
2179 UNSERIALIZE_SCALAR(regs
.vtcr
);
2180 UNSERIALIZE_SCALAR(regs
.vdr
);
2181 UNSERIALIZE_SCALAR(regs
.ccsr
);
2182 UNSERIALIZE_SCALAR(regs
.tbicr
);
2183 UNSERIALIZE_SCALAR(regs
.tbisr
);
2184 UNSERIALIZE_SCALAR(regs
.tanar
);
2185 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2186 UNSERIALIZE_SCALAR(regs
.taner
);
2187 UNSERIALIZE_SCALAR(regs
.tesr
);
2189 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2192 * unserialize the various helper variables
2194 uint32_t txPktBufPtr
;
2195 UNSERIALIZE_SCALAR(txPktBufPtr
);
2196 txPacketBufPtr
= (uint8_t *) txPktBufPtr
;
2197 uint32_t rxPktBufPtr
;
2198 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2199 rxPacketBufPtr
= (uint8_t *) rxPktBufPtr
;
2200 UNSERIALIZE_SCALAR(txXferLen
);
2201 UNSERIALIZE_SCALAR(rxXferLen
);
2202 UNSERIALIZE_SCALAR(txPktXmitted
);
2204 bool txPacketExists
;
2205 UNSERIALIZE_SCALAR(txPacketExists
);
2206 bool rxPacketExists
;
2207 UNSERIALIZE_SCALAR(rxPacketExists
);
2210 * Unserialize DescCaches
2212 UNSERIALIZE_SCALAR(txDescCache
.link
);
2213 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2214 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2215 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2216 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2217 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2218 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2219 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2222 * unserialize tx state machine
2225 UNSERIALIZE_SCALAR(txNumPkts
);
2227 UNSERIALIZE_SCALAR(txState
);
2228 this->txState
= (TxState
) txState
;
2229 UNSERIALIZE_SCALAR(CTDD
);
2230 UNSERIALIZE_SCALAR(txFifoCnt
);
2231 UNSERIALIZE_SCALAR(txFifoAvail
);
2232 UNSERIALIZE_SCALAR(txHalt
);
2233 UNSERIALIZE_SCALAR(txFragPtr
);
2234 UNSERIALIZE_SCALAR(txDescCnt
);
2236 UNSERIALIZE_SCALAR(txDmaState
);
2237 this->txDmaState
= (DmaState
) txDmaState
;
2240 * unserialize rx state machine
2243 UNSERIALIZE_SCALAR(rxNumPkts
);
2245 UNSERIALIZE_SCALAR(rxState
);
2246 this->rxState
= (RxState
) rxState
;
2247 UNSERIALIZE_SCALAR(CRDD
);
2248 UNSERIALIZE_SCALAR(rxPktBytes
);
2249 UNSERIALIZE_SCALAR(rxFifoCnt
);
2250 UNSERIALIZE_SCALAR(rxHalt
);
2251 UNSERIALIZE_SCALAR(rxDescCnt
);
2253 UNSERIALIZE_SCALAR(rxDmaState
);
2254 this->rxDmaState
= (DmaState
) rxDmaState
;
2256 UNSERIALIZE_SCALAR(extstsEnable
);
2259 * If there's a pending transmit, store the time so we can
2260 * reschedule it later
2263 UNSERIALIZE_SCALAR(transmitTick
);
2265 txEvent
.schedule(curTick
+ transmitTick
);
2268 * Keep track of pending interrupt status.
2270 UNSERIALIZE_SCALAR(intrTick
);
2271 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2273 UNSERIALIZE_SCALAR(intrEventTick
);
2274 if (intrEventTick
) {
2275 intrEvent
= new IntrEvent(this, true);
2276 intrEvent
->schedule(intrEventTick
);
2279 for (int i
= 0; i
< rxNumPkts
; ++i
) {
2280 PacketPtr p
= new EtherPacket
;
2281 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2282 rxFifo
.push_back(p
);
2285 if (rxPacketExists
) {
2286 rxPacket
= new EtherPacket
;
2287 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2289 for (int i
= 0; i
< txNumPkts
; ++i
) {
2290 PacketPtr p
= new EtherPacket
;
2291 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2292 txFifo
.push_back(p
);
2294 if (txPacketExists
) {
2295 txPacket
= new EtherPacket
;
2296 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2302 NSGigE::cacheAccess(MemReqPtr
&req
)
2304 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2305 req
->paddr
, req
->paddr
- addr
);
2306 return curTick
+ pioLatency
;
2308 //=====================================================================
2311 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2313 SimObjectParam
<EtherInt
*> peer
;
2314 SimObjectParam
<NSGigE
*> device
;
2316 END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2318 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2320 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2321 INIT_PARAM(device
, "Ethernet device of this interface")
2323 END_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2325 CREATE_SIM_OBJECT(NSGigEInt
)
2327 NSGigEInt
*dev_int
= new NSGigEInt(getInstanceName(), device
);
2329 EtherInt
*p
= (EtherInt
*)peer
;
2331 dev_int
->setPeer(p
);
2332 p
->setPeer(dev_int
);
2338 REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt
)
2341 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2343 Param
<Tick
> tx_delay
;
2344 Param
<Tick
> rx_delay
;
2345 SimObjectParam
<IntrControl
*> intr_ctrl
;
2346 Param
<Tick
> intr_delay
;
2347 SimObjectParam
<MemoryController
*> mmu
;
2348 SimObjectParam
<PhysicalMemory
*> physmem
;
2350 Param
<bool> rx_filter
;
2351 Param
<string
> hardware_address
;
2352 SimObjectParam
<Bus
*> header_bus
;
2353 SimObjectParam
<Bus
*> payload_bus
;
2354 SimObjectParam
<HierParams
*> hier
;
2355 Param
<Tick
> pio_latency
;
2356 Param
<bool> dma_desc_free
;
2357 Param
<bool> dma_data_free
;
2358 Param
<Tick
> dma_read_delay
;
2359 Param
<Tick
> dma_write_delay
;
2360 Param
<Tick
> dma_read_factor
;
2361 Param
<Tick
> dma_write_factor
;
2362 SimObjectParam
<PciConfigAll
*> configspace
;
2363 SimObjectParam
<PciConfigData
*> configdata
;
2364 SimObjectParam
<Tsunami
*> tsunami
;
2365 Param
<uint32_t> pci_bus
;
2366 Param
<uint32_t> pci_dev
;
2367 Param
<uint32_t> pci_func
;
2369 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2371 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2373 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2374 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2375 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2376 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2377 INIT_PARAM(mmu
, "Memory Controller"),
2378 INIT_PARAM(physmem
, "Physical Memory"),
2379 INIT_PARAM(addr
, "Device Address"),
2380 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2381 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2382 "00:99:00:00:00:01"),
2383 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2384 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2385 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2386 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000),
2387 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2388 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2389 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2390 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2391 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2392 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2393 INIT_PARAM(configspace
, "PCI Configspace"),
2394 INIT_PARAM(configdata
, "PCI Config data"),
2395 INIT_PARAM(tsunami
, "Tsunami"),
2396 INIT_PARAM(pci_bus
, "PCI bus"),
2397 INIT_PARAM(pci_dev
, "PCI device number"),
2398 INIT_PARAM(pci_func
, "PCI function code")
2400 END_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2403 CREATE_SIM_OBJECT(NSGigE
)
2406 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2407 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2409 return new NSGigE(getInstanceName(), intr_ctrl
, intr_delay
,
2410 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2411 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2412 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2413 dma_write_factor
, configspace
, configdata
,
2414 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
,
2418 REGISTER_SIM_OBJECT("NSGigE", NSGigE
)