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/etherlink.hh"
42 #include "dev/ns_gige.hh"
43 #include "dev/pciconfigall.hh"
44 #include "dev/tsunami_cchip.hh"
45 #include "mem/bus/bus.hh"
46 #include "mem/bus/dma_interface.hh"
47 #include "mem/bus/pio_interface.hh"
48 #include "mem/bus/pio_interface_impl.hh"
49 #include "mem/functional_mem/memory_control.hh"
50 #include "mem/functional_mem/physical_memory.hh"
51 #include "sim/builder.hh"
52 #include "sim/debug.hh"
53 #include "sim/host.hh"
54 #include "sim/sim_stats.hh"
55 #include "targetarch/vtophys.hh"
57 const char *NsRxStateStrings
[] =
68 const char *NsTxStateStrings
[] =
79 const char *NsDmaState
[] =
90 // helper function declarations
91 // These functions reverse Endianness so we can evaluate network data
93 uint16_t reverseEnd16(uint16_t);
94 uint32_t reverseEnd32(uint32_t);
96 ///////////////////////////////////////////////////////////////////////
100 NSGigE::NSGigE(const std::string
&name
, IntrControl
*i
, Tick intr_delay
,
101 PhysicalMemory
*pmem
, Tick tx_delay
, Tick rx_delay
,
102 MemoryController
*mmu
, HierParams
*hier
, Bus
*header_bus
,
103 Bus
*payload_bus
, Tick pio_latency
, bool dma_desc_free
,
104 bool dma_data_free
, Tick dma_read_delay
, Tick dma_write_delay
,
105 Tick dma_read_factor
, Tick dma_write_factor
, PciConfigAll
*cf
,
106 PciConfigData
*cd
, Tsunami
*t
, uint32_t bus
, uint32_t dev
,
107 uint32_t func
, bool rx_filter
, const int eaddr
[6],
108 uint32_t tx_fifo_size
, uint32_t rx_fifo_size
)
109 : PciDev(name
, mmu
, cf
, cd
, bus
, dev
, func
), tsunami(t
), ioEnable(false),
110 maxTxFifoSize(tx_fifo_size
), maxRxFifoSize(rx_fifo_size
),
111 txPacket(0), rxPacket(0), txPacketBufPtr(NULL
), rxPacketBufPtr(NULL
),
112 txXferLen(0), rxXferLen(0), txState(txIdle
), txEnable(false),
113 CTDD(false), txFifoAvail(tx_fifo_size
),
114 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle
), rxState(rxIdle
),
115 rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0),
116 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle
), extstsEnable(false),
117 rxDmaReadEvent(this), rxDmaWriteEvent(this),
118 txDmaReadEvent(this), txDmaWriteEvent(this),
119 dmaDescFree(dma_desc_free
), dmaDataFree(dma_data_free
),
120 txDelay(tx_delay
), rxDelay(rx_delay
), rxKickTick(0), txKickTick(0),
121 txEvent(this), rxFilterEnable(rx_filter
), acceptBroadcast(false),
122 acceptMulticast(false), acceptUnicast(false),
123 acceptPerfect(false), acceptArp(false),
124 physmem(pmem
), intctrl(i
), intrTick(0), cpuPendingIntr(false),
125 intrEvent(0), interface(0)
127 tsunami
->ethernet
= this;
130 pioInterface
= newPioInterface(name
, hier
, header_bus
, this,
131 &NSGigE::cacheAccess
);
133 pioLatency
= pio_latency
* header_bus
->clockRatio
;
136 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
137 header_bus
, payload_bus
, 1);
139 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
140 header_bus
, header_bus
, 1);
141 } else if (payload_bus
) {
142 pioInterface
= newPioInterface(name
, hier
, payload_bus
, this,
143 &NSGigE::cacheAccess
);
145 pioLatency
= pio_latency
* payload_bus
->clockRatio
;
147 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma", payload_bus
,
152 intrDelay
= US2Ticks(intr_delay
);
153 dmaReadDelay
= dma_read_delay
;
154 dmaWriteDelay
= dma_write_delay
;
155 dmaReadFactor
= dma_read_factor
;
156 dmaWriteFactor
= dma_write_factor
;
159 rom
.perfectMatch
[0] = eaddr
[0];
160 rom
.perfectMatch
[1] = eaddr
[1];
161 rom
.perfectMatch
[2] = eaddr
[2];
162 rom
.perfectMatch
[3] = eaddr
[3];
163 rom
.perfectMatch
[4] = eaddr
[4];
164 rom
.perfectMatch
[5] = eaddr
[5];
174 .name(name() + ".txBytes")
175 .desc("Bytes Transmitted")
180 .name(name() + ".rxBytes")
181 .desc("Bytes Received")
186 .name(name() + ".txPackets")
187 .desc("Number of Packets Transmitted")
192 .name(name() + ".rxPackets")
193 .desc("Number of Packets Received")
198 .name(name() + ".txIPChecksums")
199 .desc("Number of tx IP Checksums done by device")
205 .name(name() + ".rxIPChecksums")
206 .desc("Number of rx IP Checksums done by device")
212 .name(name() + ".txTCPChecksums")
213 .desc("Number of tx TCP Checksums done by device")
219 .name(name() + ".rxTCPChecksums")
220 .desc("Number of rx TCP Checksums done by device")
226 .name(name() + ".descDMAReads")
227 .desc("Number of descriptors the device read w/ DMA")
232 .name(name() + ".descDMAWrites")
233 .desc("Number of descriptors the device wrote w/ DMA")
238 .name(name() + ".descDmaReadBytes")
239 .desc("number of descriptor bytes read w/ DMA")
244 .name(name() + ".descDmaWriteBytes")
245 .desc("number of descriptor bytes write w/ DMA")
251 .name(name() + ".txBandwidth")
252 .desc("Transmit Bandwidth (bits/s)")
258 .name(name() + ".rxBandwidth")
259 .desc("Receive Bandwidth (bits/s)")
265 .name(name() + ".txPPS")
266 .desc("Packet Tranmission Rate (packets/s)")
272 .name(name() + ".rxPPS")
273 .desc("Packet Reception Rate (packets/s)")
278 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
279 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
280 txPacketRate
= txPackets
/ simSeconds
;
281 rxPacketRate
= rxPackets
/ simSeconds
;
285 * This is to read the PCI general configuration registers
288 NSGigE::ReadConfig(int offset
, int size
, uint8_t *data
)
290 if (offset
< PCI_DEVICE_SPECIFIC
)
291 PciDev::ReadConfig(offset
, size
, data
);
293 panic("Device specific PCI config space not implemented!\n");
297 * This is to write to the PCI general configuration registers
300 NSGigE::WriteConfig(int offset
, int size
, uint32_t data
)
302 if (offset
< PCI_DEVICE_SPECIFIC
)
303 PciDev::WriteConfig(offset
, size
, data
);
305 panic("Device specific PCI config space not implemented!\n");
307 // Need to catch writes to BARs to update the PIO interface
309 // seems to work fine without all these PCI settings, but i
310 // put in the IO to double check, an assertion will fail if we
311 // need to properly implement it
313 if (config
.data
[offset
] & PCI_CMD_IOSE
)
319 if (config
.data
[offset
] & PCI_CMD_BME
) {
326 if (config
.data
[offset
] & PCI_CMD_MSE
) {
335 case PCI0_BASE_ADDR0
:
336 if (BARAddrs
[0] != 0) {
338 pioInterface
->addAddrRange(BARAddrs
[0],
339 BARAddrs
[0] + BARSize
[0] - 1);
341 BARAddrs
[0] &= PA_UNCACHED_MASK
;
344 case PCI0_BASE_ADDR1
:
345 if (BARAddrs
[1] != 0) {
347 pioInterface
->addAddrRange(BARAddrs
[1],
348 BARAddrs
[1] + BARSize
[1] - 1);
350 BARAddrs
[1] &= PA_UNCACHED_MASK
;
357 * This reads the device registers, which are detailed in the NS83820
361 NSGigE::read(MemReqPtr
&req
, uint8_t *data
)
365 //The mask is to give you only the offset into the device register file
366 Addr daddr
= req
->paddr
& 0xfff;
367 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x va=%#x size=%d\n",
368 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
371 // there are some reserved registers, you can see ns_gige_reg.h and
372 // the spec sheet for details
373 if (daddr
> LAST
&& daddr
<= RESERVED
) {
374 panic("Accessing reserved register");
375 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
376 ReadConfig(daddr
& 0xff, req
->size
, data
);
378 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
379 // don't implement all the MIB's. hopefully the kernel
380 // doesn't actually DEPEND upon their values
381 // MIB are just hardware stats keepers
382 uint32_t ®
= *(uint32_t *) data
;
385 } else if (daddr
> 0x3FC)
386 panic("Something is messed up!\n");
389 case sizeof(uint32_t):
391 uint32_t ®
= *(uint32_t *)data
;
396 //these are supposed to be cleared on a read
397 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
414 devIntrClear(ISR_ALL
);
469 // see the spec sheet for how RFCR and RFDR work
470 // basically, you write to RFCR to tell the machine
471 // what you want to do next, then you act upon RFDR,
472 // and the device will be prepared b/c of what you
479 switch (regs
.rfcr
& RFCR_RFADDR
) {
481 reg
= rom
.perfectMatch
[1];
483 reg
+= rom
.perfectMatch
[0];
486 reg
= rom
.perfectMatch
[3] << 8;
487 reg
+= rom
.perfectMatch
[2];
490 reg
= rom
.perfectMatch
[5] << 8;
491 reg
+= rom
.perfectMatch
[4];
494 panic("reading RFDR for something other than PMATCH!\n");
495 // didn't implement other RFDR functionality b/c
496 // driver didn't use it
506 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
550 panic("reading unimplemented register: addr=%#x", daddr
);
553 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n",
559 panic("accessing register with invalid size: addr=%#x, size=%d",
567 NSGigE::write(MemReqPtr
&req
, const uint8_t *data
)
571 Addr daddr
= req
->paddr
& 0xfff;
572 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x va=%#x size=%d\n",
573 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
575 if (daddr
> LAST
&& daddr
<= RESERVED
) {
576 panic("Accessing reserved register");
577 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
578 WriteConfig(daddr
& 0xff, req
->size
, *(uint32_t *)data
);
580 } else if (daddr
> 0x3FC)
581 panic("Something is messed up!\n");
583 if (req
->size
== sizeof(uint32_t)) {
584 uint32_t reg
= *(uint32_t *)data
;
585 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
592 } else if (reg
& CR_TXE
) {
595 // the kernel is enabling the transmit machine
596 if (txState
== txIdle
)
602 } else if (reg
& CR_RXE
) {
605 if (rxState
== rxIdle
)
616 devIntrPost(ISR_SWI
);
627 if (reg
& CFG_LNKSTS
||
630 reg
& CFG_RESERVED
||
633 panic("writing to read-only or reserved CFG bits!\n");
635 regs
.config
|= reg
& ~(CFG_LNKSTS
| CFG_SPDSTS
| CFG_DUPSTS
|
636 CFG_RESERVED
| CFG_T64ADDR
| CFG_PCI64_DET
);
638 // all these #if 0's are because i don't THINK the kernel needs to
639 // have these implemented. if there is a problem relating to one of
640 // these, you may need to add functionality in.
642 if (reg
& CFG_TBI_EN
) ;
643 if (reg
& CFG_MODE_1000
) ;
646 if (reg
& CFG_AUTO_1000
)
647 panic("CFG_AUTO_1000 not implemented!\n");
650 if (reg
& CFG_PINT_DUPSTS
||
651 reg
& CFG_PINT_LNKSTS
||
652 reg
& CFG_PINT_SPDSTS
)
655 if (reg
& CFG_TMRTEST
) ;
656 if (reg
& CFG_MRM_DIS
) ;
657 if (reg
& CFG_MWI_DIS
) ;
659 if (reg
& CFG_T64ADDR
)
660 panic("CFG_T64ADDR is read only register!\n");
662 if (reg
& CFG_PCI64_DET
)
663 panic("CFG_PCI64_DET is read only register!\n");
665 if (reg
& CFG_DATA64_EN
) ;
666 if (reg
& CFG_M64ADDR
) ;
667 if (reg
& CFG_PHY_RST
) ;
668 if (reg
& CFG_PHY_DIS
) ;
671 if (reg
& CFG_EXTSTS_EN
)
674 extstsEnable
= false;
677 if (reg
& CFG_REQALG
) ;
681 if (reg
& CFG_PESEL
) ;
682 if (reg
& CFG_BROM_DIS
) ;
683 if (reg
& CFG_EXT_125
) ;
690 // since phy is completely faked, MEAR_MD* don't matter
691 // and since the driver never uses MEAR_EE*, they don't
694 if (reg
& MEAR_EEDI
) ;
695 if (reg
& MEAR_EEDO
) ; // this one is read only
696 if (reg
& MEAR_EECLK
) ;
697 if (reg
& MEAR_EESEL
) ;
698 if (reg
& MEAR_MDIO
) ;
699 if (reg
& MEAR_MDDIR
) ;
700 if (reg
& MEAR_MDC
) ;
705 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
706 // these control BISTs for various parts of chip - we
707 // don't care or do just fake that the BIST is done
708 if (reg
& PTSCR_RBIST_EN
)
709 regs
.ptscr
|= PTSCR_RBIST_DONE
;
710 if (reg
& PTSCR_EEBIST_EN
)
711 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
712 if (reg
& PTSCR_EELOAD_EN
)
713 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
716 case ISR
: /* writing to the ISR has no effect */
717 panic("ISR is a read only register!\n");
730 /* not going to implement real interrupt holdoff */
734 regs
.txdp
= (reg
& 0xFFFFFFFC);
735 assert(txState
== txIdle
);
746 if (reg
& TXCFG_CSI
) ;
747 if (reg
& TXCFG_HBI
) ;
748 if (reg
& TXCFG_MLB
) ;
749 if (reg
& TXCFG_ATP
) ;
750 if (reg
& TXCFG_ECRETRY
) {
752 * this could easily be implemented, but considering
753 * the network is just a fake pipe, wouldn't make
758 if (reg
& TXCFG_BRST_DIS
) ;
762 /* we handle our own DMA, ignore the kernel's exhortations */
763 if (reg
& TXCFG_MXDMA
) ;
766 // also, we currently don't care about fill/drain
767 // thresholds though this may change in the future with
768 // more realistic networks or a driver which changes it
769 // according to feedback
775 /* these just control general purpose i/o pins, don't matter */
790 if (reg
& RXCFG_AEP
) ;
791 if (reg
& RXCFG_ARP
) ;
792 if (reg
& RXCFG_STRIPCRC
) ;
793 if (reg
& RXCFG_RX_RD
) ;
794 if (reg
& RXCFG_ALP
) ;
795 if (reg
& RXCFG_AIRL
) ;
797 /* we handle our own DMA, ignore what kernel says about it */
798 if (reg
& RXCFG_MXDMA
) ;
800 //also, we currently don't care about fill/drain thresholds
801 //though this may change in the future with more realistic
802 //networks or a driver which changes it according to feedback
803 if (reg
& (RXCFG_DRTH
| RXCFG_DRTH0
)) ;
808 /* there is no priority queueing used in the linux 2.6 driver */
813 /* not going to implement wake on LAN */
818 /* not going to implement pause control */
825 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
826 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
827 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
828 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
829 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
830 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
834 panic("RFCR_APAT not implemented!\n");
837 if (reg
& RFCR_MHEN
|| reg
& RFCR_UHEN
)
838 panic("hash filtering not implemented!\n");
841 panic("RFCR_ULM not implemented!\n");
846 panic("the driver never writes to RFDR, something is wrong!\n");
849 panic("the driver never uses BRAR, something is wrong!\n");
852 panic("the driver never uses BRDR, something is wrong!\n");
855 panic("SRR is read only register!\n");
858 panic("the driver never uses MIBC, something is wrong!\n");
869 panic("the driver never uses VDR, something is wrong!\n");
873 /* not going to implement clockrun stuff */
879 if (reg
& TBICR_MR_LOOPBACK
)
880 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
882 if (reg
& TBICR_MR_AN_ENABLE
) {
883 regs
.tanlpar
= regs
.tanar
;
884 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
888 if (reg
& TBICR_MR_RESTART_AN
) ;
894 panic("TBISR is read only register!\n");
899 panic("this isn't used in driver, something wrong!\n");
902 panic("this isn't used in driver, something wrong!\n");
906 panic("this should only be written to by the fake phy!\n");
909 panic("TANER is read only register!\n");
916 panic("invalid register access daddr=%#x", daddr
);
919 panic("Invalid Request Size");
926 NSGigE::devIntrPost(uint32_t interrupts
)
928 if (interrupts
& ISR_RESERVE
)
929 panic("Cannot set a reserved interrupt");
931 if (interrupts
& ISR_NOIMPL
)
932 warn("interrupt not implemented %#x\n", interrupts
);
934 interrupts
&= ~ISR_NOIMPL
;
935 regs
.isr
|= interrupts
;
937 DPRINTF(EthernetIntr
,
938 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
939 interrupts
, regs
.isr
, regs
.imr
);
941 if ((regs
.isr
& regs
.imr
)) {
943 if (!(regs
.isr
& regs
.imr
& ISR_NODELAY
))
950 NSGigE::devIntrClear(uint32_t interrupts
)
952 if (interrupts
& ISR_RESERVE
)
953 panic("Cannot clear a reserved interrupt");
955 interrupts
&= ~ISR_NOIMPL
;
956 regs
.isr
&= ~interrupts
;
958 DPRINTF(EthernetIntr
,
959 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
960 interrupts
, regs
.isr
, regs
.imr
);
962 if (!(regs
.isr
& regs
.imr
))
967 NSGigE::devIntrChangeMask()
969 DPRINTF(EthernetIntr
, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
970 regs
.isr
, regs
.imr
, regs
.isr
& regs
.imr
);
972 if (regs
.isr
& regs
.imr
)
973 cpuIntrPost(curTick
);
979 NSGigE::cpuIntrPost(Tick when
)
981 // If the interrupt you want to post is later than an interrupt
982 // already scheduled, just let it post in the coming one and don't
984 // HOWEVER, must be sure that the scheduled intrTick is in the
985 // future (this was formerly the source of a bug)
987 * @todo this warning should be removed and the intrTick code should
990 if (intrTick
< curTick
&& intrTick
!= 0) {
991 warn("intrTick < curTick !!! intrTick=%d curTick=%d\n",
995 assert((intrTick
>= curTick
) || (intrTick
== 0));
996 if (when
> intrTick
&& intrTick
!= 0)
1002 intrEvent
->squash();
1006 if (when
< curTick
) {
1009 DPRINTF(EthernetIntr
,
1010 "going to schedule an interrupt for intrTick=%d\n",
1012 intrEvent
= new IntrEvent(this, true);
1013 intrEvent
->schedule(intrTick
);
1018 NSGigE::cpuInterrupt()
1020 // Don't send an interrupt if there's already one
1021 if (cpuPendingIntr
) {
1022 DPRINTF(EthernetIntr
,
1023 "would send an interrupt now, but there's already pending\n");
1027 // Don't send an interrupt if it's supposed to be delayed
1028 if (intrTick
> curTick
) {
1029 DPRINTF(EthernetIntr
,
1030 "an interrupt is scheduled for %d, wait til then\n",
1035 // Whether or not there's a pending interrupt, we don't care about
1041 cpuPendingIntr
= true;
1043 DPRINTF(EthernetIntr
, "posting cchip interrupt\n");
1044 tsunami
->cchip
->postDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
1048 NSGigE::cpuIntrClear()
1050 if (!cpuPendingIntr
)
1053 cpuPendingIntr
= false;
1055 DPRINTF(EthernetIntr
, "clearing cchip interrupt\n");
1056 tsunami
->cchip
->clearDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
1060 NSGigE::cpuIntrPending() const
1061 { return cpuPendingIntr
; }
1067 DPRINTF(Ethernet
, "transmit reset\n");
1070 txFifoAvail
= maxTxFifoSize
;
1073 assert(txDescCnt
== 0);
1076 assert(txDmaState
== dmaIdle
);
1082 DPRINTF(Ethernet
, "receive reset\n");
1085 assert(rxPktBytes
== 0);
1089 assert(rxDescCnt
== 0);
1090 assert(rxDmaState
== dmaIdle
);
1098 memset(®s
, 0, sizeof(regs
));
1099 regs
.config
= CFG_LNKSTS
;
1100 regs
.mear
= MEAR_MDDIR
| MEAR_EEDO
;
1101 regs
.txcfg
= 0x120; // set drain threshold to 1024 bytes and
1102 // fill threshold to 32 bytes
1103 regs
.rxcfg
= 0x4; // set drain threshold to 16 bytes
1104 regs
.srr
= 0x0103; // set the silicon revision to rev B or 0x103
1105 regs
.mibc
= MIBC_FRZ
;
1106 regs
.vdr
= 0x81; // set the vlan tag type to 802.1q
1107 regs
.tesr
= 0xc000; // TBI capable of both full and half duplex
1109 extstsEnable
= false;
1110 acceptBroadcast
= false;
1111 acceptMulticast
= false;
1112 acceptUnicast
= false;
1113 acceptPerfect
= false;
1118 NSGigE::rxDmaReadCopy()
1120 assert(rxDmaState
== dmaReading
);
1122 physmem
->dma_read((uint8_t *)rxDmaData
, rxDmaAddr
, rxDmaLen
);
1123 rxDmaState
= dmaIdle
;
1125 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1126 rxDmaAddr
, rxDmaLen
);
1127 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1131 NSGigE::doRxDmaRead()
1133 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1134 rxDmaState
= dmaReading
;
1136 if (dmaInterface
&& !rxDmaFree
) {
1137 if (dmaInterface
->busy())
1138 rxDmaState
= dmaReadWaiting
;
1140 dmaInterface
->doDMA(Read
, rxDmaAddr
, rxDmaLen
, curTick
,
1141 &rxDmaReadEvent
, true);
1145 if (dmaReadDelay
== 0 && dmaReadFactor
== 0) {
1150 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1151 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1152 rxDmaReadEvent
.schedule(start
);
1157 NSGigE::rxDmaReadDone()
1159 assert(rxDmaState
== dmaReading
);
1162 // If the transmit state machine has a pending DMA, let it go first
1163 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1170 NSGigE::rxDmaWriteCopy()
1172 assert(rxDmaState
== dmaWriting
);
1174 physmem
->dma_write(rxDmaAddr
, (uint8_t *)rxDmaData
, rxDmaLen
);
1175 rxDmaState
= dmaIdle
;
1177 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1178 rxDmaAddr
, rxDmaLen
);
1179 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1183 NSGigE::doRxDmaWrite()
1185 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1186 rxDmaState
= dmaWriting
;
1188 if (dmaInterface
&& !rxDmaFree
) {
1189 if (dmaInterface
->busy())
1190 rxDmaState
= dmaWriteWaiting
;
1192 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
, curTick
,
1193 &rxDmaWriteEvent
, true);
1197 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0) {
1202 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1203 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1204 rxDmaWriteEvent
.schedule(start
);
1209 NSGigE::rxDmaWriteDone()
1211 assert(rxDmaState
== dmaWriting
);
1214 // If the transmit state machine has a pending DMA, let it go first
1215 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1224 DPRINTF(EthernetSM
, "receive kick rxState=%s (rxBuf.size=%d)\n",
1225 NsRxStateStrings
[rxState
], rxFifo
.size());
1227 if (rxKickTick
> curTick
) {
1228 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
1234 switch(rxDmaState
) {
1235 case dmaReadWaiting
:
1239 case dmaWriteWaiting
:
1247 // see state machine from spec for details
1248 // the way this works is, if you finish work on one state and can
1249 // go directly to another, you do that through jumping to the
1250 // label "next". however, if you have intermediate work, like DMA
1251 // so that you can't go to the next state yet, you go to exit and
1252 // exit the loop. however, when the DMA is done it will trigger
1253 // an event and come back to this loop.
1257 DPRINTF(EthernetSM
, "Receive Disabled! Nothing to do.\n");
1262 rxState
= rxDescRefr
;
1264 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1265 rxDmaData
= &rxDescCache
+ offsetof(ns_desc
, link
);
1266 rxDmaLen
= sizeof(rxDescCache
.link
);
1267 rxDmaFree
= dmaDescFree
;
1270 descDmaRdBytes
+= rxDmaLen
;
1275 rxState
= rxDescRead
;
1277 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1278 rxDmaData
= &rxDescCache
;
1279 rxDmaLen
= sizeof(ns_desc
);
1280 rxDmaFree
= dmaDescFree
;
1283 descDmaRdBytes
+= rxDmaLen
;
1291 if (rxDmaState
!= dmaIdle
)
1294 rxState
= rxAdvance
;
1298 if (rxDmaState
!= dmaIdle
)
1301 DPRINTF(EthernetDesc
,
1302 "rxDescCache: addr=%08x read descriptor\n",
1303 regs
.rxdp
& 0x3fffffff);
1304 DPRINTF(EthernetDesc
,
1305 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
1306 rxDescCache
.link
, rxDescCache
.bufptr
, rxDescCache
.cmdsts
,
1307 rxDescCache
.extsts
);
1309 if (rxDescCache
.cmdsts
& CMDSTS_OWN
) {
1310 devIntrPost(ISR_RXIDLE
);
1314 rxState
= rxFifoBlock
;
1315 rxFragPtr
= rxDescCache
.bufptr
;
1316 rxDescCnt
= rxDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1323 * @todo in reality, we should be able to start processing
1324 * the packet as it arrives, and not have to wait for the
1325 * full packet ot be in the receive fifo.
1330 DPRINTF(EthernetSM
, "****processing receive of new packet****\n");
1332 // If we don't have a packet, grab a new one from the fifo.
1333 rxPacket
= rxFifo
.front();
1334 rxPktBytes
= rxPacket
->length
;
1335 rxPacketBufPtr
= rxPacket
->data
;
1338 if (DTRACE(Ethernet
)) {
1339 if (rxPacket
->isIpPkt()) {
1340 ip_header
*ip
= rxPacket
->getIpHdr();
1341 DPRINTF(Ethernet
, "ID is %d\n", reverseEnd16(ip
->ID
));
1342 if (rxPacket
->isTcpPkt()) {
1343 tcp_header
*tcp
= rxPacket
->getTcpHdr(ip
);
1344 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
1345 reverseEnd16(tcp
->src_port_num
),
1346 reverseEnd16(tcp
->dest_port_num
));
1352 // sanity check - i think the driver behaves like this
1353 assert(rxDescCnt
>= rxPktBytes
);
1355 // Must clear the value before popping to decrement the
1357 rxFifo
.front() = NULL
;
1359 rxFifoCnt
-= rxPacket
->length
;
1363 // dont' need the && rxDescCnt > 0 if driver sanity check
1365 if (rxPktBytes
> 0) {
1366 rxState
= rxFragWrite
;
1367 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1369 rxXferLen
= rxPktBytes
;
1371 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1372 rxDmaData
= rxPacketBufPtr
;
1373 rxDmaLen
= rxXferLen
;
1374 rxDmaFree
= dmaDataFree
;
1380 rxState
= rxDescWrite
;
1382 //if (rxPktBytes == 0) { /* packet is done */
1383 assert(rxPktBytes
== 0);
1384 DPRINTF(EthernetSM
, "done with receiving packet\n");
1386 rxDescCache
.cmdsts
|= CMDSTS_OWN
;
1387 rxDescCache
.cmdsts
&= ~CMDSTS_MORE
;
1388 rxDescCache
.cmdsts
|= CMDSTS_OK
;
1389 rxDescCache
.cmdsts
&= 0xffff0000;
1390 rxDescCache
.cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1394 * all the driver uses these are for its own stats keeping
1395 * which we don't care about, aren't necessary for
1396 * functionality and doing this would just slow us down.
1397 * if they end up using this in a later version for
1398 * functional purposes, just undef
1400 if (rxFilterEnable
) {
1401 rxDescCache
.cmdsts
&= ~CMDSTS_DEST_MASK
;
1402 if (rxFifo
.front()->IsUnicast())
1403 rxDescCache
.cmdsts
|= CMDSTS_DEST_SELF
;
1404 if (rxFifo
.front()->IsMulticast())
1405 rxDescCache
.cmdsts
|= CMDSTS_DEST_MULTI
;
1406 if (rxFifo
.front()->IsBroadcast())
1407 rxDescCache
.cmdsts
|= CMDSTS_DEST_MASK
;
1411 if (rxPacket
->isIpPkt() && extstsEnable
) {
1412 rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1414 if (!ipChecksum(rxPacket
, false)) {
1415 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
1416 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1418 if (rxPacket
->isTcpPkt()) {
1419 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1421 if (!tcpChecksum(rxPacket
, false)) {
1422 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
1423 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1426 } else if (rxPacket
->isUdpPkt()) {
1427 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1428 if (!udpChecksum(rxPacket
, false)) {
1429 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
1430 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1437 * the driver seems to always receive into desc buffers
1438 * of size 1514, so you never have a pkt that is split
1439 * into multiple descriptors on the receive side, so
1440 * i don't implement that case, hence the assert above.
1443 DPRINTF(EthernetDesc
,
1444 "rxDescCache: addr=%08x writeback cmdsts extsts\n",
1445 regs
.rxdp
& 0x3fffffff);
1446 DPRINTF(EthernetDesc
,
1447 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
1448 rxDescCache
.link
, rxDescCache
.bufptr
, rxDescCache
.cmdsts
,
1449 rxDescCache
.extsts
);
1451 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1452 rxDmaData
= &(rxDescCache
.cmdsts
);
1453 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1454 rxDmaFree
= dmaDescFree
;
1457 descDmaWrBytes
+= rxDmaLen
;
1465 if (rxDmaState
!= dmaIdle
)
1468 rxPacketBufPtr
+= rxXferLen
;
1469 rxFragPtr
+= rxXferLen
;
1470 rxPktBytes
-= rxXferLen
;
1472 rxState
= rxFifoBlock
;
1476 if (rxDmaState
!= dmaIdle
)
1479 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1481 assert(rxPacket
== 0);
1482 devIntrPost(ISR_RXOK
);
1484 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1485 devIntrPost(ISR_RXDESC
);
1488 DPRINTF(EthernetSM
, "Halting the RX state machine\n");
1492 rxState
= rxAdvance
;
1496 if (rxDescCache
.link
== 0) {
1497 devIntrPost(ISR_RXIDLE
);
1502 rxState
= rxDescRead
;
1503 regs
.rxdp
= rxDescCache
.link
;
1506 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1507 rxDmaData
= &rxDescCache
;
1508 rxDmaLen
= sizeof(ns_desc
);
1509 rxDmaFree
= dmaDescFree
;
1517 panic("Invalid rxState!");
1520 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
1521 NsRxStateStrings
[rxState
]);
1527 * @todo do we want to schedule a future kick?
1529 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
1530 NsRxStateStrings
[rxState
]);
1536 if (txFifo
.empty()) {
1537 DPRINTF(Ethernet
, "nothing to transmit\n");
1541 DPRINTF(Ethernet
, "Attempt Pkt Transmit: txFifo length=%d\n",
1542 maxTxFifoSize
- txFifoAvail
);
1543 if (interface
->sendPacket(txFifo
.front())) {
1545 if (DTRACE(Ethernet
)) {
1546 if (txFifo
.front()->isIpPkt()) {
1547 ip_header
*ip
= txFifo
.front()->getIpHdr();
1548 DPRINTF(Ethernet
, "ID is %d\n", reverseEnd16(ip
->ID
));
1549 if (txFifo
.front()->isTcpPkt()) {
1550 tcp_header
*tcp
= txFifo
.front()->getTcpHdr(ip
);
1551 DPRINTF(Ethernet
, "Src Port=%d, Dest Port=%d\n",
1552 reverseEnd16(tcp
->src_port_num
),
1553 reverseEnd16(tcp
->dest_port_num
));
1559 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1560 txBytes
+= txFifo
.front()->length
;
1563 txFifoAvail
+= txFifo
.front()->length
;
1565 DPRINTF(Ethernet
, "Successful Xmit! now txFifoAvail is %d\n",
1567 txFifo
.front() = NULL
;
1571 * normally do a writeback of the descriptor here, and ONLY
1572 * after that is done, send this interrupt. but since our
1573 * stuff never actually fails, just do this interrupt here,
1574 * otherwise the code has to stray from this nice format.
1575 * besides, it's functionally the same.
1577 devIntrPost(ISR_TXOK
);
1580 "May need to rethink always sending the descriptors back?\n");
1583 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1584 DPRINTF(Ethernet
, "reschedule transmit\n");
1585 txEvent
.schedule(curTick
+ 1000);
1590 NSGigE::txDmaReadCopy()
1592 assert(txDmaState
== dmaReading
);
1594 physmem
->dma_read((uint8_t *)txDmaData
, txDmaAddr
, txDmaLen
);
1595 txDmaState
= dmaIdle
;
1597 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1598 txDmaAddr
, txDmaLen
);
1599 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1603 NSGigE::doTxDmaRead()
1605 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1606 txDmaState
= dmaReading
;
1608 if (dmaInterface
&& !txDmaFree
) {
1609 if (dmaInterface
->busy())
1610 txDmaState
= dmaReadWaiting
;
1612 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1613 &txDmaReadEvent
, true);
1617 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1622 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1623 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1624 txDmaReadEvent
.schedule(start
);
1629 NSGigE::txDmaReadDone()
1631 assert(txDmaState
== dmaReading
);
1634 // If the receive state machine has a pending DMA, let it go first
1635 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1642 NSGigE::txDmaWriteCopy()
1644 assert(txDmaState
== dmaWriting
);
1646 physmem
->dma_write(txDmaAddr
, (uint8_t *)txDmaData
, txDmaLen
);
1647 txDmaState
= dmaIdle
;
1649 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1650 txDmaAddr
, txDmaLen
);
1651 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1655 NSGigE::doTxDmaWrite()
1657 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1658 txDmaState
= dmaWriting
;
1660 if (dmaInterface
&& !txDmaFree
) {
1661 if (dmaInterface
->busy())
1662 txDmaState
= dmaWriteWaiting
;
1664 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1665 &txDmaWriteEvent
, true);
1669 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1674 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1675 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1676 txDmaWriteEvent
.schedule(start
);
1681 NSGigE::txDmaWriteDone()
1683 assert(txDmaState
== dmaWriting
);
1686 // If the receive state machine has a pending DMA, let it go first
1687 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1696 DPRINTF(EthernetSM
, "transmit kick txState=%s\n",
1697 NsTxStateStrings
[txState
]);
1699 if (txKickTick
> curTick
) {
1700 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
1707 switch(txDmaState
) {
1708 case dmaReadWaiting
:
1712 case dmaWriteWaiting
:
1723 DPRINTF(EthernetSM
, "Transmit disabled. Nothing to do.\n");
1728 txState
= txDescRefr
;
1730 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1731 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1732 txDmaLen
= sizeof(txDescCache
.link
);
1733 txDmaFree
= dmaDescFree
;
1736 descDmaRdBytes
+= txDmaLen
;
1742 txState
= txDescRead
;
1744 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1745 txDmaData
= &txDescCache
;
1746 txDmaLen
= sizeof(ns_desc
);
1747 txDmaFree
= dmaDescFree
;
1750 descDmaRdBytes
+= txDmaLen
;
1758 if (txDmaState
!= dmaIdle
)
1761 txState
= txAdvance
;
1765 if (txDmaState
!= dmaIdle
)
1768 DPRINTF(EthernetDesc
,
1769 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
1770 txDescCache
.link
, txDescCache
.bufptr
, txDescCache
.cmdsts
,
1771 txDescCache
.extsts
);
1773 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1774 txState
= txFifoBlock
;
1775 txFragPtr
= txDescCache
.bufptr
;
1776 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1778 devIntrPost(ISR_TXIDLE
);
1786 DPRINTF(EthernetSM
, "****starting the tx of a new packet****\n");
1787 txPacket
= new EtherPacket
;
1788 txPacket
->data
= new uint8_t[16384];
1789 txPacketBufPtr
= txPacket
->data
;
1792 if (txDescCnt
== 0) {
1793 DPRINTF(EthernetSM
, "the txDescCnt == 0, done with descriptor\n");
1794 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1795 DPRINTF(EthernetSM
, "there are more descriptors to come\n");
1796 txState
= txDescWrite
;
1798 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1800 txDmaAddr
= regs
.txdp
+ offsetof(ns_desc
, cmdsts
);
1801 txDmaAddr
&= 0x3fffffff;
1802 txDmaData
= &(txDescCache
.cmdsts
);
1803 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1804 txDmaFree
= dmaDescFree
;
1809 } else { /* this packet is totally done */
1810 DPRINTF(EthernetSM
, "This packet is done, let's wrap it up\n");
1811 /* deal with the the packet that just finished */
1812 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1813 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1814 udpChecksum(txPacket
, true);
1815 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1816 tcpChecksum(txPacket
, true);
1819 if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1820 ipChecksum(txPacket
, true);
1825 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1826 // this is just because the receive can't handle a
1827 // packet bigger want to make sure
1828 assert(txPacket
->length
<= 1514);
1829 txFifo
.push_back(txPacket
);
1832 * this following section is not tqo spec, but
1833 * functionally shouldn't be any different. normally,
1834 * the chip will wait til the transmit has occurred
1835 * before writing back the descriptor because it has
1836 * to wait to see that it was successfully transmitted
1837 * to decide whether to set CMDSTS_OK or not.
1838 * however, in the simulator since it is always
1839 * successfully transmitted, and writing it exactly to
1840 * spec would complicate the code, we just do it here
1843 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1844 txDescCache
.cmdsts
|= CMDSTS_OK
;
1846 DPRINTF(EthernetDesc
,
1847 "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1848 txDescCache
.cmdsts
, txDescCache
.extsts
);
1850 txDmaAddr
= regs
.txdp
+ offsetof(ns_desc
, cmdsts
);
1851 txDmaAddr
&= 0x3fffffff;
1852 txDmaData
= &(txDescCache
.cmdsts
);
1853 txDmaLen
= sizeof(txDescCache
.cmdsts
) +
1854 sizeof(txDescCache
.extsts
);
1855 txDmaFree
= dmaDescFree
;
1858 descDmaWrBytes
+= txDmaLen
;
1864 DPRINTF(EthernetSM
, "halting TX state machine\n");
1868 txState
= txAdvance
;
1874 DPRINTF(EthernetSM
, "this descriptor isn't done yet\n");
1876 txState
= txFragRead
;
1879 * The number of bytes transferred is either whatever
1880 * is left in the descriptor (txDescCnt), or if there
1881 * is not enough room in the fifo, just whatever room
1882 * is left in the fifo
1884 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1886 txDmaAddr
= txFragPtr
& 0x3fffffff;
1887 txDmaData
= txPacketBufPtr
;
1888 txDmaLen
= txXferLen
;
1889 txDmaFree
= dmaDataFree
;
1894 txState
= txFifoBlock
;
1904 if (txDmaState
!= dmaIdle
)
1907 txPacketBufPtr
+= txXferLen
;
1908 txFragPtr
+= txXferLen
;
1909 txDescCnt
-= txXferLen
;
1910 txFifoAvail
-= txXferLen
;
1912 txState
= txFifoBlock
;
1916 if (txDmaState
!= dmaIdle
)
1919 if (txDescCache
.cmdsts
& CMDSTS_INTR
)
1920 devIntrPost(ISR_TXDESC
);
1922 txState
= txAdvance
;
1926 if (txDescCache
.link
== 0) {
1927 devIntrPost(ISR_TXIDLE
);
1931 txState
= txDescRead
;
1932 regs
.txdp
= txDescCache
.link
;
1935 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1936 txDmaData
= &txDescCache
;
1937 txDmaLen
= sizeof(ns_desc
);
1938 txDmaFree
= dmaDescFree
;
1946 panic("invalid state");
1949 DPRINTF(EthernetSM
, "entering next txState=%s\n",
1950 NsTxStateStrings
[txState
]);
1956 * @todo do we want to schedule a future kick?
1958 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
1959 NsTxStateStrings
[txState
]);
1963 NSGigE::transferDone()
1965 if (txFifo
.empty()) {
1966 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
1970 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
1972 if (txEvent
.scheduled())
1973 txEvent
.reschedule(curTick
+ 1);
1975 txEvent
.schedule(curTick
+ 1);
1979 NSGigE::rxFilter(PacketPtr packet
)
1984 if (packet
->IsUnicast()) {
1987 // If we're accepting all unicast addresses
1991 // If we make a perfect match
1992 if (acceptPerfect
&&
1993 memcmp(rom
.perfectMatch
, packet
->data
, EADDR_LEN
) == 0)
1996 eth_header
*eth
= (eth_header
*) packet
->data
;
1997 if ((acceptArp
) && (eth
->type
== 0x608))
2000 } else if (packet
->IsBroadcast()) {
2003 // if we're accepting broadcasts
2004 if (acceptBroadcast
)
2007 } else if (packet
->IsMulticast()) {
2010 // if we're accepting all multicasts
2011 if (acceptMulticast
)
2017 // oh well, punt on this one
2021 DPRINTF(Ethernet
, "rxFilter drop\n");
2022 DDUMP(EthernetData
, packet
->data
, packet
->length
);
2029 NSGigE::recvPacket(PacketPtr packet
)
2031 rxBytes
+= packet
->length
;
2034 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifoAvail=%d\n",
2035 maxRxFifoSize
- rxFifoCnt
);
2038 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
2040 interface
->recvDone();
2044 if (rxFilterEnable
&& rxFilter(packet
)) {
2045 DPRINTF(Ethernet
, "packet filtered...dropped\n");
2046 interface
->recvDone();
2050 if ((rxFifoCnt
+ packet
->length
) >= maxRxFifoSize
) {
2052 "packet will not fit in receive buffer...packet dropped\n");
2053 devIntrPost(ISR_RXORN
);
2057 rxFifo
.push_back(packet
);
2058 rxFifoCnt
+= packet
->length
;
2059 interface
->recvDone();
2066 * does a udp checksum. if gen is true, then it generates it and puts
2067 * it in the right place else, it just checks what it calculates
2068 * against the value in the header in packet
2071 NSGigE::udpChecksum(PacketPtr packet
, bool gen
)
2073 ip_header
*ip
= packet
->getIpHdr();
2074 udp_header
*hdr
= packet
->getUdpHdr(ip
);
2076 pseudo_header
*pseudo
= new pseudo_header
;
2078 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
2079 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
2080 pseudo
->protocol
= ip
->protocol
;
2081 pseudo
->len
= hdr
->len
;
2083 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
2084 (uint32_t) hdr
->len
);
2088 hdr
->chksum
= cksum
;
2097 NSGigE::tcpChecksum(PacketPtr packet
, bool gen
)
2099 ip_header
*ip
= packet
->getIpHdr();
2100 tcp_header
*hdr
= packet
->getTcpHdr(ip
);
2103 pseudo_header
*pseudo
= new pseudo_header
;
2105 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
2106 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
2107 pseudo
->protocol
= reverseEnd16(ip
->protocol
);
2108 pseudo
->len
= reverseEnd16(reverseEnd16(ip
->dgram_len
) -
2109 (ip
->vers_len
& 0xf)*4);
2111 cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
2112 (uint32_t) reverseEnd16(pseudo
->len
));
2114 pseudo
->src_ip_addr
= 0;
2115 pseudo
->dest_ip_addr
= 0;
2116 pseudo
->protocol
= hdr
->chksum
;
2119 cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
2120 (uint32_t) (reverseEnd16(ip
->dgram_len
) -
2121 (ip
->vers_len
& 0xf)*4));
2126 hdr
->chksum
= cksum
;
2135 NSGigE::ipChecksum(PacketPtr packet
, bool gen
)
2137 ip_header
*hdr
= packet
->getIpHdr();
2139 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
,
2140 (hdr
->vers_len
& 0xf)*4);
2143 DPRINTF(EthernetCksum
, "generated checksum: %#x\n", cksum
);
2144 hdr
->hdr_chksum
= cksum
;
2154 NSGigE::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
2158 uint16_t last_pad
= 0;
2160 last_pad
= buf
[len
/2] & 0xff;
2166 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
2167 pseudo
[3] + pseudo
[4] + pseudo
[5];
2170 for (int i
=0; i
< (len
/2); ++i
) {
2175 sum
= (sum
>> 16) + (sum
& 0xffff);
2180 //=====================================================================
2184 NSGigE::serialize(ostream
&os
)
2186 // Serialize the PciDev base class
2187 PciDev::serialize(os
);
2190 * Finalize any DMA events now.
2192 if (rxDmaReadEvent
.scheduled())
2194 if (rxDmaWriteEvent
.scheduled())
2196 if (txDmaReadEvent
.scheduled())
2198 if (txDmaWriteEvent
.scheduled())
2202 * Serialize the device registers
2204 SERIALIZE_SCALAR(regs
.command
);
2205 SERIALIZE_SCALAR(regs
.config
);
2206 SERIALIZE_SCALAR(regs
.mear
);
2207 SERIALIZE_SCALAR(regs
.ptscr
);
2208 SERIALIZE_SCALAR(regs
.isr
);
2209 SERIALIZE_SCALAR(regs
.imr
);
2210 SERIALIZE_SCALAR(regs
.ier
);
2211 SERIALIZE_SCALAR(regs
.ihr
);
2212 SERIALIZE_SCALAR(regs
.txdp
);
2213 SERIALIZE_SCALAR(regs
.txdp_hi
);
2214 SERIALIZE_SCALAR(regs
.txcfg
);
2215 SERIALIZE_SCALAR(regs
.gpior
);
2216 SERIALIZE_SCALAR(regs
.rxdp
);
2217 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2218 SERIALIZE_SCALAR(regs
.rxcfg
);
2219 SERIALIZE_SCALAR(regs
.pqcr
);
2220 SERIALIZE_SCALAR(regs
.wcsr
);
2221 SERIALIZE_SCALAR(regs
.pcr
);
2222 SERIALIZE_SCALAR(regs
.rfcr
);
2223 SERIALIZE_SCALAR(regs
.rfdr
);
2224 SERIALIZE_SCALAR(regs
.srr
);
2225 SERIALIZE_SCALAR(regs
.mibc
);
2226 SERIALIZE_SCALAR(regs
.vrcr
);
2227 SERIALIZE_SCALAR(regs
.vtcr
);
2228 SERIALIZE_SCALAR(regs
.vdr
);
2229 SERIALIZE_SCALAR(regs
.ccsr
);
2230 SERIALIZE_SCALAR(regs
.tbicr
);
2231 SERIALIZE_SCALAR(regs
.tbisr
);
2232 SERIALIZE_SCALAR(regs
.tanar
);
2233 SERIALIZE_SCALAR(regs
.tanlpar
);
2234 SERIALIZE_SCALAR(regs
.taner
);
2235 SERIALIZE_SCALAR(regs
.tesr
);
2237 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2239 SERIALIZE_SCALAR(ioEnable
);
2242 * Serialize the data Fifos
2244 int txNumPkts
= txFifo
.size();
2245 SERIALIZE_SCALAR(txNumPkts
);
2247 pktiter_t end
= txFifo
.end();
2248 for (pktiter_t p
= txFifo
.begin(); p
!= end
; ++p
) {
2249 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2250 (*p
)->serialize(os
);
2253 int rxNumPkts
= rxFifo
.size();
2254 SERIALIZE_SCALAR(rxNumPkts
);
2257 for (pktiter_t p
= rxFifo
.begin(); p
!= end
; ++p
) {
2258 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2259 (*p
)->serialize(os
);
2263 * Serialize the various helper variables
2265 bool txPacketExists
= txPacket
;
2266 SERIALIZE_SCALAR(txPacketExists
);
2267 if (txPacketExists
) {
2268 nameOut(os
, csprintf("%s.txPacket", name()));
2269 txPacket
->serialize(os
);
2270 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
2271 SERIALIZE_SCALAR(txPktBufPtr
);
2274 bool rxPacketExists
= rxPacket
;
2275 SERIALIZE_SCALAR(rxPacketExists
);
2276 if (rxPacketExists
) {
2277 nameOut(os
, csprintf("%s.rxPacket", name()));
2278 rxPacket
->serialize(os
);
2279 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
2280 SERIALIZE_SCALAR(rxPktBufPtr
);
2283 SERIALIZE_SCALAR(txXferLen
);
2284 SERIALIZE_SCALAR(rxXferLen
);
2287 * Serialize DescCaches
2289 SERIALIZE_SCALAR(txDescCache
.link
);
2290 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2291 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2292 SERIALIZE_SCALAR(txDescCache
.extsts
);
2293 SERIALIZE_SCALAR(rxDescCache
.link
);
2294 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2295 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2296 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2299 * Serialize tx state machine
2301 int txState
= this->txState
;
2302 SERIALIZE_SCALAR(txState
);
2303 SERIALIZE_SCALAR(txEnable
);
2304 SERIALIZE_SCALAR(CTDD
);
2305 SERIALIZE_SCALAR(txFifoAvail
);
2306 SERIALIZE_SCALAR(txFragPtr
);
2307 SERIALIZE_SCALAR(txDescCnt
);
2308 int txDmaState
= this->txDmaState
;
2309 SERIALIZE_SCALAR(txDmaState
);
2312 * Serialize rx state machine
2314 int rxState
= this->rxState
;
2315 SERIALIZE_SCALAR(rxState
);
2316 SERIALIZE_SCALAR(rxEnable
);
2317 SERIALIZE_SCALAR(CRDD
);
2318 SERIALIZE_SCALAR(rxPktBytes
);
2319 SERIALIZE_SCALAR(rxFifoCnt
);
2320 SERIALIZE_SCALAR(rxDescCnt
);
2321 int rxDmaState
= this->rxDmaState
;
2322 SERIALIZE_SCALAR(rxDmaState
);
2324 SERIALIZE_SCALAR(extstsEnable
);
2327 * If there's a pending transmit, store the time so we can
2328 * reschedule it later
2330 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2331 SERIALIZE_SCALAR(transmitTick
);
2334 * receive address filter settings
2336 SERIALIZE_SCALAR(rxFilterEnable
);
2337 SERIALIZE_SCALAR(acceptBroadcast
);
2338 SERIALIZE_SCALAR(acceptMulticast
);
2339 SERIALIZE_SCALAR(acceptUnicast
);
2340 SERIALIZE_SCALAR(acceptPerfect
);
2341 SERIALIZE_SCALAR(acceptArp
);
2344 * Keep track of pending interrupt status.
2346 SERIALIZE_SCALAR(intrTick
);
2347 SERIALIZE_SCALAR(cpuPendingIntr
);
2348 Tick intrEventTick
= 0;
2350 intrEventTick
= intrEvent
->when();
2351 SERIALIZE_SCALAR(intrEventTick
);
2356 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2358 // Unserialize the PciDev base class
2359 PciDev::unserialize(cp
, section
);
2361 UNSERIALIZE_SCALAR(regs
.command
);
2362 UNSERIALIZE_SCALAR(regs
.config
);
2363 UNSERIALIZE_SCALAR(regs
.mear
);
2364 UNSERIALIZE_SCALAR(regs
.ptscr
);
2365 UNSERIALIZE_SCALAR(regs
.isr
);
2366 UNSERIALIZE_SCALAR(regs
.imr
);
2367 UNSERIALIZE_SCALAR(regs
.ier
);
2368 UNSERIALIZE_SCALAR(regs
.ihr
);
2369 UNSERIALIZE_SCALAR(regs
.txdp
);
2370 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2371 UNSERIALIZE_SCALAR(regs
.txcfg
);
2372 UNSERIALIZE_SCALAR(regs
.gpior
);
2373 UNSERIALIZE_SCALAR(regs
.rxdp
);
2374 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2375 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2376 UNSERIALIZE_SCALAR(regs
.pqcr
);
2377 UNSERIALIZE_SCALAR(regs
.wcsr
);
2378 UNSERIALIZE_SCALAR(regs
.pcr
);
2379 UNSERIALIZE_SCALAR(regs
.rfcr
);
2380 UNSERIALIZE_SCALAR(regs
.rfdr
);
2381 UNSERIALIZE_SCALAR(regs
.srr
);
2382 UNSERIALIZE_SCALAR(regs
.mibc
);
2383 UNSERIALIZE_SCALAR(regs
.vrcr
);
2384 UNSERIALIZE_SCALAR(regs
.vtcr
);
2385 UNSERIALIZE_SCALAR(regs
.vdr
);
2386 UNSERIALIZE_SCALAR(regs
.ccsr
);
2387 UNSERIALIZE_SCALAR(regs
.tbicr
);
2388 UNSERIALIZE_SCALAR(regs
.tbisr
);
2389 UNSERIALIZE_SCALAR(regs
.tanar
);
2390 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2391 UNSERIALIZE_SCALAR(regs
.taner
);
2392 UNSERIALIZE_SCALAR(regs
.tesr
);
2394 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2396 UNSERIALIZE_SCALAR(ioEnable
);
2399 * unserialize the data fifos
2402 UNSERIALIZE_SCALAR(txNumPkts
);
2404 for (i
= 0; i
< txNumPkts
; ++i
) {
2405 PacketPtr p
= new EtherPacket
;
2406 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2407 txFifo
.push_back(p
);
2411 UNSERIALIZE_SCALAR(rxNumPkts
);
2412 for (i
= 0; i
< rxNumPkts
; ++i
) {
2413 PacketPtr p
= new EtherPacket
;
2414 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2415 rxFifo
.push_back(p
);
2419 * unserialize the various helper variables
2421 bool txPacketExists
;
2422 UNSERIALIZE_SCALAR(txPacketExists
);
2423 if (txPacketExists
) {
2424 txPacket
= new EtherPacket
;
2425 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2426 uint32_t txPktBufPtr
;
2427 UNSERIALIZE_SCALAR(txPktBufPtr
);
2428 txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
2432 bool rxPacketExists
;
2433 UNSERIALIZE_SCALAR(rxPacketExists
);
2435 if (rxPacketExists
) {
2436 rxPacket
= new EtherPacket
;
2437 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2438 uint32_t rxPktBufPtr
;
2439 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2440 rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
2444 UNSERIALIZE_SCALAR(txXferLen
);
2445 UNSERIALIZE_SCALAR(rxXferLen
);
2448 * Unserialize DescCaches
2450 UNSERIALIZE_SCALAR(txDescCache
.link
);
2451 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2452 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2453 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2454 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2455 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2456 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2457 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2460 * unserialize tx state machine
2463 UNSERIALIZE_SCALAR(txState
);
2464 this->txState
= (TxState
) txState
;
2465 UNSERIALIZE_SCALAR(txEnable
);
2466 UNSERIALIZE_SCALAR(CTDD
);
2467 UNSERIALIZE_SCALAR(txFifoAvail
);
2468 UNSERIALIZE_SCALAR(txFragPtr
);
2469 UNSERIALIZE_SCALAR(txDescCnt
);
2471 UNSERIALIZE_SCALAR(txDmaState
);
2472 this->txDmaState
= (DmaState
) txDmaState
;
2475 * unserialize rx state machine
2478 UNSERIALIZE_SCALAR(rxState
);
2479 this->rxState
= (RxState
) rxState
;
2480 UNSERIALIZE_SCALAR(rxEnable
);
2481 UNSERIALIZE_SCALAR(CRDD
);
2482 UNSERIALIZE_SCALAR(rxPktBytes
);
2483 UNSERIALIZE_SCALAR(rxFifoCnt
);
2484 UNSERIALIZE_SCALAR(rxDescCnt
);
2486 UNSERIALIZE_SCALAR(rxDmaState
);
2487 this->rxDmaState
= (DmaState
) rxDmaState
;
2489 UNSERIALIZE_SCALAR(extstsEnable
);
2492 * If there's a pending transmit, reschedule it now
2495 UNSERIALIZE_SCALAR(transmitTick
);
2497 txEvent
.schedule(curTick
+ transmitTick
);
2500 * unserialize receive address filter settings
2502 UNSERIALIZE_SCALAR(rxFilterEnable
);
2503 UNSERIALIZE_SCALAR(acceptBroadcast
);
2504 UNSERIALIZE_SCALAR(acceptMulticast
);
2505 UNSERIALIZE_SCALAR(acceptUnicast
);
2506 UNSERIALIZE_SCALAR(acceptPerfect
);
2507 UNSERIALIZE_SCALAR(acceptArp
);
2510 * Keep track of pending interrupt status.
2512 UNSERIALIZE_SCALAR(intrTick
);
2513 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2515 UNSERIALIZE_SCALAR(intrEventTick
);
2516 if (intrEventTick
) {
2517 intrEvent
= new IntrEvent(this, true);
2518 intrEvent
->schedule(intrEventTick
);
2522 * re-add addrRanges to bus bridges
2525 pioInterface
->addAddrRange(BARAddrs
[0], BARAddrs
[0] + BARSize
[0] - 1);
2526 pioInterface
->addAddrRange(BARAddrs
[1], BARAddrs
[1] + BARSize
[1] - 1);
2531 NSGigE::cacheAccess(MemReqPtr
&req
)
2533 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2534 req
->paddr
, req
->paddr
- addr
);
2535 return curTick
+ pioLatency
;
2537 //=====================================================================
2540 //********** helper functions******************************************
2542 uint16_t reverseEnd16(uint16_t num
)
2544 uint16_t reverse
= (num
& 0xff)<<8;
2545 reverse
+= ((num
& 0xff00) >> 8);
2549 uint32_t reverseEnd32(uint32_t num
)
2551 uint32_t reverse
= (reverseEnd16(num
& 0xffff)) << 16;
2552 reverse
+= reverseEnd16((uint16_t) ((num
& 0xffff0000) >> 8));
2558 //=====================================================================
2560 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2562 SimObjectParam
<EtherInt
*> peer
;
2563 SimObjectParam
<NSGigE
*> device
;
2565 END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2567 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2569 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2570 INIT_PARAM(device
, "Ethernet device of this interface")
2572 END_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2574 CREATE_SIM_OBJECT(NSGigEInt
)
2576 NSGigEInt
*dev_int
= new NSGigEInt(getInstanceName(), device
);
2578 EtherInt
*p
= (EtherInt
*)peer
;
2580 dev_int
->setPeer(p
);
2581 p
->setPeer(dev_int
);
2587 REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt
)
2590 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2592 Param
<Tick
> tx_delay
;
2593 Param
<Tick
> rx_delay
;
2594 SimObjectParam
<IntrControl
*> intr_ctrl
;
2595 Param
<Tick
> intr_delay
;
2596 SimObjectParam
<MemoryController
*> mmu
;
2597 SimObjectParam
<PhysicalMemory
*> physmem
;
2598 Param
<bool> rx_filter
;
2599 Param
<string
> hardware_address
;
2600 SimObjectParam
<Bus
*> header_bus
;
2601 SimObjectParam
<Bus
*> payload_bus
;
2602 SimObjectParam
<HierParams
*> hier
;
2603 Param
<Tick
> pio_latency
;
2604 Param
<bool> dma_desc_free
;
2605 Param
<bool> dma_data_free
;
2606 Param
<Tick
> dma_read_delay
;
2607 Param
<Tick
> dma_write_delay
;
2608 Param
<Tick
> dma_read_factor
;
2609 Param
<Tick
> dma_write_factor
;
2610 SimObjectParam
<PciConfigAll
*> configspace
;
2611 SimObjectParam
<PciConfigData
*> configdata
;
2612 SimObjectParam
<Tsunami
*> tsunami
;
2613 Param
<uint32_t> pci_bus
;
2614 Param
<uint32_t> pci_dev
;
2615 Param
<uint32_t> pci_func
;
2616 Param
<uint32_t> tx_fifo_size
;
2617 Param
<uint32_t> rx_fifo_size
;
2619 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2621 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2623 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2624 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2625 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2626 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2627 INIT_PARAM(mmu
, "Memory Controller"),
2628 INIT_PARAM(physmem
, "Physical Memory"),
2629 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2630 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2631 "00:99:00:00:00:01"),
2632 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2633 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2634 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2635 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
2636 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2637 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2638 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2639 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2640 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2641 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2642 INIT_PARAM(configspace
, "PCI Configspace"),
2643 INIT_PARAM(configdata
, "PCI Config data"),
2644 INIT_PARAM(tsunami
, "Tsunami"),
2645 INIT_PARAM(pci_bus
, "PCI bus"),
2646 INIT_PARAM(pci_dev
, "PCI device number"),
2647 INIT_PARAM(pci_func
, "PCI function code"),
2648 INIT_PARAM_DFLT(tx_fifo_size
, "max size in bytes of txFifo", 131072),
2649 INIT_PARAM_DFLT(rx_fifo_size
, "max size in bytes of rxFifo", 131072)
2651 END_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2654 CREATE_SIM_OBJECT(NSGigE
)
2657 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2658 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2660 return new NSGigE(getInstanceName(), intr_ctrl
, intr_delay
,
2661 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2662 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2663 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2664 dma_write_factor
, configspace
, configdata
,
2665 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
,
2666 tx_fifo_size
, rx_fifo_size
);
2669 REGISTER_SIM_OBJECT("NSGigE", NSGigE
)