2 * Copyright (c) 2004-2005 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.
28 * Authors: Nathan Binkert
33 * Device module for modelling the National Semiconductor
34 * DP83820 ethernet controller. Does not support priority queueing
39 #include "base/inet.hh"
40 #include "cpu/thread_context.hh"
41 #include "dev/etherlink.hh"
42 #include "dev/ns_gige.hh"
43 #include "dev/pciconfigall.hh"
44 #include "mem/packet.hh"
45 #include "mem/packet_access.hh"
46 #include "params/NSGigE.hh"
47 #include "sim/debug.hh"
48 #include "sim/host.hh"
49 #include "sim/stats.hh"
50 #include "sim/system.hh"
52 const char *NsRxStateStrings
[] =
63 const char *NsTxStateStrings
[] =
74 const char *NsDmaState
[] =
85 using namespace TheISA
;
87 ///////////////////////////////////////////////////////////////////////
91 NSGigE::NSGigE(Params
*p
)
92 : EtherDevice(p
), ioEnable(false),
93 txFifo(p
->tx_fifo_size
), rxFifo(p
->rx_fifo_size
),
94 txPacket(0), rxPacket(0), txPacketBufPtr(NULL
), rxPacketBufPtr(NULL
),
95 txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
97 txState(txIdle
), txEnable(false), CTDD(false), txHalt(false),
98 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle
), rxState(rxIdle
),
99 rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
100 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle
), extstsEnable(false),
101 eepromState(eepromStart
), eepromClk(false), eepromBitsToRx(0),
102 eepromOpcode(0), eepromAddress(0), eepromData(0),
103 dmaReadDelay(p
->dma_read_delay
), dmaWriteDelay(p
->dma_write_delay
),
104 dmaReadFactor(p
->dma_read_factor
), dmaWriteFactor(p
->dma_write_factor
),
105 rxDmaData(NULL
), rxDmaAddr(0), rxDmaLen(0),
106 txDmaData(NULL
), txDmaAddr(0), txDmaLen(0),
107 rxDmaReadEvent(this), rxDmaWriteEvent(this),
108 txDmaReadEvent(this), txDmaWriteEvent(this),
109 dmaDescFree(p
->dma_desc_free
), dmaDataFree(p
->dma_data_free
),
110 txDelay(p
->tx_delay
), rxDelay(p
->rx_delay
),
111 rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
112 txEvent(this), rxFilterEnable(p
->rx_filter
),
113 acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
114 acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
115 intrDelay(p
->intr_delay
), intrTick(0), cpuPendingIntr(false),
116 intrEvent(0), interface(0)
120 interface
= new NSGigEInt(name() + ".int0", this);
123 memcpy(&rom
.perfectMatch
, p
->hardware_address
.bytes(), ETH_ADDR_LEN
);
125 memset(&rxDesc32
, 0, sizeof(rxDesc32
));
126 memset(&txDesc32
, 0, sizeof(txDesc32
));
127 memset(&rxDesc64
, 0, sizeof(rxDesc64
));
128 memset(&txDesc64
, 0, sizeof(txDesc64
));
138 .name(name() + ".txBytes")
139 .desc("Bytes Transmitted")
144 .name(name() + ".rxBytes")
145 .desc("Bytes Received")
150 .name(name() + ".txPackets")
151 .desc("Number of Packets Transmitted")
156 .name(name() + ".rxPackets")
157 .desc("Number of Packets Received")
162 .name(name() + ".txIpChecksums")
163 .desc("Number of tx IP Checksums done by device")
169 .name(name() + ".rxIpChecksums")
170 .desc("Number of rx IP Checksums done by device")
176 .name(name() + ".txTcpChecksums")
177 .desc("Number of tx TCP Checksums done by device")
183 .name(name() + ".rxTcpChecksums")
184 .desc("Number of rx TCP Checksums done by device")
190 .name(name() + ".txUdpChecksums")
191 .desc("Number of tx UDP Checksums done by device")
197 .name(name() + ".rxUdpChecksums")
198 .desc("Number of rx UDP Checksums done by device")
204 .name(name() + ".descDMAReads")
205 .desc("Number of descriptors the device read w/ DMA")
210 .name(name() + ".descDMAWrites")
211 .desc("Number of descriptors the device wrote w/ DMA")
216 .name(name() + ".descDmaReadBytes")
217 .desc("number of descriptor bytes read w/ DMA")
222 .name(name() + ".descDmaWriteBytes")
223 .desc("number of descriptor bytes write w/ DMA")
228 .name(name() + ".txBandwidth")
229 .desc("Transmit Bandwidth (bits/s)")
235 .name(name() + ".rxBandwidth")
236 .desc("Receive Bandwidth (bits/s)")
242 .name(name() + ".totBandwidth")
243 .desc("Total Bandwidth (bits/s)")
249 .name(name() + ".totPackets")
250 .desc("Total Packets")
256 .name(name() + ".totBytes")
263 .name(name() + ".totPPS")
264 .desc("Total Tranmission Rate (packets/s)")
270 .name(name() + ".txPPS")
271 .desc("Packet Tranmission Rate (packets/s)")
277 .name(name() + ".rxPPS")
278 .desc("Packet Reception Rate (packets/s)")
284 .name(name() + ".postedSwi")
285 .desc("number of software interrupts posted to CPU")
290 .name(name() + ".totalSwi")
291 .desc("total number of Swi written to ISR")
296 .name(name() + ".coalescedSwi")
297 .desc("average number of Swi's coalesced into each post")
302 .name(name() + ".postedRxIdle")
303 .desc("number of rxIdle interrupts posted to CPU")
308 .name(name() + ".totalRxIdle")
309 .desc("total number of RxIdle written to ISR")
314 .name(name() + ".coalescedRxIdle")
315 .desc("average number of RxIdle's coalesced into each post")
320 .name(name() + ".postedRxOk")
321 .desc("number of RxOk interrupts posted to CPU")
326 .name(name() + ".totalRxOk")
327 .desc("total number of RxOk written to ISR")
332 .name(name() + ".coalescedRxOk")
333 .desc("average number of RxOk's coalesced into each post")
338 .name(name() + ".postedRxDesc")
339 .desc("number of RxDesc interrupts posted to CPU")
344 .name(name() + ".totalRxDesc")
345 .desc("total number of RxDesc written to ISR")
350 .name(name() + ".coalescedRxDesc")
351 .desc("average number of RxDesc's coalesced into each post")
356 .name(name() + ".postedTxOk")
357 .desc("number of TxOk interrupts posted to CPU")
362 .name(name() + ".totalTxOk")
363 .desc("total number of TxOk written to ISR")
368 .name(name() + ".coalescedTxOk")
369 .desc("average number of TxOk's coalesced into each post")
374 .name(name() + ".postedTxIdle")
375 .desc("number of TxIdle interrupts posted to CPU")
380 .name(name() + ".totalTxIdle")
381 .desc("total number of TxIdle written to ISR")
386 .name(name() + ".coalescedTxIdle")
387 .desc("average number of TxIdle's coalesced into each post")
392 .name(name() + ".postedTxDesc")
393 .desc("number of TxDesc interrupts posted to CPU")
398 .name(name() + ".totalTxDesc")
399 .desc("total number of TxDesc written to ISR")
404 .name(name() + ".coalescedTxDesc")
405 .desc("average number of TxDesc's coalesced into each post")
410 .name(name() + ".postedRxOrn")
411 .desc("number of RxOrn posted to CPU")
416 .name(name() + ".totalRxOrn")
417 .desc("total number of RxOrn written to ISR")
422 .name(name() + ".coalescedRxOrn")
423 .desc("average number of RxOrn's coalesced into each post")
428 .name(name() + ".coalescedTotal")
429 .desc("average number of interrupts coalesced into each post")
434 .name(name() + ".postedInterrupts")
435 .desc("number of posts to CPU")
440 .name(name() + ".droppedPackets")
441 .desc("number of packets dropped")
445 coalescedSwi
= totalSwi
/ postedInterrupts
;
446 coalescedRxIdle
= totalRxIdle
/ postedInterrupts
;
447 coalescedRxOk
= totalRxOk
/ postedInterrupts
;
448 coalescedRxDesc
= totalRxDesc
/ postedInterrupts
;
449 coalescedTxOk
= totalTxOk
/ postedInterrupts
;
450 coalescedTxIdle
= totalTxIdle
/ postedInterrupts
;
451 coalescedTxDesc
= totalTxDesc
/ postedInterrupts
;
452 coalescedRxOrn
= totalRxOrn
/ postedInterrupts
;
454 coalescedTotal
= (totalSwi
+ totalRxIdle
+ totalRxOk
+ totalRxDesc
+
455 totalTxOk
+ totalTxIdle
+ totalTxDesc
+
456 totalRxOrn
) / postedInterrupts
;
458 txBandwidth
= txBytes
* Stats::constant(8) / simSeconds
;
459 rxBandwidth
= rxBytes
* Stats::constant(8) / simSeconds
;
460 totBandwidth
= txBandwidth
+ rxBandwidth
;
461 totBytes
= txBytes
+ rxBytes
;
462 totPackets
= txPackets
+ rxPackets
;
464 txPacketRate
= txPackets
/ simSeconds
;
465 rxPacketRate
= rxPackets
/ simSeconds
;
470 * This is to write to the PCI general configuration registers
473 NSGigE::writeConfig(PacketPtr pkt
)
475 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
476 if (offset
< PCI_DEVICE_SPECIFIC
)
477 PciDev::writeConfig(pkt
);
479 panic("Device specific PCI config space not implemented!\n");
482 // seems to work fine without all these PCI settings, but i
483 // put in the IO to double check, an assertion will fail if we
484 // need to properly implement it
486 if (config
.data
[offset
] & PCI_CMD_IOSE
)
497 NSGigE::getEthPort(const std::string
&if_name
, int idx
)
499 if (if_name
== "interface") {
500 if (interface
->getPeer())
501 panic("interface already connected to\n");
508 * This reads the device registers, which are detailed in the NS83820
512 NSGigE::read(PacketPtr pkt
)
518 //The mask is to give you only the offset into the device register file
519 Addr daddr
= pkt
->getAddr() & 0xfff;
520 DPRINTF(EthernetPIO
, "read da=%#x pa=%#x size=%d\n",
521 daddr
, pkt
->getAddr(), pkt
->getSize());
524 // there are some reserved registers, you can see ns_gige_reg.h and
525 // the spec sheet for details
526 if (daddr
> LAST
&& daddr
<= RESERVED
) {
527 panic("Accessing reserved register");
528 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
529 return readConfig(pkt
);
530 } else if (daddr
>= MIB_START
&& daddr
<= MIB_END
) {
531 // don't implement all the MIB's. hopefully the kernel
532 // doesn't actually DEPEND upon their values
533 // MIB are just hardware stats keepers
534 pkt
->set
<uint32_t>(0);
535 pkt
->makeAtomicResponse();
537 } else if (daddr
> 0x3FC)
538 panic("Something is messed up!\n");
540 assert(pkt
->getSize() == sizeof(uint32_t));
541 uint32_t ®
= *pkt
->getPtr
<uint32_t>();
547 //these are supposed to be cleared on a read
548 reg
&= ~(CR_RXD
| CR_TXD
| CR_TXR
| CR_RXR
);
565 devIntrClear(ISR_ALL
);
620 // see the spec sheet for how RFCR and RFDR work
621 // basically, you write to RFCR to tell the machine
622 // what you want to do next, then you act upon RFDR,
623 // and the device will be prepared b/c of what you
630 rfaddr
= (uint16_t)(regs
.rfcr
& RFCR_RFADDR
);
632 // Read from perfect match ROM octets
634 reg
= rom
.perfectMatch
[1];
636 reg
+= rom
.perfectMatch
[0];
639 reg
= rom
.perfectMatch
[3] << 8;
640 reg
+= rom
.perfectMatch
[2];
643 reg
= rom
.perfectMatch
[5] << 8;
644 reg
+= rom
.perfectMatch
[4];
647 // Read filter hash table
648 if (rfaddr
>= FHASH_ADDR
&&
649 rfaddr
< FHASH_ADDR
+ FHASH_SIZE
) {
651 // Only word-aligned reads supported
653 panic("unaligned read from filter hash table!");
655 reg
= rom
.filterHash
[rfaddr
- FHASH_ADDR
+ 1] << 8;
656 reg
+= rom
.filterHash
[rfaddr
- FHASH_ADDR
];
660 panic("reading RFDR for something other than pattern"
661 " matching or hashing! %#x\n", rfaddr
);
671 reg
&= ~(MIBC_MIBS
| MIBC_ACLR
);
716 if (params()->rx_thread
)
717 reg
|= M5REG_RX_THREAD
;
718 if (params()->tx_thread
)
719 reg
|= M5REG_TX_THREAD
;
725 panic("reading unimplemented register: addr=%#x", daddr
);
728 DPRINTF(EthernetPIO
, "read from %#x: data=%d data=%#x\n",
731 pkt
->makeAtomicResponse();
736 NSGigE::write(PacketPtr pkt
)
740 Addr daddr
= pkt
->getAddr() & 0xfff;
741 DPRINTF(EthernetPIO
, "write da=%#x pa=%#x size=%d\n",
742 daddr
, pkt
->getAddr(), pkt
->getSize());
744 if (daddr
> LAST
&& daddr
<= RESERVED
) {
745 panic("Accessing reserved register");
746 } else if (daddr
> RESERVED
&& daddr
<= 0x3FC) {
747 return writeConfig(pkt
);
748 } else if (daddr
> 0x3FC)
749 panic("Something is messed up!\n");
751 if (pkt
->getSize() == sizeof(uint32_t)) {
752 uint32_t reg
= pkt
->get
<uint32_t>();
755 DPRINTF(EthernetPIO
, "write data=%d data=%#x\n", reg
, reg
);
762 } else if (reg
& CR_TXE
) {
765 // the kernel is enabling the transmit machine
766 if (txState
== txIdle
)
772 } else if (reg
& CR_RXE
) {
775 if (rxState
== rxIdle
)
786 devIntrPost(ISR_SWI
);
797 if (reg
& CFGR_LNKSTS
||
800 reg
& CFGR_RESERVED
||
801 reg
& CFGR_T64ADDR
||
802 reg
& CFGR_PCI64_DET
)
804 // First clear all writable bits
805 regs
.config
&= CFGR_LNKSTS
| CFGR_SPDSTS
| CFGR_DUPSTS
|
806 CFGR_RESERVED
| CFGR_T64ADDR
|
808 // Now set the appropriate writable bits
809 regs
.config
|= reg
& ~(CFGR_LNKSTS
| CFGR_SPDSTS
| CFGR_DUPSTS
|
810 CFGR_RESERVED
| CFGR_T64ADDR
|
813 // all these #if 0's are because i don't THINK the kernel needs to
814 // have these implemented. if there is a problem relating to one of
815 // these, you may need to add functionality in.
816 if (reg
& CFGR_TBI_EN
) ;
817 if (reg
& CFGR_MODE_1000
) ;
819 if (reg
& CFGR_AUTO_1000
)
820 panic("CFGR_AUTO_1000 not implemented!\n");
822 if (reg
& CFGR_PINT_DUPSTS
||
823 reg
& CFGR_PINT_LNKSTS
||
824 reg
& CFGR_PINT_SPDSTS
)
827 if (reg
& CFGR_TMRTEST
) ;
828 if (reg
& CFGR_MRM_DIS
) ;
829 if (reg
& CFGR_MWI_DIS
) ;
831 if (reg
& CFGR_T64ADDR
) ;
832 // panic("CFGR_T64ADDR is read only register!\n");
834 if (reg
& CFGR_PCI64_DET
)
835 panic("CFGR_PCI64_DET is read only register!\n");
837 if (reg
& CFGR_DATA64_EN
) ;
838 if (reg
& CFGR_M64ADDR
) ;
839 if (reg
& CFGR_PHY_RST
) ;
840 if (reg
& CFGR_PHY_DIS
) ;
842 if (reg
& CFGR_EXTSTS_EN
)
845 extstsEnable
= false;
847 if (reg
& CFGR_REQALG
) ;
849 if (reg
& CFGR_POW
) ;
850 if (reg
& CFGR_EXD
) ;
851 if (reg
& CFGR_PESEL
) ;
852 if (reg
& CFGR_BROM_DIS
) ;
853 if (reg
& CFGR_EXT_125
) ;
854 if (reg
& CFGR_BEM
) ;
858 // Clear writable bits
859 regs
.mear
&= MEAR_EEDO
;
860 // Set appropriate writable bits
861 regs
.mear
|= reg
& ~MEAR_EEDO
;
863 // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
864 // even though it could get it through RFDR
865 if (reg
& MEAR_EESEL
) {
866 // Rising edge of clock
867 if (reg
& MEAR_EECLK
&& !eepromClk
)
871 eepromState
= eepromStart
;
872 regs
.mear
&= ~MEAR_EEDI
;
875 eepromClk
= reg
& MEAR_EECLK
;
877 // since phy is completely faked, MEAR_MD* don't matter
878 if (reg
& MEAR_MDIO
) ;
879 if (reg
& MEAR_MDDIR
) ;
880 if (reg
& MEAR_MDC
) ;
884 regs
.ptscr
= reg
& ~(PTSCR_RBIST_RDONLY
);
885 // these control BISTs for various parts of chip - we
886 // don't care or do just fake that the BIST is done
887 if (reg
& PTSCR_RBIST_EN
)
888 regs
.ptscr
|= PTSCR_RBIST_DONE
;
889 if (reg
& PTSCR_EEBIST_EN
)
890 regs
.ptscr
&= ~PTSCR_EEBIST_EN
;
891 if (reg
& PTSCR_EELOAD_EN
)
892 regs
.ptscr
&= ~PTSCR_EELOAD_EN
;
895 case ISR
: /* writing to the ISR has no effect */
896 panic("ISR is a read only register!\n");
909 /* not going to implement real interrupt holdoff */
913 regs
.txdp
= (reg
& 0xFFFFFFFC);
914 assert(txState
== txIdle
);
925 if (reg
& TX_CFG_CSI
) ;
926 if (reg
& TX_CFG_HBI
) ;
927 if (reg
& TX_CFG_MLB
) ;
928 if (reg
& TX_CFG_ATP
) ;
929 if (reg
& TX_CFG_ECRETRY
) {
931 * this could easily be implemented, but considering
932 * the network is just a fake pipe, wouldn't make
937 if (reg
& TX_CFG_BRST_DIS
) ;
941 /* we handle our own DMA, ignore the kernel's exhortations */
942 if (reg
& TX_CFG_MXDMA
) ;
945 // also, we currently don't care about fill/drain
946 // thresholds though this may change in the future with
947 // more realistic networks or a driver which changes it
948 // according to feedback
953 // Only write writable bits
954 regs
.gpior
&= GPIOR_UNUSED
| GPIOR_GP5_IN
| GPIOR_GP4_IN
955 | GPIOR_GP3_IN
| GPIOR_GP2_IN
| GPIOR_GP1_IN
;
956 regs
.gpior
|= reg
& ~(GPIOR_UNUSED
| GPIOR_GP5_IN
| GPIOR_GP4_IN
957 | GPIOR_GP3_IN
| GPIOR_GP2_IN
| GPIOR_GP1_IN
);
958 /* these just control general purpose i/o pins, don't matter */
973 if (reg
& RX_CFG_AEP
) ;
974 if (reg
& RX_CFG_ARP
) ;
975 if (reg
& RX_CFG_STRIPCRC
) ;
976 if (reg
& RX_CFG_RX_RD
) ;
977 if (reg
& RX_CFG_ALP
) ;
978 if (reg
& RX_CFG_AIRL
) ;
980 /* we handle our own DMA, ignore what kernel says about it */
981 if (reg
& RX_CFG_MXDMA
) ;
983 //also, we currently don't care about fill/drain thresholds
984 //though this may change in the future with more realistic
985 //networks or a driver which changes it according to feedback
986 if (reg
& (RX_CFG_DRTH
| RX_CFG_DRTH0
)) ;
991 /* there is no priority queueing used in the linux 2.6 driver */
996 /* not going to implement wake on LAN */
1001 /* not going to implement pause control */
1008 rxFilterEnable
= (reg
& RFCR_RFEN
) ? true : false;
1009 acceptBroadcast
= (reg
& RFCR_AAB
) ? true : false;
1010 acceptMulticast
= (reg
& RFCR_AAM
) ? true : false;
1011 acceptUnicast
= (reg
& RFCR_AAU
) ? true : false;
1012 acceptPerfect
= (reg
& RFCR_APM
) ? true : false;
1013 acceptArp
= (reg
& RFCR_AARP
) ? true : false;
1014 multicastHashEnable
= (reg
& RFCR_MHEN
) ? true : false;
1017 if (reg
& RFCR_APAT
)
1018 panic("RFCR_APAT not implemented!\n");
1020 if (reg
& RFCR_UHEN
)
1021 panic("Unicast hash filtering not used by drivers!\n");
1024 panic("RFCR_ULM not implemented!\n");
1029 rfaddr
= (uint16_t)(regs
.rfcr
& RFCR_RFADDR
);
1032 rom
.perfectMatch
[0] = (uint8_t)reg
;
1033 rom
.perfectMatch
[1] = (uint8_t)(reg
>> 8);
1036 rom
.perfectMatch
[2] = (uint8_t)reg
;
1037 rom
.perfectMatch
[3] = (uint8_t)(reg
>> 8);
1040 rom
.perfectMatch
[4] = (uint8_t)reg
;
1041 rom
.perfectMatch
[5] = (uint8_t)(reg
>> 8);
1045 if (rfaddr
>= FHASH_ADDR
&&
1046 rfaddr
< FHASH_ADDR
+ FHASH_SIZE
) {
1048 // Only word-aligned writes supported
1050 panic("unaligned write to filter hash table!");
1052 rom
.filterHash
[rfaddr
- FHASH_ADDR
] = (uint8_t)reg
;
1053 rom
.filterHash
[rfaddr
- FHASH_ADDR
+ 1]
1054 = (uint8_t)(reg
>> 8);
1057 panic("writing RFDR for something other than pattern matching\
1058 or hashing! %#x\n", rfaddr
);
1066 panic("the driver never uses BRDR, something is wrong!\n");
1069 panic("SRR is read only register!\n");
1072 panic("the driver never uses MIBC, something is wrong!\n");
1083 panic("the driver never uses VDR, something is wrong!\n");
1086 /* not going to implement clockrun stuff */
1092 if (reg
& TBICR_MR_LOOPBACK
)
1093 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
1095 if (reg
& TBICR_MR_AN_ENABLE
) {
1096 regs
.tanlpar
= regs
.tanar
;
1097 regs
.tbisr
|= (TBISR_MR_AN_COMPLETE
| TBISR_MR_LINK_STATUS
);
1101 if (reg
& TBICR_MR_RESTART_AN
) ;
1107 panic("TBISR is read only register!\n");
1110 // Only write the writable bits
1111 regs
.tanar
&= TANAR_RF1
| TANAR_RF2
| TANAR_UNUSED
;
1112 regs
.tanar
|= reg
& ~(TANAR_RF1
| TANAR_RF2
| TANAR_UNUSED
);
1114 // Pause capability unimplemented
1116 if (reg
& TANAR_PS2
) ;
1117 if (reg
& TANAR_PS1
) ;
1123 panic("this should only be written to by the fake phy!\n");
1126 panic("TANER is read only register!\n");
1133 panic("invalid register access daddr=%#x", daddr
);
1136 panic("Invalid Request Size");
1138 pkt
->makeAtomicResponse();
1143 NSGigE::devIntrPost(uint32_t interrupts
)
1145 if (interrupts
& ISR_RESERVE
)
1146 panic("Cannot set a reserved interrupt");
1148 if (interrupts
& ISR_NOIMPL
)
1149 warn("interrupt not implemented %#x\n", interrupts
);
1151 interrupts
&= ISR_IMPL
;
1152 regs
.isr
|= interrupts
;
1154 if (interrupts
& regs
.imr
) {
1155 if (interrupts
& ISR_SWI
) {
1158 if (interrupts
& ISR_RXIDLE
) {
1161 if (interrupts
& ISR_RXOK
) {
1164 if (interrupts
& ISR_RXDESC
) {
1167 if (interrupts
& ISR_TXOK
) {
1170 if (interrupts
& ISR_TXIDLE
) {
1173 if (interrupts
& ISR_TXDESC
) {
1176 if (interrupts
& ISR_RXORN
) {
1181 DPRINTF(EthernetIntr
,
1182 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
1183 interrupts
, regs
.isr
, regs
.imr
);
1185 if ((regs
.isr
& regs
.imr
)) {
1186 Tick when
= curTick
;
1187 if ((regs
.isr
& regs
.imr
& ISR_NODELAY
) == 0)
1193 /* writing this interrupt counting stats inside this means that this function
1194 is now limited to being used to clear all interrupts upon the kernel
1195 reading isr and servicing. just telling you in case you were thinking
1199 NSGigE::devIntrClear(uint32_t interrupts
)
1201 if (interrupts
& ISR_RESERVE
)
1202 panic("Cannot clear a reserved interrupt");
1204 if (regs
.isr
& regs
.imr
& ISR_SWI
) {
1207 if (regs
.isr
& regs
.imr
& ISR_RXIDLE
) {
1210 if (regs
.isr
& regs
.imr
& ISR_RXOK
) {
1213 if (regs
.isr
& regs
.imr
& ISR_RXDESC
) {
1216 if (regs
.isr
& regs
.imr
& ISR_TXOK
) {
1219 if (regs
.isr
& regs
.imr
& ISR_TXIDLE
) {
1222 if (regs
.isr
& regs
.imr
& ISR_TXDESC
) {
1225 if (regs
.isr
& regs
.imr
& ISR_RXORN
) {
1229 if (regs
.isr
& regs
.imr
& ISR_IMPL
)
1232 interrupts
&= ~ISR_NOIMPL
;
1233 regs
.isr
&= ~interrupts
;
1235 DPRINTF(EthernetIntr
,
1236 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
1237 interrupts
, regs
.isr
, regs
.imr
);
1239 if (!(regs
.isr
& regs
.imr
))
1244 NSGigE::devIntrChangeMask()
1246 DPRINTF(EthernetIntr
, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
1247 regs
.isr
, regs
.imr
, regs
.isr
& regs
.imr
);
1249 if (regs
.isr
& regs
.imr
)
1250 cpuIntrPost(curTick
);
1256 NSGigE::cpuIntrPost(Tick when
)
1258 // If the interrupt you want to post is later than an interrupt
1259 // already scheduled, just let it post in the coming one and don't
1260 // schedule another.
1261 // HOWEVER, must be sure that the scheduled intrTick is in the
1262 // future (this was formerly the source of a bug)
1264 * @todo this warning should be removed and the intrTick code should
1267 assert(when
>= curTick
);
1268 assert(intrTick
>= curTick
|| intrTick
== 0);
1269 if (when
> intrTick
&& intrTick
!= 0) {
1270 DPRINTF(EthernetIntr
, "don't need to schedule event...intrTick=%d\n",
1276 if (intrTick
< curTick
) {
1281 DPRINTF(EthernetIntr
, "going to schedule an interrupt for intrTick=%d\n",
1285 intrEvent
->squash();
1286 intrEvent
= new IntrEvent(this, intrTick
, true);
1290 NSGigE::cpuInterrupt()
1292 assert(intrTick
== curTick
);
1294 // Whether or not there's a pending interrupt, we don't care about
1299 // Don't send an interrupt if there's already one
1300 if (cpuPendingIntr
) {
1301 DPRINTF(EthernetIntr
,
1302 "would send an interrupt now, but there's already pending\n");
1305 cpuPendingIntr
= true;
1307 DPRINTF(EthernetIntr
, "posting interrupt\n");
1313 NSGigE::cpuIntrClear()
1315 if (!cpuPendingIntr
)
1319 intrEvent
->squash();
1325 cpuPendingIntr
= false;
1327 DPRINTF(EthernetIntr
, "clearing interrupt\n");
1332 NSGigE::cpuIntrPending() const
1333 { return cpuPendingIntr
; }
1339 DPRINTF(Ethernet
, "transmit reset\n");
1344 assert(txDescCnt
== 0);
1347 assert(txDmaState
== dmaIdle
);
1353 DPRINTF(Ethernet
, "receive reset\n");
1356 assert(rxPktBytes
== 0);
1359 assert(rxDescCnt
== 0);
1360 assert(rxDmaState
== dmaIdle
);
1368 memset(®s
, 0, sizeof(regs
));
1369 regs
.config
= (CFGR_LNKSTS
| CFGR_TBI_EN
| CFGR_MODE_1000
);
1371 regs
.txcfg
= 0x120; // set drain threshold to 1024 bytes and
1372 // fill threshold to 32 bytes
1373 regs
.rxcfg
= 0x4; // set drain threshold to 16 bytes
1374 regs
.srr
= 0x0103; // set the silicon revision to rev B or 0x103
1375 regs
.mibc
= MIBC_FRZ
;
1376 regs
.vdr
= 0x81; // set the vlan tag type to 802.1q
1377 regs
.tesr
= 0xc000; // TBI capable of both full and half duplex
1378 regs
.brar
= 0xffffffff;
1380 extstsEnable
= false;
1381 acceptBroadcast
= false;
1382 acceptMulticast
= false;
1383 acceptUnicast
= false;
1384 acceptPerfect
= false;
1389 NSGigE::doRxDmaRead()
1391 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaReadWaiting
);
1392 rxDmaState
= dmaReading
;
1394 if (dmaPending() || getState() != Running
)
1395 rxDmaState
= dmaReadWaiting
;
1397 dmaRead(rxDmaAddr
, rxDmaLen
, &rxDmaReadEvent
, (uint8_t*)rxDmaData
);
1403 NSGigE::rxDmaReadDone()
1405 assert(rxDmaState
== dmaReading
);
1406 rxDmaState
= dmaIdle
;
1408 DPRINTF(EthernetDMA
, "rx dma read paddr=%#x len=%d\n",
1409 rxDmaAddr
, rxDmaLen
);
1410 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1412 // If the transmit state machine has a pending DMA, let it go first
1413 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1420 NSGigE::doRxDmaWrite()
1422 assert(rxDmaState
== dmaIdle
|| rxDmaState
== dmaWriteWaiting
);
1423 rxDmaState
= dmaWriting
;
1425 if (dmaPending() || getState() != Running
)
1426 rxDmaState
= dmaWriteWaiting
;
1428 dmaWrite(rxDmaAddr
, rxDmaLen
, &rxDmaWriteEvent
, (uint8_t*)rxDmaData
);
1433 NSGigE::rxDmaWriteDone()
1435 assert(rxDmaState
== dmaWriting
);
1436 rxDmaState
= dmaIdle
;
1438 DPRINTF(EthernetDMA
, "rx dma write paddr=%#x len=%d\n",
1439 rxDmaAddr
, rxDmaLen
);
1440 DDUMP(EthernetDMA
, rxDmaData
, rxDmaLen
);
1442 // If the transmit state machine has a pending DMA, let it go first
1443 if (txDmaState
== dmaReadWaiting
|| txDmaState
== dmaWriteWaiting
)
1452 bool is64bit
= (bool)(regs
.config
& CFGR_M64ADDR
);
1455 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1456 NsRxStateStrings
[rxState
], rxFifo
.size(), is64bit
? 64 : 32);
1459 uint32_t &cmdsts
= is64bit
? rxDesc64
.cmdsts
: rxDesc32
.cmdsts
;
1460 uint32_t &extsts
= is64bit
? rxDesc64
.extsts
: rxDesc32
.extsts
;
1464 if (rxKickTick
> curTick
) {
1465 DPRINTF(EthernetSM
, "receive kick exiting, can't run till %d\n",
1471 // Go to the next state machine clock tick.
1472 rxKickTick
= curTick
+ ticks(1);
1475 switch(rxDmaState
) {
1476 case dmaReadWaiting
:
1480 case dmaWriteWaiting
:
1488 link
= is64bit
? (Addr
)rxDesc64
.link
: (Addr
)rxDesc32
.link
;
1489 bufptr
= is64bit
? (Addr
)rxDesc64
.bufptr
: (Addr
)rxDesc32
.bufptr
;
1491 // see state machine from spec for details
1492 // the way this works is, if you finish work on one state and can
1493 // go directly to another, you do that through jumping to the
1494 // label "next". however, if you have intermediate work, like DMA
1495 // so that you can't go to the next state yet, you go to exit and
1496 // exit the loop. however, when the DMA is done it will trigger
1497 // an event and come back to this loop.
1501 DPRINTF(EthernetSM
, "Receive Disabled! Nothing to do.\n");
1506 rxState
= rxDescRefr
;
1508 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1510 is64bit
? (void *)&rxDesc64
.link
: (void *)&rxDesc32
.link
;
1511 rxDmaLen
= is64bit
? sizeof(rxDesc64
.link
) : sizeof(rxDesc32
.link
);
1512 rxDmaFree
= dmaDescFree
;
1515 descDmaRdBytes
+= rxDmaLen
;
1520 rxState
= rxDescRead
;
1522 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1523 rxDmaData
= is64bit
? (void *)&rxDesc64
: (void *)&rxDesc32
;
1524 rxDmaLen
= is64bit
? sizeof(rxDesc64
) : sizeof(rxDesc32
);
1525 rxDmaFree
= dmaDescFree
;
1528 descDmaRdBytes
+= rxDmaLen
;
1536 if (rxDmaState
!= dmaIdle
)
1539 rxState
= rxAdvance
;
1543 if (rxDmaState
!= dmaIdle
)
1546 DPRINTF(EthernetDesc
, "rxDesc: addr=%08x read descriptor\n",
1547 regs
.rxdp
& 0x3fffffff);
1548 DPRINTF(EthernetDesc
,
1549 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1550 link
, bufptr
, cmdsts
, extsts
);
1552 if (cmdsts
& CMDSTS_OWN
) {
1553 devIntrPost(ISR_RXIDLE
);
1557 rxState
= rxFifoBlock
;
1559 rxDescCnt
= cmdsts
& CMDSTS_LEN_MASK
;
1566 * @todo in reality, we should be able to start processing
1567 * the packet as it arrives, and not have to wait for the
1568 * full packet ot be in the receive fifo.
1573 DPRINTF(EthernetSM
, "****processing receive of new packet****\n");
1575 // If we don't have a packet, grab a new one from the fifo.
1576 rxPacket
= rxFifo
.front();
1577 rxPktBytes
= rxPacket
->length
;
1578 rxPacketBufPtr
= rxPacket
->data
;
1581 if (DTRACE(Ethernet
)) {
1584 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
1588 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1589 tcp
->sport(), tcp
->dport(), tcp
->seq(),
1596 // sanity check - i think the driver behaves like this
1597 assert(rxDescCnt
>= rxPktBytes
);
1602 // dont' need the && rxDescCnt > 0 if driver sanity check
1604 if (rxPktBytes
> 0) {
1605 rxState
= rxFragWrite
;
1606 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1608 rxXferLen
= rxPktBytes
;
1610 rxDmaAddr
= rxFragPtr
& 0x3fffffff;
1611 rxDmaData
= rxPacketBufPtr
;
1612 rxDmaLen
= rxXferLen
;
1613 rxDmaFree
= dmaDataFree
;
1619 rxState
= rxDescWrite
;
1621 //if (rxPktBytes == 0) { /* packet is done */
1622 assert(rxPktBytes
== 0);
1623 DPRINTF(EthernetSM
, "done with receiving packet\n");
1625 cmdsts
|= CMDSTS_OWN
;
1626 cmdsts
&= ~CMDSTS_MORE
;
1627 cmdsts
|= CMDSTS_OK
;
1628 cmdsts
&= 0xffff0000;
1629 cmdsts
+= rxPacket
->length
; //i.e. set CMDSTS_SIZE
1633 * all the driver uses these are for its own stats keeping
1634 * which we don't care about, aren't necessary for
1635 * functionality and doing this would just slow us down.
1636 * if they end up using this in a later version for
1637 * functional purposes, just undef
1639 if (rxFilterEnable
) {
1640 cmdsts
&= ~CMDSTS_DEST_MASK
;
1641 const EthAddr
&dst
= rxFifoFront()->dst();
1643 cmdsts
|= CMDSTS_DEST_SELF
;
1644 if (dst
->multicast())
1645 cmdsts
|= CMDSTS_DEST_MULTI
;
1646 if (dst
->broadcast())
1647 cmdsts
|= CMDSTS_DEST_MASK
;
1652 if (extstsEnable
&& ip
) {
1653 extsts
|= EXTSTS_IPPKT
;
1655 if (cksum(ip
) != 0) {
1656 DPRINTF(EthernetCksum
, "Rx IP Checksum Error\n");
1657 extsts
|= EXTSTS_IPERR
;
1662 extsts
|= EXTSTS_TCPPKT
;
1664 if (cksum(tcp
) != 0) {
1665 DPRINTF(EthernetCksum
, "Rx TCP Checksum Error\n");
1666 extsts
|= EXTSTS_TCPERR
;
1670 extsts
|= EXTSTS_UDPPKT
;
1672 if (cksum(udp
) != 0) {
1673 DPRINTF(EthernetCksum
, "Rx UDP Checksum Error\n");
1674 extsts
|= EXTSTS_UDPERR
;
1681 * the driver seems to always receive into desc buffers
1682 * of size 1514, so you never have a pkt that is split
1683 * into multiple descriptors on the receive side, so
1684 * i don't implement that case, hence the assert above.
1687 DPRINTF(EthernetDesc
,
1688 "rxDesc: addr=%08x writeback cmdsts extsts\n",
1689 regs
.rxdp
& 0x3fffffff);
1690 DPRINTF(EthernetDesc
,
1691 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1692 link
, bufptr
, cmdsts
, extsts
);
1694 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1695 rxDmaData
= &cmdsts
;
1697 rxDmaAddr
+= offsetof(ns_desc64
, cmdsts
);
1698 rxDmaLen
= sizeof(rxDesc64
.cmdsts
) + sizeof(rxDesc64
.extsts
);
1700 rxDmaAddr
+= offsetof(ns_desc32
, cmdsts
);
1701 rxDmaLen
= sizeof(rxDesc32
.cmdsts
) + sizeof(rxDesc32
.extsts
);
1703 rxDmaFree
= dmaDescFree
;
1706 descDmaWrBytes
+= rxDmaLen
;
1714 if (rxDmaState
!= dmaIdle
)
1717 rxPacketBufPtr
+= rxXferLen
;
1718 rxFragPtr
+= rxXferLen
;
1719 rxPktBytes
-= rxXferLen
;
1721 rxState
= rxFifoBlock
;
1725 if (rxDmaState
!= dmaIdle
)
1728 assert(cmdsts
& CMDSTS_OWN
);
1730 assert(rxPacket
== 0);
1731 devIntrPost(ISR_RXOK
);
1733 if (cmdsts
& CMDSTS_INTR
)
1734 devIntrPost(ISR_RXDESC
);
1737 DPRINTF(EthernetSM
, "Halting the RX state machine\n");
1741 rxState
= rxAdvance
;
1746 devIntrPost(ISR_RXIDLE
);
1751 if (rxDmaState
!= dmaIdle
)
1753 rxState
= rxDescRead
;
1757 rxDmaAddr
= regs
.rxdp
& 0x3fffffff;
1758 rxDmaData
= is64bit
? (void *)&rxDesc64
: (void *)&rxDesc32
;
1759 rxDmaLen
= is64bit
? sizeof(rxDesc64
) : sizeof(rxDesc32
);
1760 rxDmaFree
= dmaDescFree
;
1768 panic("Invalid rxState!");
1771 DPRINTF(EthernetSM
, "entering next rxState=%s\n",
1772 NsRxStateStrings
[rxState
]);
1777 * @todo do we want to schedule a future kick?
1779 DPRINTF(EthernetSM
, "rx state machine exited rxState=%s\n",
1780 NsRxStateStrings
[rxState
]);
1782 if (clock
&& !rxKickEvent
.scheduled())
1783 rxKickEvent
.schedule(rxKickTick
);
1789 if (txFifo
.empty()) {
1790 DPRINTF(Ethernet
, "nothing to transmit\n");
1794 DPRINTF(Ethernet
, "Attempt Pkt Transmit: txFifo length=%d\n",
1796 if (interface
->sendPacket(txFifo
.front())) {
1798 if (DTRACE(Ethernet
)) {
1799 IpPtr
ip(txFifo
.front());
1801 DPRINTF(Ethernet
, "ID is %d\n", ip
->id());
1805 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1806 tcp
->sport(), tcp
->dport(), tcp
->seq(),
1813 DDUMP(EthernetData
, txFifo
.front()->data
, txFifo
.front()->length
);
1814 txBytes
+= txFifo
.front()->length
;
1817 DPRINTF(Ethernet
, "Successful Xmit! now txFifoAvail is %d\n",
1822 * normally do a writeback of the descriptor here, and ONLY
1823 * after that is done, send this interrupt. but since our
1824 * stuff never actually fails, just do this interrupt here,
1825 * otherwise the code has to stray from this nice format.
1826 * besides, it's functionally the same.
1828 devIntrPost(ISR_TXOK
);
1831 if (!txFifo
.empty() && !txEvent
.scheduled()) {
1832 DPRINTF(Ethernet
, "reschedule transmit\n");
1833 txEvent
.schedule(curTick
+ retryTime
);
1838 NSGigE::doTxDmaRead()
1840 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaReadWaiting
);
1841 txDmaState
= dmaReading
;
1843 if (dmaPending() || getState() != Running
)
1844 txDmaState
= dmaReadWaiting
;
1846 dmaRead(txDmaAddr
, txDmaLen
, &txDmaReadEvent
, (uint8_t*)txDmaData
);
1852 NSGigE::txDmaReadDone()
1854 assert(txDmaState
== dmaReading
);
1855 txDmaState
= dmaIdle
;
1857 DPRINTF(EthernetDMA
, "tx dma read paddr=%#x len=%d\n",
1858 txDmaAddr
, txDmaLen
);
1859 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1861 // If the receive state machine has a pending DMA, let it go first
1862 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1869 NSGigE::doTxDmaWrite()
1871 assert(txDmaState
== dmaIdle
|| txDmaState
== dmaWriteWaiting
);
1872 txDmaState
= dmaWriting
;
1874 if (dmaPending() || getState() != Running
)
1875 txDmaState
= dmaWriteWaiting
;
1877 dmaWrite(txDmaAddr
, txDmaLen
, &txDmaWriteEvent
, (uint8_t*)txDmaData
);
1882 NSGigE::txDmaWriteDone()
1884 assert(txDmaState
== dmaWriting
);
1885 txDmaState
= dmaIdle
;
1887 DPRINTF(EthernetDMA
, "tx dma write paddr=%#x len=%d\n",
1888 txDmaAddr
, txDmaLen
);
1889 DDUMP(EthernetDMA
, txDmaData
, txDmaLen
);
1891 // If the receive state machine has a pending DMA, let it go first
1892 if (rxDmaState
== dmaReadWaiting
|| rxDmaState
== dmaWriteWaiting
)
1901 bool is64bit
= (bool)(regs
.config
& CFGR_M64ADDR
);
1903 DPRINTF(EthernetSM
, "transmit kick txState=%s %d-bit\n",
1904 NsTxStateStrings
[txState
], is64bit
? 64 : 32);
1907 uint32_t &cmdsts
= is64bit
? txDesc64
.cmdsts
: txDesc32
.cmdsts
;
1908 uint32_t &extsts
= is64bit
? txDesc64
.extsts
: txDesc32
.extsts
;
1912 if (txKickTick
> curTick
) {
1913 DPRINTF(EthernetSM
, "transmit kick exiting, can't run till %d\n",
1918 // Go to the next state machine clock tick.
1919 txKickTick
= curTick
+ ticks(1);
1922 switch(txDmaState
) {
1923 case dmaReadWaiting
:
1927 case dmaWriteWaiting
:
1935 link
= is64bit
? (Addr
)txDesc64
.link
: (Addr
)txDesc32
.link
;
1936 bufptr
= is64bit
? (Addr
)txDesc64
.bufptr
: (Addr
)txDesc32
.bufptr
;
1940 DPRINTF(EthernetSM
, "Transmit disabled. Nothing to do.\n");
1945 txState
= txDescRefr
;
1947 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1949 is64bit
? (void *)&txDesc64
.link
: (void *)&txDesc32
.link
;
1950 txDmaLen
= is64bit
? sizeof(txDesc64
.link
) : sizeof(txDesc32
.link
);
1951 txDmaFree
= dmaDescFree
;
1954 descDmaRdBytes
+= txDmaLen
;
1960 txState
= txDescRead
;
1962 txDmaAddr
= regs
.txdp
& 0x3fffffff;
1963 txDmaData
= is64bit
? (void *)&txDesc64
: (void *)&txDesc32
;
1964 txDmaLen
= is64bit
? sizeof(txDesc64
) : sizeof(txDesc32
);
1965 txDmaFree
= dmaDescFree
;
1968 descDmaRdBytes
+= txDmaLen
;
1976 if (txDmaState
!= dmaIdle
)
1979 txState
= txAdvance
;
1983 if (txDmaState
!= dmaIdle
)
1986 DPRINTF(EthernetDesc
, "txDesc: addr=%08x read descriptor\n",
1987 regs
.txdp
& 0x3fffffff);
1988 DPRINTF(EthernetDesc
,
1989 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1990 link
, bufptr
, cmdsts
, extsts
);
1992 if (cmdsts
& CMDSTS_OWN
) {
1993 txState
= txFifoBlock
;
1995 txDescCnt
= cmdsts
& CMDSTS_LEN_MASK
;
1997 devIntrPost(ISR_TXIDLE
);
2005 DPRINTF(EthernetSM
, "****starting the tx of a new packet****\n");
2006 txPacket
= new EthPacketData(16384);
2007 txPacketBufPtr
= txPacket
->data
;
2010 if (txDescCnt
== 0) {
2011 DPRINTF(EthernetSM
, "the txDescCnt == 0, done with descriptor\n");
2012 if (cmdsts
& CMDSTS_MORE
) {
2013 DPRINTF(EthernetSM
, "there are more descriptors to come\n");
2014 txState
= txDescWrite
;
2016 cmdsts
&= ~CMDSTS_OWN
;
2018 txDmaAddr
= regs
.txdp
& 0x3fffffff;
2019 txDmaData
= &cmdsts
;
2021 txDmaAddr
+= offsetof(ns_desc64
, cmdsts
);
2022 txDmaLen
= sizeof(txDesc64
.cmdsts
);
2024 txDmaAddr
+= offsetof(ns_desc32
, cmdsts
);
2025 txDmaLen
= sizeof(txDesc32
.cmdsts
);
2027 txDmaFree
= dmaDescFree
;
2032 } else { /* this packet is totally done */
2033 DPRINTF(EthernetSM
, "This packet is done, let's wrap it up\n");
2034 /* deal with the the packet that just finished */
2035 if ((regs
.vtcr
& VTCR_PPCHK
) && extstsEnable
) {
2037 if (extsts
& EXTSTS_UDPPKT
) {
2041 udp
->sum(cksum(udp
));
2045 warn_once("UDPPKT set, but not UDP!\n");
2047 } else if (extsts
& EXTSTS_TCPPKT
) {
2051 tcp
->sum(cksum(tcp
));
2055 warn_once("TCPPKT set, but not UDP!\n");
2058 if (extsts
& EXTSTS_IPPKT
) {
2065 warn_once("IPPKT set, but not UDP!\n");
2070 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
2071 // this is just because the receive can't handle a
2072 // packet bigger want to make sure
2073 if (txPacket
->length
> 1514)
2074 panic("transmit packet too large, %s > 1514\n",
2080 txFifo
.push(txPacket
);
2084 * this following section is not tqo spec, but
2085 * functionally shouldn't be any different. normally,
2086 * the chip will wait til the transmit has occurred
2087 * before writing back the descriptor because it has
2088 * to wait to see that it was successfully transmitted
2089 * to decide whether to set CMDSTS_OK or not.
2090 * however, in the simulator since it is always
2091 * successfully transmitted, and writing it exactly to
2092 * spec would complicate the code, we just do it here
2095 cmdsts
&= ~CMDSTS_OWN
;
2096 cmdsts
|= CMDSTS_OK
;
2098 DPRINTF(EthernetDesc
,
2099 "txDesc writeback: cmdsts=%08x extsts=%08x\n",
2102 txDmaFree
= dmaDescFree
;
2103 txDmaAddr
= regs
.txdp
& 0x3fffffff;
2104 txDmaData
= &cmdsts
;
2106 txDmaAddr
+= offsetof(ns_desc64
, cmdsts
);
2108 sizeof(txDesc64
.cmdsts
) + sizeof(txDesc64
.extsts
);
2110 txDmaAddr
+= offsetof(ns_desc32
, cmdsts
);
2112 sizeof(txDesc32
.cmdsts
) + sizeof(txDesc32
.extsts
);
2116 descDmaWrBytes
+= txDmaLen
;
2122 DPRINTF(EthernetSM
, "halting TX state machine\n");
2126 txState
= txAdvance
;
2132 DPRINTF(EthernetSM
, "this descriptor isn't done yet\n");
2133 if (!txFifo
.full()) {
2134 txState
= txFragRead
;
2137 * The number of bytes transferred is either whatever
2138 * is left in the descriptor (txDescCnt), or if there
2139 * is not enough room in the fifo, just whatever room
2140 * is left in the fifo
2142 txXferLen
= min
<uint32_t>(txDescCnt
, txFifo
.avail());
2144 txDmaAddr
= txFragPtr
& 0x3fffffff;
2145 txDmaData
= txPacketBufPtr
;
2146 txDmaLen
= txXferLen
;
2147 txDmaFree
= dmaDataFree
;
2152 txState
= txFifoBlock
;
2162 if (txDmaState
!= dmaIdle
)
2165 txPacketBufPtr
+= txXferLen
;
2166 txFragPtr
+= txXferLen
;
2167 txDescCnt
-= txXferLen
;
2168 txFifo
.reserve(txXferLen
);
2170 txState
= txFifoBlock
;
2174 if (txDmaState
!= dmaIdle
)
2177 if (cmdsts
& CMDSTS_INTR
)
2178 devIntrPost(ISR_TXDESC
);
2181 DPRINTF(EthernetSM
, "halting TX state machine\n");
2185 txState
= txAdvance
;
2190 devIntrPost(ISR_TXIDLE
);
2194 if (txDmaState
!= dmaIdle
)
2196 txState
= txDescRead
;
2200 txDmaAddr
= link
& 0x3fffffff;
2201 txDmaData
= is64bit
? (void *)&txDesc64
: (void *)&txDesc32
;
2202 txDmaLen
= is64bit
? sizeof(txDesc64
) : sizeof(txDesc32
);
2203 txDmaFree
= dmaDescFree
;
2211 panic("invalid state");
2214 DPRINTF(EthernetSM
, "entering next txState=%s\n",
2215 NsTxStateStrings
[txState
]);
2220 * @todo do we want to schedule a future kick?
2222 DPRINTF(EthernetSM
, "tx state machine exited txState=%s\n",
2223 NsTxStateStrings
[txState
]);
2225 if (clock
&& !txKickEvent
.scheduled())
2226 txKickEvent
.schedule(txKickTick
);
2230 * Advance the EEPROM state machine
2231 * Called on rising edge of EEPROM clock bit in MEAR
2234 NSGigE::eepromKick()
2236 switch (eepromState
) {
2240 // Wait for start bit
2241 if (regs
.mear
& MEAR_EEDI
) {
2242 // Set up to get 2 opcode bits
2243 eepromState
= eepromGetOpcode
;
2249 case eepromGetOpcode
:
2251 eepromOpcode
+= (regs
.mear
& MEAR_EEDI
) ? 1 : 0;
2254 // Done getting opcode
2255 if (eepromBitsToRx
== 0) {
2256 if (eepromOpcode
!= EEPROM_READ
)
2257 panic("only EEPROM reads are implemented!");
2259 // Set up to get address
2260 eepromState
= eepromGetAddress
;
2266 case eepromGetAddress
:
2267 eepromAddress
<<= 1;
2268 eepromAddress
+= (regs
.mear
& MEAR_EEDI
) ? 1 : 0;
2271 // Done getting address
2272 if (eepromBitsToRx
== 0) {
2274 if (eepromAddress
>= EEPROM_SIZE
)
2275 panic("EEPROM read access out of range!");
2277 switch (eepromAddress
) {
2279 case EEPROM_PMATCH2_ADDR
:
2280 eepromData
= rom
.perfectMatch
[5];
2282 eepromData
+= rom
.perfectMatch
[4];
2285 case EEPROM_PMATCH1_ADDR
:
2286 eepromData
= rom
.perfectMatch
[3];
2288 eepromData
+= rom
.perfectMatch
[2];
2291 case EEPROM_PMATCH0_ADDR
:
2292 eepromData
= rom
.perfectMatch
[1];
2294 eepromData
+= rom
.perfectMatch
[0];
2298 panic("FreeBSD driver only uses EEPROM to read PMATCH!");
2300 // Set up to read data
2301 eepromState
= eepromRead
;
2302 eepromBitsToRx
= 16;
2304 // Clear data in bit
2305 regs
.mear
&= ~MEAR_EEDI
;
2310 // Clear Data Out bit
2311 regs
.mear
&= ~MEAR_EEDO
;
2312 // Set bit to value of current EEPROM bit
2313 regs
.mear
|= (eepromData
& 0x8000) ? MEAR_EEDO
: 0x0;
2319 if (eepromBitsToRx
== 0) {
2320 eepromState
= eepromStart
;
2325 panic("invalid EEPROM state");
2331 NSGigE::transferDone()
2333 if (txFifo
.empty()) {
2334 DPRINTF(Ethernet
, "transfer complete: txFifo empty...nothing to do\n");
2338 DPRINTF(Ethernet
, "transfer complete: data in txFifo...schedule xmit\n");
2340 txEvent
.reschedule(curTick
+ ticks(1), true);
2344 NSGigE::rxFilter(const EthPacketPtr
&packet
)
2346 EthPtr eth
= packet
;
2350 const EthAddr
&dst
= eth
->dst();
2351 if (dst
.unicast()) {
2352 // If we're accepting all unicast addresses
2356 // If we make a perfect match
2357 if (acceptPerfect
&& dst
== rom
.perfectMatch
)
2360 if (acceptArp
&& eth
->type() == ETH_TYPE_ARP
)
2363 } else if (dst
.broadcast()) {
2364 // if we're accepting broadcasts
2365 if (acceptBroadcast
)
2368 } else if (dst
.multicast()) {
2369 // if we're accepting all multicasts
2370 if (acceptMulticast
)
2373 // Multicast hashing faked - all packets accepted
2374 if (multicastHashEnable
)
2379 DPRINTF(Ethernet
, "rxFilter drop\n");
2380 DDUMP(EthernetData
, packet
->data
, packet
->length
);
2387 NSGigE::recvPacket(EthPacketPtr packet
)
2389 rxBytes
+= packet
->length
;
2392 DPRINTF(Ethernet
, "Receiving packet from wire, rxFifoAvail=%d\n",
2396 DPRINTF(Ethernet
, "receive disabled...packet dropped\n");
2400 if (!rxFilterEnable
) {
2402 "receive packet filtering disabled . . . packet dropped\n");
2406 if (rxFilter(packet
)) {
2407 DPRINTF(Ethernet
, "packet filtered...dropped\n");
2411 if (rxFifo
.avail() < packet
->length
) {
2417 "packet won't fit in receive buffer...pkt ID %d dropped\n",
2420 DPRINTF(Ethernet
, "Seq=%d\n", tcp
->seq());
2425 devIntrPost(ISR_RXORN
);
2429 rxFifo
.push(packet
);
2439 SimObject::resume();
2441 // During drain we could have left the state machines in a waiting state and
2442 // they wouldn't get out until some other event occured to kick them.
2443 // This way they'll get out immediately
2449 //=====================================================================
2453 NSGigE::serialize(ostream
&os
)
2455 // Serialize the PciDev base class
2456 PciDev::serialize(os
);
2459 * Finalize any DMA events now.
2461 // @todo will mem system save pending dma?
2464 * Serialize the device registers
2466 SERIALIZE_SCALAR(regs
.command
);
2467 SERIALIZE_SCALAR(regs
.config
);
2468 SERIALIZE_SCALAR(regs
.mear
);
2469 SERIALIZE_SCALAR(regs
.ptscr
);
2470 SERIALIZE_SCALAR(regs
.isr
);
2471 SERIALIZE_SCALAR(regs
.imr
);
2472 SERIALIZE_SCALAR(regs
.ier
);
2473 SERIALIZE_SCALAR(regs
.ihr
);
2474 SERIALIZE_SCALAR(regs
.txdp
);
2475 SERIALIZE_SCALAR(regs
.txdp_hi
);
2476 SERIALIZE_SCALAR(regs
.txcfg
);
2477 SERIALIZE_SCALAR(regs
.gpior
);
2478 SERIALIZE_SCALAR(regs
.rxdp
);
2479 SERIALIZE_SCALAR(regs
.rxdp_hi
);
2480 SERIALIZE_SCALAR(regs
.rxcfg
);
2481 SERIALIZE_SCALAR(regs
.pqcr
);
2482 SERIALIZE_SCALAR(regs
.wcsr
);
2483 SERIALIZE_SCALAR(regs
.pcr
);
2484 SERIALIZE_SCALAR(regs
.rfcr
);
2485 SERIALIZE_SCALAR(regs
.rfdr
);
2486 SERIALIZE_SCALAR(regs
.brar
);
2487 SERIALIZE_SCALAR(regs
.brdr
);
2488 SERIALIZE_SCALAR(regs
.srr
);
2489 SERIALIZE_SCALAR(regs
.mibc
);
2490 SERIALIZE_SCALAR(regs
.vrcr
);
2491 SERIALIZE_SCALAR(regs
.vtcr
);
2492 SERIALIZE_SCALAR(regs
.vdr
);
2493 SERIALIZE_SCALAR(regs
.ccsr
);
2494 SERIALIZE_SCALAR(regs
.tbicr
);
2495 SERIALIZE_SCALAR(regs
.tbisr
);
2496 SERIALIZE_SCALAR(regs
.tanar
);
2497 SERIALIZE_SCALAR(regs
.tanlpar
);
2498 SERIALIZE_SCALAR(regs
.taner
);
2499 SERIALIZE_SCALAR(regs
.tesr
);
2501 SERIALIZE_ARRAY(rom
.perfectMatch
, ETH_ADDR_LEN
);
2502 SERIALIZE_ARRAY(rom
.filterHash
, FHASH_SIZE
);
2504 SERIALIZE_SCALAR(ioEnable
);
2507 * Serialize the data Fifos
2509 rxFifo
.serialize("rxFifo", os
);
2510 txFifo
.serialize("txFifo", os
);
2513 * Serialize the various helper variables
2515 bool txPacketExists
= txPacket
;
2516 SERIALIZE_SCALAR(txPacketExists
);
2517 if (txPacketExists
) {
2518 txPacket
->length
= txPacketBufPtr
- txPacket
->data
;
2519 txPacket
->serialize("txPacket", os
);
2520 uint32_t txPktBufPtr
= (uint32_t) (txPacketBufPtr
- txPacket
->data
);
2521 SERIALIZE_SCALAR(txPktBufPtr
);
2524 bool rxPacketExists
= rxPacket
;
2525 SERIALIZE_SCALAR(rxPacketExists
);
2526 if (rxPacketExists
) {
2527 rxPacket
->serialize("rxPacket", os
);
2528 uint32_t rxPktBufPtr
= (uint32_t) (rxPacketBufPtr
- rxPacket
->data
);
2529 SERIALIZE_SCALAR(rxPktBufPtr
);
2532 SERIALIZE_SCALAR(txXferLen
);
2533 SERIALIZE_SCALAR(rxXferLen
);
2536 * Serialize Cached Descriptors
2538 SERIALIZE_SCALAR(rxDesc64
.link
);
2539 SERIALIZE_SCALAR(rxDesc64
.bufptr
);
2540 SERIALIZE_SCALAR(rxDesc64
.cmdsts
);
2541 SERIALIZE_SCALAR(rxDesc64
.extsts
);
2542 SERIALIZE_SCALAR(txDesc64
.link
);
2543 SERIALIZE_SCALAR(txDesc64
.bufptr
);
2544 SERIALIZE_SCALAR(txDesc64
.cmdsts
);
2545 SERIALIZE_SCALAR(txDesc64
.extsts
);
2546 SERIALIZE_SCALAR(rxDesc32
.link
);
2547 SERIALIZE_SCALAR(rxDesc32
.bufptr
);
2548 SERIALIZE_SCALAR(rxDesc32
.cmdsts
);
2549 SERIALIZE_SCALAR(rxDesc32
.extsts
);
2550 SERIALIZE_SCALAR(txDesc32
.link
);
2551 SERIALIZE_SCALAR(txDesc32
.bufptr
);
2552 SERIALIZE_SCALAR(txDesc32
.cmdsts
);
2553 SERIALIZE_SCALAR(txDesc32
.extsts
);
2554 SERIALIZE_SCALAR(extstsEnable
);
2557 * Serialize tx state machine
2559 int txState
= this->txState
;
2560 SERIALIZE_SCALAR(txState
);
2561 SERIALIZE_SCALAR(txEnable
);
2562 SERIALIZE_SCALAR(CTDD
);
2563 SERIALIZE_SCALAR(txFragPtr
);
2564 SERIALIZE_SCALAR(txDescCnt
);
2565 int txDmaState
= this->txDmaState
;
2566 SERIALIZE_SCALAR(txDmaState
);
2567 SERIALIZE_SCALAR(txKickTick
);
2570 * Serialize rx state machine
2572 int rxState
= this->rxState
;
2573 SERIALIZE_SCALAR(rxState
);
2574 SERIALIZE_SCALAR(rxEnable
);
2575 SERIALIZE_SCALAR(CRDD
);
2576 SERIALIZE_SCALAR(rxPktBytes
);
2577 SERIALIZE_SCALAR(rxFragPtr
);
2578 SERIALIZE_SCALAR(rxDescCnt
);
2579 int rxDmaState
= this->rxDmaState
;
2580 SERIALIZE_SCALAR(rxDmaState
);
2581 SERIALIZE_SCALAR(rxKickTick
);
2584 * Serialize EEPROM state machine
2586 int eepromState
= this->eepromState
;
2587 SERIALIZE_SCALAR(eepromState
);
2588 SERIALIZE_SCALAR(eepromClk
);
2589 SERIALIZE_SCALAR(eepromBitsToRx
);
2590 SERIALIZE_SCALAR(eepromOpcode
);
2591 SERIALIZE_SCALAR(eepromAddress
);
2592 SERIALIZE_SCALAR(eepromData
);
2595 * If there's a pending transmit, store the time so we can
2596 * reschedule it later
2598 Tick transmitTick
= txEvent
.scheduled() ? txEvent
.when() - curTick
: 0;
2599 SERIALIZE_SCALAR(transmitTick
);
2602 * receive address filter settings
2604 SERIALIZE_SCALAR(rxFilterEnable
);
2605 SERIALIZE_SCALAR(acceptBroadcast
);
2606 SERIALIZE_SCALAR(acceptMulticast
);
2607 SERIALIZE_SCALAR(acceptUnicast
);
2608 SERIALIZE_SCALAR(acceptPerfect
);
2609 SERIALIZE_SCALAR(acceptArp
);
2610 SERIALIZE_SCALAR(multicastHashEnable
);
2613 * Keep track of pending interrupt status.
2615 SERIALIZE_SCALAR(intrTick
);
2616 SERIALIZE_SCALAR(cpuPendingIntr
);
2617 Tick intrEventTick
= 0;
2619 intrEventTick
= intrEvent
->when();
2620 SERIALIZE_SCALAR(intrEventTick
);
2625 NSGigE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
2627 // Unserialize the PciDev base class
2628 PciDev::unserialize(cp
, section
);
2630 UNSERIALIZE_SCALAR(regs
.command
);
2631 UNSERIALIZE_SCALAR(regs
.config
);
2632 UNSERIALIZE_SCALAR(regs
.mear
);
2633 UNSERIALIZE_SCALAR(regs
.ptscr
);
2634 UNSERIALIZE_SCALAR(regs
.isr
);
2635 UNSERIALIZE_SCALAR(regs
.imr
);
2636 UNSERIALIZE_SCALAR(regs
.ier
);
2637 UNSERIALIZE_SCALAR(regs
.ihr
);
2638 UNSERIALIZE_SCALAR(regs
.txdp
);
2639 UNSERIALIZE_SCALAR(regs
.txdp_hi
);
2640 UNSERIALIZE_SCALAR(regs
.txcfg
);
2641 UNSERIALIZE_SCALAR(regs
.gpior
);
2642 UNSERIALIZE_SCALAR(regs
.rxdp
);
2643 UNSERIALIZE_SCALAR(regs
.rxdp_hi
);
2644 UNSERIALIZE_SCALAR(regs
.rxcfg
);
2645 UNSERIALIZE_SCALAR(regs
.pqcr
);
2646 UNSERIALIZE_SCALAR(regs
.wcsr
);
2647 UNSERIALIZE_SCALAR(regs
.pcr
);
2648 UNSERIALIZE_SCALAR(regs
.rfcr
);
2649 UNSERIALIZE_SCALAR(regs
.rfdr
);
2650 UNSERIALIZE_SCALAR(regs
.brar
);
2651 UNSERIALIZE_SCALAR(regs
.brdr
);
2652 UNSERIALIZE_SCALAR(regs
.srr
);
2653 UNSERIALIZE_SCALAR(regs
.mibc
);
2654 UNSERIALIZE_SCALAR(regs
.vrcr
);
2655 UNSERIALIZE_SCALAR(regs
.vtcr
);
2656 UNSERIALIZE_SCALAR(regs
.vdr
);
2657 UNSERIALIZE_SCALAR(regs
.ccsr
);
2658 UNSERIALIZE_SCALAR(regs
.tbicr
);
2659 UNSERIALIZE_SCALAR(regs
.tbisr
);
2660 UNSERIALIZE_SCALAR(regs
.tanar
);
2661 UNSERIALIZE_SCALAR(regs
.tanlpar
);
2662 UNSERIALIZE_SCALAR(regs
.taner
);
2663 UNSERIALIZE_SCALAR(regs
.tesr
);
2665 UNSERIALIZE_ARRAY(rom
.perfectMatch
, ETH_ADDR_LEN
);
2666 UNSERIALIZE_ARRAY(rom
.filterHash
, FHASH_SIZE
);
2668 UNSERIALIZE_SCALAR(ioEnable
);
2671 * unserialize the data fifos
2673 rxFifo
.unserialize("rxFifo", cp
, section
);
2674 txFifo
.unserialize("txFifo", cp
, section
);
2677 * unserialize the various helper variables
2679 bool txPacketExists
;
2680 UNSERIALIZE_SCALAR(txPacketExists
);
2681 if (txPacketExists
) {
2682 txPacket
= new EthPacketData(16384);
2683 txPacket
->unserialize("txPacket", cp
, section
);
2684 uint32_t txPktBufPtr
;
2685 UNSERIALIZE_SCALAR(txPktBufPtr
);
2686 txPacketBufPtr
= (uint8_t *) txPacket
->data
+ txPktBufPtr
;
2690 bool rxPacketExists
;
2691 UNSERIALIZE_SCALAR(rxPacketExists
);
2693 if (rxPacketExists
) {
2694 rxPacket
= new EthPacketData(16384);
2695 rxPacket
->unserialize("rxPacket", cp
, section
);
2696 uint32_t rxPktBufPtr
;
2697 UNSERIALIZE_SCALAR(rxPktBufPtr
);
2698 rxPacketBufPtr
= (uint8_t *) rxPacket
->data
+ rxPktBufPtr
;
2702 UNSERIALIZE_SCALAR(txXferLen
);
2703 UNSERIALIZE_SCALAR(rxXferLen
);
2706 * Unserialize Cached Descriptors
2708 UNSERIALIZE_SCALAR(rxDesc64
.link
);
2709 UNSERIALIZE_SCALAR(rxDesc64
.bufptr
);
2710 UNSERIALIZE_SCALAR(rxDesc64
.cmdsts
);
2711 UNSERIALIZE_SCALAR(rxDesc64
.extsts
);
2712 UNSERIALIZE_SCALAR(txDesc64
.link
);
2713 UNSERIALIZE_SCALAR(txDesc64
.bufptr
);
2714 UNSERIALIZE_SCALAR(txDesc64
.cmdsts
);
2715 UNSERIALIZE_SCALAR(txDesc64
.extsts
);
2716 UNSERIALIZE_SCALAR(rxDesc32
.link
);
2717 UNSERIALIZE_SCALAR(rxDesc32
.bufptr
);
2718 UNSERIALIZE_SCALAR(rxDesc32
.cmdsts
);
2719 UNSERIALIZE_SCALAR(rxDesc32
.extsts
);
2720 UNSERIALIZE_SCALAR(txDesc32
.link
);
2721 UNSERIALIZE_SCALAR(txDesc32
.bufptr
);
2722 UNSERIALIZE_SCALAR(txDesc32
.cmdsts
);
2723 UNSERIALIZE_SCALAR(txDesc32
.extsts
);
2724 UNSERIALIZE_SCALAR(extstsEnable
);
2727 * unserialize tx state machine
2730 UNSERIALIZE_SCALAR(txState
);
2731 this->txState
= (TxState
) txState
;
2732 UNSERIALIZE_SCALAR(txEnable
);
2733 UNSERIALIZE_SCALAR(CTDD
);
2734 UNSERIALIZE_SCALAR(txFragPtr
);
2735 UNSERIALIZE_SCALAR(txDescCnt
);
2737 UNSERIALIZE_SCALAR(txDmaState
);
2738 this->txDmaState
= (DmaState
) txDmaState
;
2739 UNSERIALIZE_SCALAR(txKickTick
);
2741 txKickEvent
.schedule(txKickTick
);
2744 * unserialize rx state machine
2747 UNSERIALIZE_SCALAR(rxState
);
2748 this->rxState
= (RxState
) rxState
;
2749 UNSERIALIZE_SCALAR(rxEnable
);
2750 UNSERIALIZE_SCALAR(CRDD
);
2751 UNSERIALIZE_SCALAR(rxPktBytes
);
2752 UNSERIALIZE_SCALAR(rxFragPtr
);
2753 UNSERIALIZE_SCALAR(rxDescCnt
);
2755 UNSERIALIZE_SCALAR(rxDmaState
);
2756 this->rxDmaState
= (DmaState
) rxDmaState
;
2757 UNSERIALIZE_SCALAR(rxKickTick
);
2759 rxKickEvent
.schedule(rxKickTick
);
2762 * Unserialize EEPROM state machine
2765 UNSERIALIZE_SCALAR(eepromState
);
2766 this->eepromState
= (EEPROMState
) eepromState
;
2767 UNSERIALIZE_SCALAR(eepromClk
);
2768 UNSERIALIZE_SCALAR(eepromBitsToRx
);
2769 UNSERIALIZE_SCALAR(eepromOpcode
);
2770 UNSERIALIZE_SCALAR(eepromAddress
);
2771 UNSERIALIZE_SCALAR(eepromData
);
2774 * If there's a pending transmit, reschedule it now
2777 UNSERIALIZE_SCALAR(transmitTick
);
2779 txEvent
.schedule(curTick
+ transmitTick
);
2782 * unserialize receive address filter settings
2784 UNSERIALIZE_SCALAR(rxFilterEnable
);
2785 UNSERIALIZE_SCALAR(acceptBroadcast
);
2786 UNSERIALIZE_SCALAR(acceptMulticast
);
2787 UNSERIALIZE_SCALAR(acceptUnicast
);
2788 UNSERIALIZE_SCALAR(acceptPerfect
);
2789 UNSERIALIZE_SCALAR(acceptArp
);
2790 UNSERIALIZE_SCALAR(multicastHashEnable
);
2793 * Keep track of pending interrupt status.
2795 UNSERIALIZE_SCALAR(intrTick
);
2796 UNSERIALIZE_SCALAR(cpuPendingIntr
);
2798 UNSERIALIZE_SCALAR(intrEventTick
);
2799 if (intrEventTick
) {
2800 intrEvent
= new IntrEvent(this, intrEventTick
, true);
2805 NSGigEParams::create()
2807 return new NSGigE(this);