2 * Copyright (c) 2004 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Device module for modelling the National Semiconductor
31 * DP83820 ethernet controller. Does not support priority queueing
37 #include "base/inet.hh"
38 #include "cpu/exec_context.hh"
39 #include "cpu/intr_control.hh"
41 #include "dev/ns_gige.hh"
42 #include "dev/etherlink.hh"
43 #include "mem/bus/bus.hh"
44 #include "mem/bus/dma_interface.hh"
45 #include "mem/bus/pio_interface.hh"
46 #include "mem/bus/pio_interface_impl.hh"
47 #include "mem/functional_mem/memory_control.hh"
48 #include "mem/functional_mem/physical_memory.hh"
49 #include "sim/builder.hh"
50 #include "sim/host.hh"
51 #include "sim/sim_stats.hh"
52 #include "targetarch/vtophys.hh"
53 #include "dev/pciconfigall.hh"
54 #include "dev/tsunami_cchip.hh"
56 const char *NsRxStateStrings
[] =
67 const char *NsTxStateStrings
[] =
78 const char *NsDmaState
[] =
89 ///////////////////////////////////////////////////////////////////////
93 NSGigE::NSGigE(const std::string
&name
, IntrControl
*i
, Tick intr_delay
,
94 PhysicalMemory
*pmem
, Tick tx_delay
, Tick rx_delay
,
95 MemoryController
*mmu
, HierParams
*hier
, Bus
*header_bus
,
96 Bus
*payload_bus
, Tick pio_latency
, bool dma_desc_free
,
97 bool dma_data_free
, Tick dma_read_delay
, Tick dma_write_delay
,
98 Tick dma_read_factor
, Tick dma_write_factor
, PciConfigAll
*cf
,
99 PciConfigData
*cd
, Tsunami
*t
, uint32_t bus
, uint32_t dev
,
100 uint32_t func
, bool rx_filter
, const int eaddr
[6])
101 : PciDev(name
, mmu
, cf
, cd
, bus
, dev
, func
), tsunami(t
), io_enable(false),
102 txPacket(0), rxPacket(0), txPacketBufPtr(NULL
), rxPacketBufPtr(NULL
),
103 txXferLen(0), rxXferLen(0), txPktXmitted(0), txState(txIdle
), CTDD(false),
104 txFifoCnt(0), txFifoAvail(MAX_TX_FIFO_SIZE
), txHalt(false),
105 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle
), rxState(rxIdle
),
106 CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false),
107 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle
), extstsEnable(false),
108 rxDmaReadEvent(this), rxDmaWriteEvent(this),
109 txDmaReadEvent(this), txDmaWriteEvent(this),
110 dmaDescFree(dma_desc_free
), dmaDataFree(dma_data_free
),
111 txDelay(tx_delay
), rxDelay(rx_delay
), rxKickTick(0), txKickTick(0),
112 txEvent(this), rxFilterEnable(rx_filter
), acceptBroadcast(false),
113 acceptMulticast(false), acceptUnicast(false),
114 acceptPerfect(false), acceptArp(false),
115 physmem(pmem
), intctrl(i
), intrTick(0),
116 cpuPendingIntr(false), intrEvent(0), interface(0), pioLatency(pio_latency
)
118 tsunami
->ethernet
= this;
121 pioInterface
= newPioInterface(name
, hier
, header_bus
, this,
122 &NSGigE::cacheAccess
);
125 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
126 header_bus
, payload_bus
, 1);
128 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma",
129 header_bus
, header_bus
, 1);
130 } else if (payload_bus
) {
131 pioInterface
= newPioInterface(name
, hier
, payload_bus
, this,
132 &NSGigE::cacheAccess
);
134 dmaInterface
= new DMAInterface
<Bus
>(name
+ ".dma", payload_bus
,
140 intrDelay
= US2Ticks(intr_delay
);
141 dmaReadDelay
= dma_read_delay
;
142 dmaWriteDelay
= dma_write_delay
;
143 dmaReadFactor
= dma_read_factor
;
144 dmaWriteFactor
= dma_write_factor
;
146 memset(®s
, 0, sizeof(regs
));
148 rom
.perfectMatch
[0] = eaddr
[0];
149 rom
.perfectMatch
[1] = eaddr
[1];
150 rom
.perfectMatch
[2] = eaddr
[2];
151 rom
.perfectMatch
[3] = eaddr
[3];
152 rom
.perfectMatch
[4] = eaddr
[4];
153 rom
.perfectMatch
[5] = eaddr
[5];
163 .name(name() + ".txBytes")
164 .desc("Bytes Transmitted")
169 .name(name() + ".rxBytes")
170 .desc("Bytes Received")
175 .name(name() + ".txPackets")
176 .desc("Number of Packets Transmitted")
181 .name(name() + ".rxPackets")
182 .desc("Number of Packets Received")
187 .name(name() + ".txBandwidth")
188 .desc("Transmit Bandwidth (bits/s)")
194 .name(name() + ".rxBandwidth")
195 .desc("Receive Bandwidth (bits/s)")
201 .name(name() + ".txPPS")
202 .desc("Packet Tranmission Rate (packets/s)")
208 .name(name() + ".rxPPS")
209 .desc("Packet Reception Rate (packets/s)")
214 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
215 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
216 txPacketRate
= txPackets
/ simSeconds
;
217 rxPacketRate
= rxPackets
/ simSeconds
;
221 * This is to read the PCI general configuration registers
224 NSGigE::ReadConfig(int offset
, int size
, uint8_t *data
)
226 if (offset
< PCI_DEVICE_SPECIFIC
)
227 PciDev::ReadConfig(offset
, size
, data
);
229 panic("Device specific PCI config space not implemented!\n");
233 * This is to write to the PCI general configuration registers
236 NSGigE::WriteConfig(int offset
, int size
, uint32_t data
)
238 if (offset
< PCI_DEVICE_SPECIFIC
)
239 PciDev::WriteConfig(offset
, size
, data
);
241 panic("Device specific PCI config space not implemented!\n");
243 // Need to catch writes to BARs to update the PIO interface
245 //seems to work fine without all these, but i ut in the IO to
246 //double check, an assertion will fail if we need to properly
249 if (config
.data
[offset
] & PCI_CMD_IOSE
)
254 if (config
.data
[offset
] & PCI_CMD_BME
)
260 if (config
.data
[offset
] & PCI_CMD_MSE
)
267 case PCI0_BASE_ADDR0
:
268 if (BARAddrs
[0] != 0) {
271 pioInterface
->addAddrRange(BARAddrs
[0], BARAddrs
[0] + BARSize
[0] - 1);
273 BARAddrs
[0] &= PA_UNCACHED_MASK
;
277 case PCI0_BASE_ADDR1
:
278 if (BARAddrs
[1] != 0) {
281 pioInterface
->addAddrRange(BARAddrs
[1], BARAddrs
[1] + BARSize
[1] - 1);
283 BARAddrs
[1] &= PA_UNCACHED_MASK
;
291 * This reads the device registers, which are detailed in the NS83820
295 NSGigE::read(MemReqPtr
&req
, uint8_t *data
)
299 //The mask is to give you only the offset into the device register file
300 Addr daddr
= req
->paddr
& 0xfff;
301 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x va=%#x size=%d\n",
302 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
305 //there are some reserved registers, you can see ns_gige_reg.h and
306 //the spec sheet for details
307 if (daddr
> LAST
&& daddr
<= RESERVED
) {
308 panic("Accessing reserved register");
309 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
310 ReadConfig(daddr
& 0xff, req
->size
, data
);
312 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
313 // don't implement all the MIB's. hopefully the kernel
314 // doesn't actually DEPEND upon their values
315 // MIB are just hardware stats keepers
316 uint32_t ®
= *(uint32_t *) data
;
319 } else if (daddr
> 0x3FC)
320 panic("Something is messed up!\n");
323 case sizeof(uint32_t):
325 uint32_t ®
= *(uint32_t *)data
;
330 //these are supposed to be cleared on a read
331 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
348 devIntrClear(ISR_ALL
);
403 //see the spec sheet for how RFCR and RFDR work
404 //basically, you write to RFCR to tell the machine what you want to do next
405 //then you act upon RFDR, and the device will be prepared b/c
406 //of what you wrote to RFCR
412 switch (regs
.rfcr
& RFCR_RFADDR
) {
414 reg
= rom
.perfectMatch
[1];
416 reg
+= rom
.perfectMatch
[0];
419 reg
= rom
.perfectMatch
[3] << 8;
420 reg
+= rom
.perfectMatch
[2];
423 reg
= rom
.perfectMatch
[5] << 8;
424 reg
+= rom
.perfectMatch
[4];
427 panic("reading from RFDR for something for other than PMATCH!\n");
428 //didn't implement other RFDR functionality b/c driver didn't use
438 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
482 panic("reading unimplemented register: addr = %#x", daddr
);
485 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n",
491 panic("accessing register with invalid size: addr=%#x, size=%d",
499 NSGigE::write(MemReqPtr
&req
, const uint8_t *data
)
503 Addr daddr
= req
->paddr
& 0xfff;
504 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x va=%#x size=%d\n",
505 daddr
, req
->paddr
, req
->vaddr
, req
->size
);
507 if (daddr
> LAST
&& daddr
<= RESERVED
) {
508 panic("Accessing reserved register");
509 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
510 WriteConfig(daddr
& 0xff, req
->size
, *(uint32_t *)data
);
512 } else if (daddr
> 0x3FC)
513 panic("Something is messed up!\n");
515 if (req
->size
== sizeof(uint32_t)) {
516 uint32_t reg
= *(uint32_t *)data
;
517 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
522 if ((reg
& (CR_TXE
| CR_TXD
)) == (CR_TXE
| CR_TXD
)) {
524 } else if (reg
& CR_TXE
) {
525 //the kernel is enabling the transmit machine
526 if (txState
== txIdle
)
528 } else if (reg
& CR_TXD
) {
532 if ((reg
& (CR_RXE
| CR_RXD
)) == (CR_RXE
| CR_RXD
)) {
534 } else if (reg
& CR_RXE
) {
535 if (rxState
== rxIdle
) {
538 } else if (reg
& CR_RXD
) {
549 devIntrPost(ISR_SWI
);
560 if (reg
& CFG_LNKSTS
|| reg
& CFG_SPDSTS
|| reg
& CFG_DUPSTS
561 || reg
& CFG_RESERVED
|| reg
& CFG_T64ADDR
562 || reg
& CFG_PCI64_DET
)
563 panic("writing to read-only or reserved CFG bits!\n");
565 regs
.config
|= reg
& ~(CFG_LNKSTS
| CFG_SPDSTS
| CFG_DUPSTS
| CFG_RESERVED
|
566 CFG_T64ADDR
| CFG_PCI64_DET
);
568 // all these #if 0's are because i don't THINK the kernel needs to have these implemented
569 // if there is a problem relating to one of these, you may need to add functionality in
571 if (reg
& CFG_TBI_EN
) ;
572 if (reg
& CFG_MODE_1000
) ;
575 if (reg
& CFG_AUTO_1000
)
576 panic("CFG_AUTO_1000 not implemented!\n");
579 if (reg
& CFG_PINT_DUPSTS
|| reg
& CFG_PINT_LNKSTS
|| reg
& CFG_PINT_SPDSTS
) ;
580 if (reg
& CFG_TMRTEST
) ;
581 if (reg
& CFG_MRM_DIS
) ;
582 if (reg
& CFG_MWI_DIS
) ;
584 if (reg
& CFG_T64ADDR
)
585 panic("CFG_T64ADDR is read only register!\n");
587 if (reg
& CFG_PCI64_DET
)
588 panic("CFG_PCI64_DET is read only register!\n");
590 if (reg
& CFG_DATA64_EN
) ;
591 if (reg
& CFG_M64ADDR
) ;
592 if (reg
& CFG_PHY_RST
) ;
593 if (reg
& CFG_PHY_DIS
) ;
596 if (reg
& CFG_EXTSTS_EN
)
599 extstsEnable
= false;
602 if (reg
& CFG_REQALG
) ;
606 if (reg
& CFG_PESEL
) ;
607 if (reg
& CFG_BROM_DIS
) ;
608 if (reg
& CFG_EXT_125
) ;
615 /* since phy is completely faked, MEAR_MD* don't matter
616 and since the driver never uses MEAR_EE*, they don't matter */
618 if (reg
& MEAR_EEDI
) ;
619 if (reg
& MEAR_EEDO
) ; //this one is read only
620 if (reg
& MEAR_EECLK
) ;
621 if (reg
& MEAR_EESEL
) ;
622 if (reg
& MEAR_MDIO
) ;
623 if (reg
& MEAR_MDDIR
) ;
624 if (reg
& MEAR_MDC
) ;
629 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
630 /* these control BISTs for various parts of chip - we don't care or do
631 just fake that the BIST is done */
632 if (reg
& PTSCR_RBIST_EN
)
633 regs
.ptscr
|= PTSCR_RBIST_DONE
;
634 if (reg
& PTSCR_EEBIST_EN
)
635 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
636 if (reg
& PTSCR_EELOAD_EN
)
637 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
640 case ISR
: /* writing to the ISR has no effect */
641 panic("ISR is a read only register!\n");
654 /* not going to implement real interrupt holdoff */
658 regs
.txdp
= (reg
& 0xFFFFFFFC);
659 assert(txState
== txIdle
);
670 if (reg
& TXCFG_CSI
) ;
671 if (reg
& TXCFG_HBI
) ;
672 if (reg
& TXCFG_MLB
) ;
673 if (reg
& TXCFG_ATP
) ;
674 if (reg
& TXCFG_ECRETRY
) ; /* this could easily be implemented, but
675 considering the network is just a fake
676 pipe, wouldn't make sense to do this */
678 if (reg
& TXCFG_BRST_DIS
) ;
682 /* we handle our own DMA, ignore the kernel's exhortations */
683 if (reg
& TXCFG_MXDMA
) ;
689 /* these just control general purpose i/o pins, don't matter */
703 if (reg
& RXCFG_AEP
) ;
704 if (reg
& RXCFG_ARP
) ;
705 if (reg
& RXCFG_STRIPCRC
) ;
706 if (reg
& RXCFG_RX_RD
) ;
707 if (reg
& RXCFG_ALP
) ;
708 if (reg
& RXCFG_AIRL
) ;
711 /* we handle our own DMA, ignore what kernel says about it */
712 if (reg
& RXCFG_MXDMA
) ;
715 if (reg
& (RXCFG_DRTH
| RXCFG_DRTH0
)) ;
720 /* there is no priority queueing used in the linux 2.6 driver */
725 /* not going to implement wake on LAN */
730 /* not going to implement pause control */
737 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
739 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
741 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
743 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
745 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
747 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
749 if (reg
& RFCR_APAT
) ;
750 // panic("RFCR_APAT not implemented!\n");
752 if (reg
& RFCR_MHEN
|| reg
& RFCR_UHEN
)
753 panic("hash filtering not implemented!\n");
756 panic("RFCR_ULM not implemented!\n");
761 panic("the driver never writes to RFDR, something is wrong!\n");
764 panic("the driver never uses BRAR, something is wrong!\n");
767 panic("the driver never uses BRDR, something is wrong!\n");
770 panic("SRR is read only register!\n");
773 panic("the driver never uses MIBC, something is wrong!\n");
784 panic("the driver never uses VDR, something is wrong!\n");
788 /* not going to implement clockrun stuff */
794 if (reg
& TBICR_MR_LOOPBACK
)
795 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
797 if (reg
& TBICR_MR_AN_ENABLE
) {
798 regs
.tanlpar
= regs
.tanar
;
799 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
803 if (reg
& TBICR_MR_RESTART_AN
) ;
809 panic("TBISR is read only register!\n");
814 panic("this isn't used in driver, something wrong!\n");
817 panic("this isn't used in driver, something wrong!\n");
821 panic("this should only be written to by the fake phy!\n");
824 panic("TANER is read only register!\n");
831 panic("thought i covered all the register, what is this? addr=%#x",
835 panic("Invalid Request Size");
841 NSGigE::devIntrPost(uint32_t interrupts
)
845 if (interrupts
& ISR_RESERVE
)
846 panic("Cannot set a reserved interrupt");
848 if (interrupts
& ISR_TXRCMP
)
849 regs
.isr
|= ISR_TXRCMP
;
851 if (interrupts
& ISR_RXRCMP
)
852 regs
.isr
|= ISR_RXRCMP
;
854 //ISR_DPERR not implemented
855 //ISR_SSERR not implemented
856 //ISR_RMABT not implemented
857 //ISR_RXSOVR not implemented
858 //ISR_HIBINT not implemented
859 //ISR_PHY not implemented
860 //ISR_PME not implemented
862 if (interrupts
& ISR_SWI
)
865 //ISR_MIB not implemented
866 //ISR_TXURN not implemented
868 if (interrupts
& ISR_TXIDLE
)
869 regs
.isr
|= ISR_TXIDLE
;
871 if (interrupts
& ISR_TXERR
)
872 regs
.isr
|= ISR_TXERR
;
874 if (interrupts
& ISR_TXDESC
)
875 regs
.isr
|= ISR_TXDESC
;
877 if (interrupts
& ISR_TXOK
) {
878 regs
.isr
|= ISR_TXOK
;
882 if (interrupts
& ISR_RXORN
)
883 regs
.isr
|= ISR_RXORN
;
885 if (interrupts
& ISR_RXIDLE
)
886 regs
.isr
|= ISR_RXIDLE
;
888 //ISR_RXEARLY not implemented
890 if (interrupts
& ISR_RXERR
)
891 regs
.isr
|= ISR_RXERR
;
893 if (interrupts
& ISR_RXDESC
)
894 regs
.isr
|= ISR_RXDESC
;
896 if (interrupts
& ISR_RXOK
) {
898 regs
.isr
|= ISR_RXOK
;
901 if ((regs
.isr
& regs
.imr
)) {
908 DPRINTF(Ethernet
, "interrupt posted intr=%#x isr=%#x imr=%#x\n",
909 interrupts
, regs
.isr
, regs
.imr
);
913 NSGigE::devIntrClear(uint32_t interrupts
)
915 if (interrupts
& ISR_RESERVE
)
916 panic("Cannot clear a reserved interrupt");
918 if (interrupts
& ISR_TXRCMP
)
919 regs
.isr
&= ~ISR_TXRCMP
;
921 if (interrupts
& ISR_RXRCMP
)
922 regs
.isr
&= ~ISR_RXRCMP
;
924 //ISR_DPERR not implemented
925 //ISR_SSERR not implemented
926 //ISR_RMABT not implemented
927 //ISR_RXSOVR not implemented
928 //ISR_HIBINT not implemented
929 //ISR_PHY not implemented
930 //ISR_PME not implemented
932 if (interrupts
& ISR_SWI
)
933 regs
.isr
&= ~ISR_SWI
;
935 //ISR_MIB not implemented
936 //ISR_TXURN not implemented
938 if (interrupts
& ISR_TXIDLE
)
939 regs
.isr
&= ~ISR_TXIDLE
;
941 if (interrupts
& ISR_TXERR
)
942 regs
.isr
&= ~ISR_TXERR
;
944 if (interrupts
& ISR_TXDESC
)
945 regs
.isr
&= ~ISR_TXDESC
;
947 if (interrupts
& ISR_TXOK
)
948 regs
.isr
&= ~ISR_TXOK
;
950 if (interrupts
& ISR_RXORN
)
951 regs
.isr
&= ~ISR_RXORN
;
953 if (interrupts
& ISR_RXIDLE
)
954 regs
.isr
&= ~ISR_RXIDLE
;
956 //ISR_RXEARLY not implemented
958 if (interrupts
& ISR_RXERR
)
959 regs
.isr
&= ~ISR_RXERR
;
961 if (interrupts
& ISR_RXDESC
)
962 regs
.isr
&= ~ISR_RXDESC
;
964 if (interrupts
& ISR_RXOK
)
965 regs
.isr
&= ~ISR_RXOK
;
967 if (!(regs
.isr
& regs
.imr
))
970 DPRINTF(Ethernet
, "interrupt cleared intr=%x isr=%x imr=%x\n",
971 interrupts
, regs
.isr
, regs
.imr
);
975 NSGigE::devIntrChangeMask()
977 DPRINTF(Ethernet
, "interrupt mask changed\n");
979 if (regs
.isr
& regs
.imr
)
980 cpuIntrPost(curTick
);
986 NSGigE::cpuIntrPost(Tick when
)
988 if (when
> intrTick
&& intrTick
!= 0)
998 if (when
< curTick
) {
1001 intrEvent
= new IntrEvent(this, true);
1002 intrEvent
->schedule(intrTick
);
1007 NSGigE::cpuInterrupt()
1009 // Don't send an interrupt if there's already one
1013 // Don't send an interrupt if it's supposed to be delayed
1014 if (intrTick
> curTick
)
1017 // Whether or not there's a pending interrupt, we don't care about
1023 cpuPendingIntr
= true;
1024 /** @todo rework the intctrl to be tsunami ok */
1025 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
1026 tsunami
->cchip
->postDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
1030 NSGigE::cpuIntrClear()
1032 if (cpuPendingIntr
) {
1033 cpuPendingIntr
= false;
1034 /** @todo rework the intctrl to be tsunami ok */
1035 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
1036 tsunami
->cchip
->clearDRIR(configData
->config
.hdr
.pci0
.interruptLine
);
1041 NSGigE::cpuIntrPending() const
1042 { return cpuPendingIntr
; }
1048 DPRINTF(Ethernet
, "transmit reset\n");
1052 txFifoAvail
= MAX_TX_FIFO_SIZE
;
1055 assert(txDescCnt
== 0);
1057 regs
.command
&= ~CR_TXE
;
1059 assert(txDmaState
== dmaIdle
);
1065 DPRINTF(Ethernet
, "receive reset\n");
1068 assert(rxPktBytes
== 0);
1072 assert(rxDescCnt
== 0);
1073 assert(rxDmaState
== dmaIdle
);
1075 regs
.command
&= ~CR_RXE
;
1079 void NSGigE::regsReset()
1081 memset(®s
, 0, sizeof(regs
));
1082 regs
.config
= 0x80000000;
1084 regs
.isr
= 0x00608000;
1094 NSGigE::rxDmaReadCopy()
1096 assert(rxDmaState
== dmaReading
);
1098 memcpy(rxDmaData
, physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaLen
);
1099 rxDmaState
= dmaIdle
;
1101 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1102 rxDmaAddr
, rxDmaLen
);
1103 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1107 NSGigE::doRxDmaRead()
1109 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1110 rxDmaState
= dmaReading
;
1112 if (dmaInterface
&& !rxDmaFree
) {
1113 if (dmaInterface
->busy())
1114 rxDmaState
= dmaReadWaiting
;
1116 dmaInterface
->doDMA(Read
, rxDmaAddr
, rxDmaLen
, curTick
,
1121 if (dmaReadDelay
== 0 && dmaReadFactor
== 0) {
1126 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1127 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1128 rxDmaReadEvent
.schedule(start
);
1133 NSGigE::rxDmaReadDone()
1135 assert(rxDmaState
== dmaReading
);
1138 // If the transmit state machine has a pending DMA, let it go first
1139 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1146 NSGigE::rxDmaWriteCopy()
1148 assert(rxDmaState
== dmaWriting
);
1150 memcpy(physmem
->dma_addr(rxDmaAddr
, rxDmaLen
), rxDmaData
, rxDmaLen
);
1151 rxDmaState
= dmaIdle
;
1153 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1154 rxDmaAddr
, rxDmaLen
);
1155 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1159 NSGigE::doRxDmaWrite()
1161 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1162 rxDmaState
= dmaWriting
;
1164 if (dmaInterface
&& !rxDmaFree
) {
1165 if (dmaInterface
->busy())
1166 rxDmaState
= dmaWriteWaiting
;
1168 dmaInterface
->doDMA(WriteInvalidate
, rxDmaAddr
, rxDmaLen
, curTick
,
1173 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0) {
1178 Tick factor
= ((rxDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1179 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1180 rxDmaWriteEvent
.schedule(start
);
1185 NSGigE::rxDmaWriteDone()
1187 assert(rxDmaState
== dmaWriting
);
1190 // If the transmit state machine has a pending DMA, let it go first
1191 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1200 DPRINTF(Ethernet
, "receive kick state=%s (rxBuf.size=%d)\n",
1201 NsRxStateStrings
[rxState
], rxFifo
.size());
1203 if (rxKickTick
> curTick
) {
1204 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1210 switch(rxDmaState
) {
1211 case dmaReadWaiting
:
1215 case dmaWriteWaiting
:
1223 // see state machine from spec for details
1224 // the way this works is, if you finish work on one state and can go directly to
1225 // another, you do that through jumping to the label "next". however, if you have
1226 // intermediate work, like DMA so that you can't go to the next state yet, you go to
1227 // exit and exit the loop. however, when the DMA is done it will trigger an
1228 // event and come back to this loop.
1231 if (!regs
.command
& CR_RXE
) {
1232 DPRINTF(Ethernet
, "Receive Disabled! Nothing to do.\n");
1237 rxState
= rxDescRefr
;
1239 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1240 rxDmaData
= &rxDescCache
+ offsetof(ns_desc
, link
);
1241 rxDmaLen
= sizeof(rxDescCache
.link
);
1242 rxDmaFree
= dmaDescFree
;
1247 rxState
= rxDescRead
;
1249 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1250 rxDmaData
= &rxDescCache
;
1251 rxDmaLen
= sizeof(ns_desc
);
1252 rxDmaFree
= dmaDescFree
;
1260 if (rxDmaState
!= dmaIdle
)
1263 rxState
= rxAdvance
;
1267 if (rxDmaState
!= dmaIdle
)
1271 "rxDescCache:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1272 ,rxDescCache
.link
, rxDescCache
.bufptr
, rxDescCache
.cmdsts
,
1273 rxDescCache
.extsts
);
1275 if (rxDescCache
.cmdsts
& CMDSTS_OWN
) {
1278 rxState
= rxFifoBlock
;
1279 rxFragPtr
= rxDescCache
.bufptr
;
1280 rxDescCnt
= rxDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1287 * @todo in reality, we should be able to start processing
1288 * the packet as it arrives, and not have to wait for the
1289 * full packet ot be in the receive fifo.
1294 // If we don't have a packet, grab a new one from the fifo.
1295 rxPacket
= rxFifo
.front();
1296 rxPktBytes
= rxPacket
->length
;
1297 rxPacketBufPtr
= rxPacket
->data
;
1299 // sanity check - i think the driver behaves like this
1300 assert(rxDescCnt
>= rxPktBytes
);
1302 // Must clear the value before popping to decrement the
1304 rxFifo
.front() = NULL
;
1309 // dont' need the && rxDescCnt > 0 if driver sanity check above holds
1310 if (rxPktBytes
> 0) {
1311 rxState
= rxFragWrite
;
1312 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity check holds
1313 rxXferLen
= rxPktBytes
;
1315 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1316 rxDmaData
= rxPacketBufPtr
;
1317 rxDmaLen
= rxXferLen
;
1318 rxDmaFree
= dmaDataFree
;
1324 rxState
= rxDescWrite
;
1326 //if (rxPktBytes == 0) { /* packet is done */
1327 assert(rxPktBytes
== 0);
1329 rxDescCache
.cmdsts
|= CMDSTS_OWN
;
1330 rxDescCache
.cmdsts
&= ~CMDSTS_MORE
;
1331 rxDescCache
.cmdsts
|= CMDSTS_OK
;
1332 rxDescCache
.cmdsts
&= 0xffff0000;
1333 rxDescCache
.cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1336 /* all the driver uses these are for its own stats keeping
1337 which we don't care about, aren't necessary for functionality
1338 and doing this would just slow us down. if they end up using
1339 this in a later version for functional purposes, just undef
1341 if (rxFilterEnable
) {
1342 rxDescCache
.cmdsts
&= ~CMDSTS_DEST_MASK
;
1343 if (rxFifo
.front()->IsUnicast())
1344 rxDescCache
.cmdsts
|= CMDSTS_DEST_SELF
;
1345 if (rxFifo
.front()->IsMulticast())
1346 rxDescCache
.cmdsts
|= CMDSTS_DEST_MULTI
;
1347 if (rxFifo
.front()->IsBroadcast())
1348 rxDescCache
.cmdsts
|= CMDSTS_DEST_MASK
;
1352 if (rxPacket
->isIpPkt() && extstsEnable
) { rxDescCache
.extsts
|= EXTSTS_IPPKT
;
1353 if (!ipChecksum(rxPacket
, false))
1354 rxDescCache
.extsts
|= EXTSTS_IPERR
;
1356 if (rxPacket
->isTcpPkt()) {
1357 rxDescCache
.extsts
|= EXTSTS_TCPPKT
;
1358 if (!tcpChecksum(rxPacket
, false))
1359 rxDescCache
.extsts
|= EXTSTS_TCPERR
;
1360 } else if (rxPacket
->isUdpPkt()) {
1361 rxDescCache
.extsts
|= EXTSTS_UDPPKT
;
1362 if (!udpChecksum(rxPacket
, false))
1363 rxDescCache
.extsts
|= EXTSTS_UDPERR
;
1367 rxFifoCnt
-= rxPacket
->length
;
1370 /* the driver seems to always receive into desc buffers
1371 of size 1514, so you never have a pkt that is split
1372 into multiple descriptors on the receive side, so
1373 i don't implement that case, hence the assert above.
1376 DPRINTF(Ethernet
, "rxDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1377 rxDescCache
.cmdsts
, rxDescCache
.extsts
);
1379 rxDmaAddr
= (regs
.rxdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1380 rxDmaData
= &(rxDescCache
.cmdsts
);
1381 rxDmaLen
= sizeof(rxDescCache
.cmdsts
) + sizeof(rxDescCache
.extsts
);
1382 rxDmaFree
= dmaDescFree
;
1390 if (rxDmaState
!= dmaIdle
)
1393 rxPacketBufPtr
+= rxXferLen
;
1394 rxFragPtr
+= rxXferLen
;
1395 rxPktBytes
-= rxXferLen
;
1397 rxState
= rxFifoBlock
;
1401 if (rxDmaState
!= dmaIdle
)
1404 assert(rxDescCache
.cmdsts
& CMDSTS_OWN
);
1406 assert(rxPacket
== 0);
1407 devIntrPost(ISR_RXOK
);
1409 if (rxDescCache
.cmdsts
& CMDSTS_INTR
)
1410 devIntrPost(ISR_RXDESC
);
1416 rxState
= rxAdvance
;
1420 if (rxDescCache
.link
== 0) {
1424 rxState
= rxDescRead
;
1425 regs
.rxdp
= rxDescCache
.link
;
1428 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1429 rxDmaData
= &rxDescCache
;
1430 rxDmaLen
= sizeof(ns_desc
);
1431 rxDmaFree
= dmaDescFree
;
1439 panic("Invalid rxState!");
1443 DPRINTF(Ethernet
, "entering next rx state = %s\n",
1444 NsRxStateStrings
[rxState
]);
1446 if (rxState
== rxIdle
) {
1447 regs
.command
&= ~CR_RXE
;
1448 devIntrPost(ISR_RXIDLE
);
1456 * @todo do we want to schedule a future kick?
1458 DPRINTF(Ethernet
, "rx state machine exited state=%s\n",
1459 NsRxStateStrings
[rxState
]);
1465 if (txFifo
.empty()) {
1466 DPRINTF(Ethernet
, "nothing to transmit\n");
1470 if (interface
->sendPacket(txFifo
.front())) {
1471 DPRINTF(Ethernet
, "transmit packet\n");
1472 DDUMP(Ethernet
, txFifo
.front()->data
, txFifo
.front()->length
);
1473 txBytes
+= txFifo
.front()->length
;
1476 txFifoCnt
-= (txFifo
.front()->length
- txPktXmitted
);
1478 txFifo
.front() = NULL
;
1481 /* normally do a writeback of the descriptor here, and ONLY after that is
1482 done, send this interrupt. but since our stuff never actually fails,
1483 just do this interrupt here, otherwise the code has to stray from this
1484 nice format. besides, it's functionally the same.
1486 devIntrPost(ISR_TXOK
);
1489 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1490 DPRINTF(Ethernet
, "reschedule transmit\n");
1491 txEvent
.schedule(curTick
+ 1000);
1496 NSGigE::txDmaReadCopy()
1498 assert(txDmaState
== dmaReading
);
1500 memcpy(txDmaData
, physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaLen
);
1501 txDmaState
= dmaIdle
;
1503 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1504 txDmaAddr
, txDmaLen
);
1505 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1509 NSGigE::doTxDmaRead()
1511 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1512 txDmaState
= dmaReading
;
1514 if (dmaInterface
&& !txDmaFree
) {
1515 if (dmaInterface
->busy())
1516 txDmaState
= dmaReadWaiting
;
1518 dmaInterface
->doDMA(Read
, txDmaAddr
, txDmaLen
, curTick
,
1523 if (dmaReadDelay
== 0 && dmaReadFactor
== 0.0) {
1528 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaReadFactor
;
1529 Tick start
= curTick
+ dmaReadDelay
+ factor
;
1530 txDmaReadEvent
.schedule(start
);
1535 NSGigE::txDmaReadDone()
1537 assert(txDmaState
== dmaReading
);
1540 // If the receive state machine has a pending DMA, let it go first
1541 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1548 NSGigE::txDmaWriteCopy()
1550 assert(txDmaState
== dmaWriting
);
1552 memcpy(physmem
->dma_addr(txDmaAddr
, txDmaLen
), txDmaData
, txDmaLen
);
1553 txDmaState
= dmaIdle
;
1555 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1556 txDmaAddr
, txDmaLen
);
1557 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1561 NSGigE::doTxDmaWrite()
1563 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1564 txDmaState
= dmaWriting
;
1566 if (dmaInterface
&& !txDmaFree
) {
1567 if (dmaInterface
->busy())
1568 txDmaState
= dmaWriteWaiting
;
1570 dmaInterface
->doDMA(WriteInvalidate
, txDmaAddr
, txDmaLen
, curTick
,
1575 if (dmaWriteDelay
== 0 && dmaWriteFactor
== 0.0) {
1580 Tick factor
= ((txDmaLen
+ ULL(63)) >> ULL(6)) * dmaWriteFactor
;
1581 Tick start
= curTick
+ dmaWriteDelay
+ factor
;
1582 txDmaWriteEvent
.schedule(start
);
1587 NSGigE::txDmaWriteDone()
1589 assert(txDmaState
== dmaWriting
);
1592 // If the receive state machine has a pending DMA, let it go first
1593 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1602 DPRINTF(Ethernet
, "transmit kick state=%s\n", NsTxStateStrings
[txState
]);
1604 if (rxKickTick
> curTick
) {
1605 DPRINTF(Ethernet
, "receive kick exiting, can't run till %d\n",
1612 switch(txDmaState
) {
1613 case dmaReadWaiting
:
1617 case dmaWriteWaiting
:
1627 if (!regs
.command
& CR_TXE
) {
1628 DPRINTF(Ethernet
, "Transmit disabled. Nothing to do.\n");
1633 txState
= txDescRefr
;
1635 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1636 txDmaData
= &txDescCache
+ offsetof(ns_desc
, link
);
1637 txDmaLen
= sizeof(txDescCache
.link
);
1638 txDmaFree
= dmaDescFree
;
1644 txState
= txDescRead
;
1646 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1647 txDmaData
= &txDescCache
;
1648 txDmaLen
= sizeof(ns_desc
);
1649 txDmaFree
= dmaDescFree
;
1657 if (txDmaState
!= dmaIdle
)
1660 txState
= txAdvance
;
1664 if (txDmaState
!= dmaIdle
)
1668 "txDescCache data:\n\tlink=%#x\n\tbufptr=%#x\n\tcmdsts=%#x\n\textsts=%#x\n"
1669 ,txDescCache
.link
, txDescCache
.bufptr
, txDescCache
.cmdsts
,
1670 txDescCache
.extsts
);
1672 if (txDescCache
.cmdsts
& CMDSTS_OWN
) {
1673 txState
= txFifoBlock
;
1674 txFragPtr
= txDescCache
.bufptr
;
1675 txDescCnt
= txDescCache
.cmdsts
& CMDSTS_LEN_MASK
;
1683 DPRINTF(Ethernet
, "starting the tx of a new packet\n");
1684 txPacket
= new EtherPacket
;
1685 txPacket
->data
= new uint8_t[16384];
1686 txPacketBufPtr
= txPacket
->data
;
1689 if (txDescCnt
== 0) {
1690 DPRINTF(Ethernet
, "the txDescCnt == 0, done with descriptor\n");
1691 if (txDescCache
.cmdsts
& CMDSTS_MORE
) {
1692 DPRINTF(Ethernet
, "there are more descriptors to come\n");
1693 txState
= txDescWrite
;
1695 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1697 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1698 txDmaData
= &(txDescCache
.cmdsts
);
1699 txDmaLen
= sizeof(txDescCache
.cmdsts
);
1700 txDmaFree
= dmaDescFree
;
1705 } else { /* this packet is totally done */
1706 DPRINTF(Ethernet
, "This packet is done, let's wrap it up\n");
1707 /* deal with the the packet that just finished */
1708 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
1709 if (txDescCache
.extsts
& EXTSTS_UDPPKT
) {
1710 udpChecksum(txPacket
, true);
1711 } else if (txDescCache
.extsts
& EXTSTS_TCPPKT
) {
1712 tcpChecksum(txPacket
, true);
1713 } else if (txDescCache
.extsts
& EXTSTS_IPPKT
) {
1714 ipChecksum(txPacket
, true);
1718 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
1719 /* this is just because the receive can't handle a packet bigger
1720 want to make sure */
1721 assert(txPacket
->length
<= 1514);
1722 txFifo
.push_back(txPacket
);
1725 /* this following section is not to spec, but functionally shouldn't
1726 be any different. normally, the chip will wait til the transmit has
1727 occurred before writing back the descriptor because it has to wait
1728 to see that it was successfully transmitted to decide whether to set
1729 CMDSTS_OK or not. however, in the simulator since it is always
1730 successfully transmitted, and writing it exactly to spec would
1731 complicate the code, we just do it here
1733 txDescCache
.cmdsts
&= ~CMDSTS_OWN
;
1734 txDescCache
.cmdsts
|= CMDSTS_OK
;
1737 "txDesc writeback:\n\tcmdsts=%#x\n\textsts=%#x\n",
1738 txDescCache
.cmdsts
, txDescCache
.extsts
);
1740 txDmaAddr
= (regs
.txdp
+ offsetof(ns_desc
, cmdsts
)) & 0x3fffffff;
1741 txDmaData
= &(txDescCache
.cmdsts
);
1742 txDmaLen
= sizeof(txDescCache
.cmdsts
) + sizeof(txDescCache
.extsts
);
1743 txDmaFree
= dmaDescFree
;
1755 txState
= txAdvance
;
1758 DPRINTF(Ethernet
, "this descriptor isn't done yet\n");
1759 /* the fill thresh is in units of 32 bytes, shift right by 8 to get the
1760 value, shift left by 5 to get the real number of bytes */
1761 if (txFifoAvail
< ((regs
.txcfg
& TXCFG_FLTH_MASK
) >> 3)) {
1762 DPRINTF(Ethernet
, "txFifoAvail=%d, regs.txcfg & TXCFG_FLTH_MASK = %#x\n",
1763 txFifoAvail
, regs
.txcfg
& TXCFG_FLTH_MASK
);
1767 txState
= txFragRead
;
1769 /* The number of bytes transferred is either whatever is left
1770 in the descriptor (txDescCnt), or if there is not enough
1771 room in the fifo, just whatever room is left in the fifo
1773 txXferLen
= min
<uint32_t>(txDescCnt
, txFifoAvail
);
1775 txDmaAddr
= txFragPtr
& 0x3fffffff;
1776 txDmaData
= txPacketBufPtr
;
1777 txDmaLen
= txXferLen
;
1778 txDmaFree
= dmaDataFree
;
1786 if (txDmaState
!= dmaIdle
)
1789 txPacketBufPtr
+= txXferLen
;
1790 txFragPtr
+= txXferLen
;
1791 txFifoCnt
+= txXferLen
;
1792 txDescCnt
-= txXferLen
;
1794 txState
= txFifoBlock
;
1798 if (txDmaState
!= dmaIdle
)
1801 if (txFifoCnt
>= ((regs
.txcfg
& TXCFG_DRTH_MASK
) << 5)) {
1802 if (txFifo
.empty()) {
1803 uint32_t xmitted
= (uint32_t) (txPacketBufPtr
- txPacket
->data
- txPktXmitted
);
1804 txFifoCnt
-= xmitted
;
1805 txPktXmitted
+= xmitted
;
1811 if (txDescCache
.cmdsts
& CMDSTS_INTR
) {
1812 devIntrPost(ISR_TXDESC
);
1815 txState
= txAdvance
;
1819 if (txDescCache
.link
== 0) {
1822 txState
= txDescRead
;
1823 regs
.txdp
= txDescCache
.link
;
1826 txDmaAddr
= txDescCache
.link
& 0x3fffffff;
1827 txDmaData
= &txDescCache
;
1828 txDmaLen
= sizeof(ns_desc
);
1829 txDmaFree
= dmaDescFree
;
1837 panic("invalid state");
1840 DPRINTF(Ethernet
, "entering next tx state=%s\n",
1841 NsTxStateStrings
[txState
]);
1843 if (txState
== txIdle
) {
1844 regs
.command
&= ~CR_TXE
;
1845 devIntrPost(ISR_TXIDLE
);
1853 * @todo do we want to schedule a future kick?
1855 DPRINTF(Ethernet
, "tx state machine exited state=%s\n",
1856 NsTxStateStrings
[txState
]);
1860 NSGigE::transferDone()
1865 DPRINTF(Ethernet
, "schedule transmit\n");
1867 if (txEvent
.scheduled())
1868 txEvent
.reschedule(curTick
+ 1);
1870 txEvent
.schedule(curTick
+ 1);
1874 NSGigE::rxFilter(PacketPtr packet
)
1879 if (packet
->IsUnicast()) {
1882 // If we're accepting all unicast addresses
1886 // If we make a perfect match
1888 && (memcmp(rom
.perfectMatch
, packet
->data
, sizeof(rom
.perfectMatch
)) == 0))
1891 eth_header
*eth
= (eth_header
*) packet
->data
;
1892 if ((acceptArp
) && (eth
->type
== 0x806))
1895 } else if (packet
->IsBroadcast()) {
1898 // if we're accepting broadcasts
1899 if (acceptBroadcast
)
1902 } else if (packet
->IsMulticast()) {
1905 // if we're accepting all multicasts
1906 if (acceptMulticast
)
1912 // oh well, punt on this one
1916 DPRINTF(Ethernet
, "rxFilter drop\n");
1917 DDUMP(EthernetData
, packet
->data
, packet
->length
);
1924 NSGigE::recvPacket(PacketPtr packet
)
1926 rxBytes
+= packet
->length
;
1929 if (rxState
== rxIdle
) {
1930 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
1931 interface
->recvDone();
1935 if (rxFilterEnable
&& rxFilter(packet
)) {
1936 DPRINTF(Ethernet
, "packet filtered...dropped\n");
1937 interface
->recvDone();
1941 if (rxFifoCnt
+ packet
->length
>= MAX_RX_FIFO_SIZE
) {
1943 "packet will not fit in receive buffer...packet dropped\n");
1944 devIntrPost(ISR_RXORN
);
1948 rxFifo
.push_back(packet
);
1949 rxFifoCnt
+= packet
->length
;
1950 interface
->recvDone();
1957 * does a udp checksum. if gen is true, then it generates it and puts it in the right place
1958 * else, it just checks what it calculates against the value in the header in packet
1961 NSGigE::udpChecksum(PacketPtr packet
, bool gen
)
1963 ip_header
*ip
= packet
->getIpHdr();
1964 udp_header
*hdr
= packet
->getUdpHdr(ip
);
1966 pseudo_header
*pseudo
= new pseudo_header
;
1968 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1969 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1970 pseudo
->protocol
= ip
->protocol
;
1971 pseudo
->len
= hdr
->len
;
1973 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
1974 (uint32_t) hdr
->len
);
1978 hdr
->chksum
= cksum
;
1987 NSGigE::tcpChecksum(PacketPtr packet
, bool gen
)
1989 ip_header
*ip
= packet
->getIpHdr();
1990 tcp_header
*hdr
= packet
->getTcpHdr(ip
);
1992 pseudo_header
*pseudo
= new pseudo_header
;
1994 pseudo
->src_ip_addr
= ip
->src_ip_addr
;
1995 pseudo
->dest_ip_addr
= ip
->dest_ip_addr
;
1996 pseudo
->protocol
= ip
->protocol
;
1997 pseudo
->len
= ip
->dgram_len
- (ip
->vers_len
& 0xf);
1999 uint16_t cksum
= checksumCalc((uint16_t *) pseudo
, (uint16_t *) hdr
,
2000 (uint32_t) pseudo
->len
);
2004 hdr
->chksum
= cksum
;
2013 NSGigE::ipChecksum(PacketPtr packet
, bool gen
)
2015 ip_header
*hdr
= packet
->getIpHdr();
2017 uint16_t cksum
= checksumCalc(NULL
, (uint16_t *) hdr
, (hdr
->vers_len
& 0xf));
2020 hdr
->hdr_chksum
= cksum
;
2029 NSGigE::checksumCalc(uint16_t *pseudo
, uint16_t *buf
, uint32_t len
)
2033 uint16_t last_pad
= 0;
2035 last_pad
= buf
[len
/2] & 0xff;
2041 sum
= pseudo
[0] + pseudo
[1] + pseudo
[2] +
2042 pseudo
[3] + pseudo
[4] + pseudo
[5];
2045 for (int i
=0; i
< (len
/2); ++i
) {
2050 sum
= (sum
>> 16) + (sum
& 0xffff);
2055 //=====================================================================
2059 NSGigE::serialize(ostream
&os
)
2061 // Serialize the PciDev base class
2062 PciDev::serialize(os
);
2065 * Finalize any DMA events now.
2067 if (rxDmaReadEvent
.scheduled())
2069 if (rxDmaWriteEvent
.scheduled())
2071 if (txDmaReadEvent
.scheduled())
2073 if (txDmaWriteEvent
.scheduled())
2077 * Serialize the device registers
2079 SERIALIZE_SCALAR(regs
.command
);
2080 SERIALIZE_SCALAR(regs
.config
);
2081 SERIALIZE_SCALAR(regs
.mear
);
2082 SERIALIZE_SCALAR(regs
.ptscr
);
2083 SERIALIZE_SCALAR(regs
.isr
);
2084 SERIALIZE_SCALAR(regs
.imr
);
2085 SERIALIZE_SCALAR(regs
.ier
);
2086 SERIALIZE_SCALAR(regs
.ihr
);
2087 SERIALIZE_SCALAR(regs
.txdp
);
2088 SERIALIZE_SCALAR(regs
.txdp_hi
);
2089 SERIALIZE_SCALAR(regs
.txcfg
);
2090 SERIALIZE_SCALAR(regs
.gpior
);
2091 SERIALIZE_SCALAR(regs
.rxdp
);
2092 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2093 SERIALIZE_SCALAR(regs
.rxcfg
);
2094 SERIALIZE_SCALAR(regs
.pqcr
);
2095 SERIALIZE_SCALAR(regs
.wcsr
);
2096 SERIALIZE_SCALAR(regs
.pcr
);
2097 SERIALIZE_SCALAR(regs
.rfcr
);
2098 SERIALIZE_SCALAR(regs
.rfdr
);
2099 SERIALIZE_SCALAR(regs
.srr
);
2100 SERIALIZE_SCALAR(regs
.mibc
);
2101 SERIALIZE_SCALAR(regs
.vrcr
);
2102 SERIALIZE_SCALAR(regs
.vtcr
);
2103 SERIALIZE_SCALAR(regs
.vdr
);
2104 SERIALIZE_SCALAR(regs
.ccsr
);
2105 SERIALIZE_SCALAR(regs
.tbicr
);
2106 SERIALIZE_SCALAR(regs
.tbisr
);
2107 SERIALIZE_SCALAR(regs
.tanar
);
2108 SERIALIZE_SCALAR(regs
.tanlpar
);
2109 SERIALIZE_SCALAR(regs
.taner
);
2110 SERIALIZE_SCALAR(regs
.tesr
);
2112 SERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2114 SERIALIZE_SCALAR(io_enable
);
2117 * Serialize the data Fifos
2119 int txNumPkts
= txFifo
.size();
2120 SERIALIZE_SCALAR(txNumPkts
);
2122 pktiter_t end
= txFifo
.end();
2123 for (pktiter_t p
= txFifo
.begin(); p
!= end
; ++p
) {
2124 nameOut(os
, csprintf("%s.txFifo%d", name(), i
++));
2125 (*p
)->serialize(os
);
2128 int rxNumPkts
= rxFifo
.size();
2129 SERIALIZE_SCALAR(rxNumPkts
);
2132 for (pktiter_t p
= rxFifo
.begin(); p
!= end
; ++p
) {
2133 nameOut(os
, csprintf("%s.rxFifo%d", name(), i
++));
2134 (*p
)->serialize(os
);
2138 * Serialize the various helper variables
2140 bool txPacketExists
= txPacket
;
2141 SERIALIZE_SCALAR(txPacketExists
);
2142 if (txPacketExists
) {
2143 nameOut(os
, csprintf("%s.txPacket", name()));
2144 txPacket
->serialize(os
);
2145 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
2146 SERIALIZE_SCALAR(txPktBufPtr
);
2149 bool rxPacketExists
= rxPacket
;
2150 SERIALIZE_SCALAR(rxPacketExists
);
2151 if (rxPacketExists
) {
2152 nameOut(os
, csprintf("%s.rxPacket", name()));
2153 rxPacket
->serialize(os
);
2154 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
2155 SERIALIZE_SCALAR(rxPktBufPtr
);
2158 SERIALIZE_SCALAR(txXferLen
);
2159 SERIALIZE_SCALAR(rxXferLen
);
2160 SERIALIZE_SCALAR(txPktXmitted
);
2163 * Serialize DescCaches
2165 SERIALIZE_SCALAR(txDescCache
.link
);
2166 SERIALIZE_SCALAR(txDescCache
.bufptr
);
2167 SERIALIZE_SCALAR(txDescCache
.cmdsts
);
2168 SERIALIZE_SCALAR(txDescCache
.extsts
);
2169 SERIALIZE_SCALAR(rxDescCache
.link
);
2170 SERIALIZE_SCALAR(rxDescCache
.bufptr
);
2171 SERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2172 SERIALIZE_SCALAR(rxDescCache
.extsts
);
2175 * Serialize tx state machine
2177 int txState
= this->txState
;
2178 SERIALIZE_SCALAR(txState
);
2179 SERIALIZE_SCALAR(CTDD
);
2180 SERIALIZE_SCALAR(txFifoCnt
);
2181 SERIALIZE_SCALAR(txFifoAvail
);
2182 SERIALIZE_SCALAR(txHalt
);
2183 SERIALIZE_SCALAR(txFragPtr
);
2184 SERIALIZE_SCALAR(txDescCnt
);
2185 int txDmaState
= this->txDmaState
;
2186 SERIALIZE_SCALAR(txDmaState
);
2189 * Serialize rx state machine
2191 int rxState
= this->rxState
;
2192 SERIALIZE_SCALAR(rxState
);
2193 SERIALIZE_SCALAR(CRDD
);
2194 SERIALIZE_SCALAR(rxPktBytes
);
2195 SERIALIZE_SCALAR(rxFifoCnt
);
2196 SERIALIZE_SCALAR(rxHalt
);
2197 SERIALIZE_SCALAR(rxDescCnt
);
2198 int rxDmaState
= this->rxDmaState
;
2199 SERIALIZE_SCALAR(rxDmaState
);
2201 SERIALIZE_SCALAR(extstsEnable
);
2204 * If there's a pending transmit, store the time so we can
2205 * reschedule it later
2207 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2208 SERIALIZE_SCALAR(transmitTick
);
2211 * receive address filter settings
2213 SERIALIZE_SCALAR(rxFilterEnable
);
2214 SERIALIZE_SCALAR(acceptBroadcast
);
2215 SERIALIZE_SCALAR(acceptMulticast
);
2216 SERIALIZE_SCALAR(acceptUnicast
);
2217 SERIALIZE_SCALAR(acceptPerfect
);
2218 SERIALIZE_SCALAR(acceptArp
);
2221 * Keep track of pending interrupt status.
2223 SERIALIZE_SCALAR(intrTick
);
2224 SERIALIZE_SCALAR(cpuPendingIntr
);
2225 Tick intrEventTick
= 0;
2227 intrEventTick
= intrEvent
->when();
2228 SERIALIZE_SCALAR(intrEventTick
);
2233 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2235 // Unserialize the PciDev base class
2236 PciDev::unserialize(cp
, section
);
2238 UNSERIALIZE_SCALAR(regs
.command
);
2239 UNSERIALIZE_SCALAR(regs
.config
);
2240 UNSERIALIZE_SCALAR(regs
.mear
);
2241 UNSERIALIZE_SCALAR(regs
.ptscr
);
2242 UNSERIALIZE_SCALAR(regs
.isr
);
2243 UNSERIALIZE_SCALAR(regs
.imr
);
2244 UNSERIALIZE_SCALAR(regs
.ier
);
2245 UNSERIALIZE_SCALAR(regs
.ihr
);
2246 UNSERIALIZE_SCALAR(regs
.txdp
);
2247 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2248 UNSERIALIZE_SCALAR(regs
.txcfg
);
2249 UNSERIALIZE_SCALAR(regs
.gpior
);
2250 UNSERIALIZE_SCALAR(regs
.rxdp
);
2251 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2252 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2253 UNSERIALIZE_SCALAR(regs
.pqcr
);
2254 UNSERIALIZE_SCALAR(regs
.wcsr
);
2255 UNSERIALIZE_SCALAR(regs
.pcr
);
2256 UNSERIALIZE_SCALAR(regs
.rfcr
);
2257 UNSERIALIZE_SCALAR(regs
.rfdr
);
2258 UNSERIALIZE_SCALAR(regs
.srr
);
2259 UNSERIALIZE_SCALAR(regs
.mibc
);
2260 UNSERIALIZE_SCALAR(regs
.vrcr
);
2261 UNSERIALIZE_SCALAR(regs
.vtcr
);
2262 UNSERIALIZE_SCALAR(regs
.vdr
);
2263 UNSERIALIZE_SCALAR(regs
.ccsr
);
2264 UNSERIALIZE_SCALAR(regs
.tbicr
);
2265 UNSERIALIZE_SCALAR(regs
.tbisr
);
2266 UNSERIALIZE_SCALAR(regs
.tanar
);
2267 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2268 UNSERIALIZE_SCALAR(regs
.taner
);
2269 UNSERIALIZE_SCALAR(regs
.tesr
);
2271 UNSERIALIZE_ARRAY(rom
.perfectMatch
, EADDR_LEN
);
2273 UNSERIALIZE_SCALAR(io_enable
);
2276 * unserialize the data fifos
2279 UNSERIALIZE_SCALAR(txNumPkts
);
2281 for (i
= 0; i
< txNumPkts
; ++i
) {
2282 PacketPtr p
= new EtherPacket
;
2283 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2284 txFifo
.push_back(p
);
2288 UNSERIALIZE_SCALAR(rxNumPkts
);
2289 for (i
= 0; i
< rxNumPkts
; ++i
) {
2290 PacketPtr p
= new EtherPacket
;
2291 p
->unserialize(cp
, csprintf("%s.rxFifo%d", section
, i
));
2292 rxFifo
.push_back(p
);
2296 * unserialize the various helper variables
2298 bool txPacketExists
;
2299 UNSERIALIZE_SCALAR(txPacketExists
);
2300 if (txPacketExists
) {
2301 txPacket
= new EtherPacket
;
2302 txPacket
->unserialize(cp
, csprintf("%s.txPacket", section
));
2303 uint32_t txPktBufPtr
;
2304 UNSERIALIZE_SCALAR(txPktBufPtr
);
2305 txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
2309 bool rxPacketExists
;
2310 UNSERIALIZE_SCALAR(rxPacketExists
);
2312 if (rxPacketExists
) {
2313 rxPacket
= new EtherPacket
;
2314 rxPacket
->unserialize(cp
, csprintf("%s.rxPacket", section
));
2315 uint32_t rxPktBufPtr
;
2316 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2317 rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
2321 UNSERIALIZE_SCALAR(txXferLen
);
2322 UNSERIALIZE_SCALAR(rxXferLen
);
2323 UNSERIALIZE_SCALAR(txPktXmitted
);
2326 * Unserialize DescCaches
2328 UNSERIALIZE_SCALAR(txDescCache
.link
);
2329 UNSERIALIZE_SCALAR(txDescCache
.bufptr
);
2330 UNSERIALIZE_SCALAR(txDescCache
.cmdsts
);
2331 UNSERIALIZE_SCALAR(txDescCache
.extsts
);
2332 UNSERIALIZE_SCALAR(rxDescCache
.link
);
2333 UNSERIALIZE_SCALAR(rxDescCache
.bufptr
);
2334 UNSERIALIZE_SCALAR(rxDescCache
.cmdsts
);
2335 UNSERIALIZE_SCALAR(rxDescCache
.extsts
);
2338 * unserialize tx state machine
2341 UNSERIALIZE_SCALAR(txState
);
2342 this->txState
= (TxState
) txState
;
2343 UNSERIALIZE_SCALAR(CTDD
);
2344 UNSERIALIZE_SCALAR(txFifoCnt
);
2345 UNSERIALIZE_SCALAR(txFifoAvail
);
2346 UNSERIALIZE_SCALAR(txHalt
);
2347 UNSERIALIZE_SCALAR(txFragPtr
);
2348 UNSERIALIZE_SCALAR(txDescCnt
);
2350 UNSERIALIZE_SCALAR(txDmaState
);
2351 this->txDmaState
= (DmaState
) txDmaState
;
2354 * unserialize rx state machine
2357 UNSERIALIZE_SCALAR(rxState
);
2358 this->rxState
= (RxState
) rxState
;
2359 UNSERIALIZE_SCALAR(CRDD
);
2360 UNSERIALIZE_SCALAR(rxPktBytes
);
2361 UNSERIALIZE_SCALAR(rxFifoCnt
);
2362 UNSERIALIZE_SCALAR(rxHalt
);
2363 UNSERIALIZE_SCALAR(rxDescCnt
);
2365 UNSERIALIZE_SCALAR(rxDmaState
);
2366 this->rxDmaState
= (DmaState
) rxDmaState
;
2368 UNSERIALIZE_SCALAR(extstsEnable
);
2371 * If there's a pending transmit, reschedule it now
2374 UNSERIALIZE_SCALAR(transmitTick
);
2376 txEvent
.schedule(curTick
+ transmitTick
);
2379 * unserialize receive address filter settings
2381 UNSERIALIZE_SCALAR(rxFilterEnable
);
2382 UNSERIALIZE_SCALAR(acceptBroadcast
);
2383 UNSERIALIZE_SCALAR(acceptMulticast
);
2384 UNSERIALIZE_SCALAR(acceptUnicast
);
2385 UNSERIALIZE_SCALAR(acceptPerfect
);
2386 UNSERIALIZE_SCALAR(acceptArp
);
2389 * Keep track of pending interrupt status.
2391 UNSERIALIZE_SCALAR(intrTick
);
2392 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2394 UNSERIALIZE_SCALAR(intrEventTick
);
2395 if (intrEventTick
) {
2396 intrEvent
= new IntrEvent(this, true);
2397 intrEvent
->schedule(intrEventTick
);
2401 * re-add addrRanges to bus bridges
2404 pioInterface
->addAddrRange(BARAddrs
[0], BARAddrs
[0] + BARSize
[0] - 1);
2405 pioInterface
->addAddrRange(BARAddrs
[1], BARAddrs
[1] + BARSize
[1] - 1);
2410 NSGigE::cacheAccess(MemReqPtr
&req
)
2412 DPRINTF(EthernetPIO
, "timing access to paddr=%#x (daddr=%#x)\n",
2413 req
->paddr
, req
->paddr
- addr
);
2414 return curTick
+ pioLatency
;
2416 //=====================================================================
2419 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2421 SimObjectParam
<EtherInt
*> peer
;
2422 SimObjectParam
<NSGigE
*> device
;
2424 END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt
)
2426 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2428 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
2429 INIT_PARAM(device
, "Ethernet device of this interface")
2431 END_INIT_SIM_OBJECT_PARAMS(NSGigEInt
)
2433 CREATE_SIM_OBJECT(NSGigEInt
)
2435 NSGigEInt
*dev_int
= new NSGigEInt(getInstanceName(), device
);
2437 EtherInt
*p
= (EtherInt
*)peer
;
2439 dev_int
->setPeer(p
);
2440 p
->setPeer(dev_int
);
2446 REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt
)
2449 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2451 Param
<Tick
> tx_delay
;
2452 Param
<Tick
> rx_delay
;
2453 SimObjectParam
<IntrControl
*> intr_ctrl
;
2454 Param
<Tick
> intr_delay
;
2455 SimObjectParam
<MemoryController
*> mmu
;
2456 SimObjectParam
<PhysicalMemory
*> physmem
;
2457 Param
<bool> rx_filter
;
2458 Param
<string
> hardware_address
;
2459 SimObjectParam
<Bus
*> header_bus
;
2460 SimObjectParam
<Bus
*> payload_bus
;
2461 SimObjectParam
<HierParams
*> hier
;
2462 Param
<Tick
> pio_latency
;
2463 Param
<bool> dma_desc_free
;
2464 Param
<bool> dma_data_free
;
2465 Param
<Tick
> dma_read_delay
;
2466 Param
<Tick
> dma_write_delay
;
2467 Param
<Tick
> dma_read_factor
;
2468 Param
<Tick
> dma_write_factor
;
2469 SimObjectParam
<PciConfigAll
*> configspace
;
2470 SimObjectParam
<PciConfigData
*> configdata
;
2471 SimObjectParam
<Tsunami
*> tsunami
;
2472 Param
<uint32_t> pci_bus
;
2473 Param
<uint32_t> pci_dev
;
2474 Param
<uint32_t> pci_func
;
2476 END_DECLARE_SIM_OBJECT_PARAMS(NSGigE
)
2478 BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2480 INIT_PARAM_DFLT(tx_delay
, "Transmit Delay", 1000),
2481 INIT_PARAM_DFLT(rx_delay
, "Receive Delay", 1000),
2482 INIT_PARAM(intr_ctrl
, "Interrupt Controller"),
2483 INIT_PARAM_DFLT(intr_delay
, "Interrupt Delay in microseconds", 0),
2484 INIT_PARAM(mmu
, "Memory Controller"),
2485 INIT_PARAM(physmem
, "Physical Memory"),
2486 INIT_PARAM_DFLT(rx_filter
, "Enable Receive Filter", true),
2487 INIT_PARAM_DFLT(hardware_address
, "Ethernet Hardware Address",
2488 "00:99:00:00:00:01"),
2489 INIT_PARAM_DFLT(header_bus
, "The IO Bus to attach to for headers", NULL
),
2490 INIT_PARAM_DFLT(payload_bus
, "The IO Bus to attach to for payload", NULL
),
2491 INIT_PARAM_DFLT(hier
, "Hierarchy global variables", &defaultHierParams
),
2492 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency", 1000),
2493 INIT_PARAM_DFLT(dma_desc_free
, "DMA of Descriptors is free", false),
2494 INIT_PARAM_DFLT(dma_data_free
, "DMA of Data is free", false),
2495 INIT_PARAM_DFLT(dma_read_delay
, "fixed delay for dma reads", 0),
2496 INIT_PARAM_DFLT(dma_write_delay
, "fixed delay for dma writes", 0),
2497 INIT_PARAM_DFLT(dma_read_factor
, "multiplier for dma reads", 0),
2498 INIT_PARAM_DFLT(dma_write_factor
, "multiplier for dma writes", 0),
2499 INIT_PARAM(configspace
, "PCI Configspace"),
2500 INIT_PARAM(configdata
, "PCI Config data"),
2501 INIT_PARAM(tsunami
, "Tsunami"),
2502 INIT_PARAM(pci_bus
, "PCI bus"),
2503 INIT_PARAM(pci_dev
, "PCI device number"),
2504 INIT_PARAM(pci_func
, "PCI function code")
2506 END_INIT_SIM_OBJECT_PARAMS(NSGigE
)
2509 CREATE_SIM_OBJECT(NSGigE
)
2512 sscanf(((string
)hardware_address
).c_str(), "%x:%x:%x:%x:%x:%x",
2513 &eaddr
[0], &eaddr
[1], &eaddr
[2], &eaddr
[3], &eaddr
[4], &eaddr
[5]);
2515 return new NSGigE(getInstanceName(), intr_ctrl
, intr_delay
,
2516 physmem
, tx_delay
, rx_delay
, mmu
, hier
, header_bus
,
2517 payload_bus
, pio_latency
, dma_desc_free
, dma_data_free
,
2518 dma_read_delay
, dma_write_delay
, dma_read_factor
,
2519 dma_write_factor
, configspace
, configdata
,
2520 tsunami
, pci_bus
, pci_dev
, pci_func
, rx_filter
, eaddr
);
2523 REGISTER_SIM_OBJECT("NSGigE", NSGigE
)