ns_gige.cc revision 4981
110612SMarco.Elver@ARM.com/* 210612SMarco.Elver@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 310612SMarco.Elver@ARM.com * All rights reserved. 410612SMarco.Elver@ARM.com * 510612SMarco.Elver@ARM.com * Redistribution and use in source and binary forms, with or without 610612SMarco.Elver@ARM.com * modification, are permitted provided that the following conditions are 710612SMarco.Elver@ARM.com * met: redistributions of source code must retain the above copyright 810612SMarco.Elver@ARM.com * notice, this list of conditions and the following disclaimer; 910612SMarco.Elver@ARM.com * redistributions in binary form must reproduce the above copyright 1010612SMarco.Elver@ARM.com * notice, this list of conditions and the following disclaimer in the 1110612SMarco.Elver@ARM.com * documentation and/or other materials provided with the distribution; 1210612SMarco.Elver@ARM.com * neither the name of the copyright holders nor the names of its 1310612SMarco.Elver@ARM.com * contributors may be used to endorse or promote products derived from 1410612SMarco.Elver@ARM.com * this software without specific prior written permission. 1510612SMarco.Elver@ARM.com * 1610612SMarco.Elver@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710612SMarco.Elver@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810612SMarco.Elver@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910612SMarco.Elver@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010612SMarco.Elver@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110612SMarco.Elver@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210612SMarco.Elver@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310612SMarco.Elver@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410612SMarco.Elver@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510612SMarco.Elver@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610612SMarco.Elver@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710612SMarco.Elver@ARM.com * 2810612SMarco.Elver@ARM.com * Authors: Nathan Binkert 2910612SMarco.Elver@ARM.com * Lisa Hsu 3010612SMarco.Elver@ARM.com */ 3110612SMarco.Elver@ARM.com 3210612SMarco.Elver@ARM.com/** @file 3310612SMarco.Elver@ARM.com * Device module for modelling the National Semiconductor 3410612SMarco.Elver@ARM.com * DP83820 ethernet controller. Does not support priority queueing 3510612SMarco.Elver@ARM.com */ 3610612SMarco.Elver@ARM.com#include <deque> 3710612SMarco.Elver@ARM.com#include <string> 3810612SMarco.Elver@ARM.com 3910612SMarco.Elver@ARM.com#include "base/inet.hh" 4010612SMarco.Elver@ARM.com#include "cpu/thread_context.hh" 4110612SMarco.Elver@ARM.com#include "dev/etherlink.hh" 4210612SMarco.Elver@ARM.com#include "dev/ns_gige.hh" 4310612SMarco.Elver@ARM.com#include "dev/pciconfigall.hh" 4410612SMarco.Elver@ARM.com#include "mem/packet.hh" 4510612SMarco.Elver@ARM.com#include "mem/packet_access.hh" 4610612SMarco.Elver@ARM.com#include "params/NSGigE.hh" 4710612SMarco.Elver@ARM.com#include "sim/debug.hh" 4810612SMarco.Elver@ARM.com#include "sim/host.hh" 4910612SMarco.Elver@ARM.com#include "sim/stats.hh" 5010612SMarco.Elver@ARM.com#include "sim/system.hh" 5110612SMarco.Elver@ARM.com 5210612SMarco.Elver@ARM.comconst char *NsRxStateStrings[] = 5310612SMarco.Elver@ARM.com{ 5410612SMarco.Elver@ARM.com "rxIdle", 5510612SMarco.Elver@ARM.com "rxDescRefr", 5610612SMarco.Elver@ARM.com "rxDescRead", 5710612SMarco.Elver@ARM.com "rxFifoBlock", 5810612SMarco.Elver@ARM.com "rxFragWrite", 5910612SMarco.Elver@ARM.com "rxDescWrite", 6010612SMarco.Elver@ARM.com "rxAdvance" 6110612SMarco.Elver@ARM.com}; 6210612SMarco.Elver@ARM.com 6310612SMarco.Elver@ARM.comconst char *NsTxStateStrings[] = 6410612SMarco.Elver@ARM.com{ 6510612SMarco.Elver@ARM.com "txIdle", 6610612SMarco.Elver@ARM.com "txDescRefr", 6710612SMarco.Elver@ARM.com "txDescRead", 6810612SMarco.Elver@ARM.com "txFifoBlock", 6910612SMarco.Elver@ARM.com "txFragRead", 7010612SMarco.Elver@ARM.com "txDescWrite", 7110612SMarco.Elver@ARM.com "txAdvance" 7210612SMarco.Elver@ARM.com}; 7310612SMarco.Elver@ARM.com 7410612SMarco.Elver@ARM.comconst char *NsDmaState[] = 7510612SMarco.Elver@ARM.com{ 7610612SMarco.Elver@ARM.com "dmaIdle", 7710612SMarco.Elver@ARM.com "dmaReading", 7810612SMarco.Elver@ARM.com "dmaWriting", 7910612SMarco.Elver@ARM.com "dmaReadWaiting", 8010612SMarco.Elver@ARM.com "dmaWriteWaiting" 8110612SMarco.Elver@ARM.com}; 8210612SMarco.Elver@ARM.com 8310612SMarco.Elver@ARM.comusing namespace std; 8410612SMarco.Elver@ARM.comusing namespace Net; 8510612SMarco.Elver@ARM.comusing namespace TheISA; 8610612SMarco.Elver@ARM.com 8710612SMarco.Elver@ARM.com/////////////////////////////////////////////////////////////////////// 8810612SMarco.Elver@ARM.com// 8910612SMarco.Elver@ARM.com// NSGigE PCI Device 9010612SMarco.Elver@ARM.com// 9110612SMarco.Elver@ARM.comNSGigE::NSGigE(Params *p) 9210612SMarco.Elver@ARM.com : EtherDevice(p), ioEnable(false), 9310612SMarco.Elver@ARM.com txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 9410612SMarco.Elver@ARM.com txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 9510612SMarco.Elver@ARM.com txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false), 9610612SMarco.Elver@ARM.com clock(p->clock), 9710612SMarco.Elver@ARM.com txState(txIdle), txEnable(false), CTDD(false), txHalt(false), 9810612SMarco.Elver@ARM.com txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 9910612SMarco.Elver@ARM.com rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false), 10010612SMarco.Elver@ARM.com rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 10110612SMarco.Elver@ARM.com eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0), 10210612SMarco.Elver@ARM.com eepromOpcode(0), eepromAddress(0), eepromData(0), 10310612SMarco.Elver@ARM.com dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay), 10410612SMarco.Elver@ARM.com dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor), 10510612SMarco.Elver@ARM.com rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0), 10610612SMarco.Elver@ARM.com txDmaData(NULL), txDmaAddr(0), txDmaLen(0), 10710612SMarco.Elver@ARM.com rxDmaReadEvent(this), rxDmaWriteEvent(this), 10810612SMarco.Elver@ARM.com txDmaReadEvent(this), txDmaWriteEvent(this), 10910612SMarco.Elver@ARM.com dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 11010612SMarco.Elver@ARM.com txDelay(p->tx_delay), rxDelay(p->rx_delay), 11110612SMarco.Elver@ARM.com rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 11210612SMarco.Elver@ARM.com txEvent(this), rxFilterEnable(p->rx_filter), 11310612SMarco.Elver@ARM.com acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), 11410612SMarco.Elver@ARM.com acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 11510612SMarco.Elver@ARM.com intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false), 11610612SMarco.Elver@ARM.com intrEvent(0), interface(0) 11710612SMarco.Elver@ARM.com{ 11810612SMarco.Elver@ARM.com 11910612SMarco.Elver@ARM.com 12010612SMarco.Elver@ARM.com interface = new NSGigEInt(name() + ".int0", this); 12110612SMarco.Elver@ARM.com 12210612SMarco.Elver@ARM.com regsReset(); 12310612SMarco.Elver@ARM.com memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN); 12410612SMarco.Elver@ARM.com 12510612SMarco.Elver@ARM.com memset(&rxDesc32, 0, sizeof(rxDesc32)); 12610612SMarco.Elver@ARM.com memset(&txDesc32, 0, sizeof(txDesc32)); 12710612SMarco.Elver@ARM.com memset(&rxDesc64, 0, sizeof(rxDesc64)); 12810612SMarco.Elver@ARM.com memset(&txDesc64, 0, sizeof(txDesc64)); 12910612SMarco.Elver@ARM.com} 13010612SMarco.Elver@ARM.com 13110612SMarco.Elver@ARM.comNSGigE::~NSGigE() 13210612SMarco.Elver@ARM.com{} 13310612SMarco.Elver@ARM.com 13410612SMarco.Elver@ARM.comvoid 13510612SMarco.Elver@ARM.comNSGigE::regStats() 13610612SMarco.Elver@ARM.com{ 13710612SMarco.Elver@ARM.com txBytes 13810612SMarco.Elver@ARM.com .name(name() + ".txBytes") 13910612SMarco.Elver@ARM.com .desc("Bytes Transmitted") 14010612SMarco.Elver@ARM.com .prereq(txBytes) 14110612SMarco.Elver@ARM.com ; 14210612SMarco.Elver@ARM.com 14310612SMarco.Elver@ARM.com rxBytes 14410612SMarco.Elver@ARM.com .name(name() + ".rxBytes") 14510612SMarco.Elver@ARM.com .desc("Bytes Received") 14610612SMarco.Elver@ARM.com .prereq(rxBytes) 14710612SMarco.Elver@ARM.com ; 14810612SMarco.Elver@ARM.com 14910612SMarco.Elver@ARM.com txPackets 15010612SMarco.Elver@ARM.com .name(name() + ".txPackets") 15110612SMarco.Elver@ARM.com .desc("Number of Packets Transmitted") 15210612SMarco.Elver@ARM.com .prereq(txBytes) 15310612SMarco.Elver@ARM.com ; 15410612SMarco.Elver@ARM.com 15510612SMarco.Elver@ARM.com rxPackets 15610612SMarco.Elver@ARM.com .name(name() + ".rxPackets") 15710612SMarco.Elver@ARM.com .desc("Number of Packets Received") 15810612SMarco.Elver@ARM.com .prereq(rxBytes) 15910612SMarco.Elver@ARM.com ; 16010612SMarco.Elver@ARM.com 16110612SMarco.Elver@ARM.com txIpChecksums 16210612SMarco.Elver@ARM.com .name(name() + ".txIpChecksums") 16310612SMarco.Elver@ARM.com .desc("Number of tx IP Checksums done by device") 16410612SMarco.Elver@ARM.com .precision(0) 16510612SMarco.Elver@ARM.com .prereq(txBytes) 16610612SMarco.Elver@ARM.com ; 16710612SMarco.Elver@ARM.com 16810612SMarco.Elver@ARM.com rxIpChecksums 16910612SMarco.Elver@ARM.com .name(name() + ".rxIpChecksums") 17010612SMarco.Elver@ARM.com .desc("Number of rx IP Checksums done by device") 17110612SMarco.Elver@ARM.com .precision(0) 17210612SMarco.Elver@ARM.com .prereq(rxBytes) 17310612SMarco.Elver@ARM.com ; 17410612SMarco.Elver@ARM.com 17510612SMarco.Elver@ARM.com txTcpChecksums 17610612SMarco.Elver@ARM.com .name(name() + ".txTcpChecksums") 17710612SMarco.Elver@ARM.com .desc("Number of tx TCP Checksums done by device") 17810612SMarco.Elver@ARM.com .precision(0) 17910612SMarco.Elver@ARM.com .prereq(txBytes) 18010612SMarco.Elver@ARM.com ; 18110612SMarco.Elver@ARM.com 18210612SMarco.Elver@ARM.com rxTcpChecksums 18310612SMarco.Elver@ARM.com .name(name() + ".rxTcpChecksums") 18410612SMarco.Elver@ARM.com .desc("Number of rx TCP Checksums done by device") 18510612SMarco.Elver@ARM.com .precision(0) 18610612SMarco.Elver@ARM.com .prereq(rxBytes) 18710612SMarco.Elver@ARM.com ; 18810612SMarco.Elver@ARM.com 18910612SMarco.Elver@ARM.com txUdpChecksums 19010612SMarco.Elver@ARM.com .name(name() + ".txUdpChecksums") 19110612SMarco.Elver@ARM.com .desc("Number of tx UDP Checksums done by device") 19210612SMarco.Elver@ARM.com .precision(0) 19310612SMarco.Elver@ARM.com .prereq(txBytes) 19410612SMarco.Elver@ARM.com ; 19510612SMarco.Elver@ARM.com 19610612SMarco.Elver@ARM.com rxUdpChecksums 19710612SMarco.Elver@ARM.com .name(name() + ".rxUdpChecksums") 19810612SMarco.Elver@ARM.com .desc("Number of rx UDP Checksums done by device") 19910612SMarco.Elver@ARM.com .precision(0) 20010612SMarco.Elver@ARM.com .prereq(rxBytes) 20110612SMarco.Elver@ARM.com ; 20210612SMarco.Elver@ARM.com 20310612SMarco.Elver@ARM.com descDmaReads 20410612SMarco.Elver@ARM.com .name(name() + ".descDMAReads") 20510612SMarco.Elver@ARM.com .desc("Number of descriptors the device read w/ DMA") 20610612SMarco.Elver@ARM.com .precision(0) 20710612SMarco.Elver@ARM.com ; 20810612SMarco.Elver@ARM.com 20910612SMarco.Elver@ARM.com descDmaWrites 21010612SMarco.Elver@ARM.com .name(name() + ".descDMAWrites") 21110612SMarco.Elver@ARM.com .desc("Number of descriptors the device wrote w/ DMA") 21210612SMarco.Elver@ARM.com .precision(0) 21310612SMarco.Elver@ARM.com ; 21410612SMarco.Elver@ARM.com 21510612SMarco.Elver@ARM.com descDmaRdBytes 21610612SMarco.Elver@ARM.com .name(name() + ".descDmaReadBytes") 21710612SMarco.Elver@ARM.com .desc("number of descriptor bytes read w/ DMA") 21810612SMarco.Elver@ARM.com .precision(0) 21910612SMarco.Elver@ARM.com ; 22010612SMarco.Elver@ARM.com 22110612SMarco.Elver@ARM.com descDmaWrBytes 22210612SMarco.Elver@ARM.com .name(name() + ".descDmaWriteBytes") 22310612SMarco.Elver@ARM.com .desc("number of descriptor bytes write w/ DMA") 22410612SMarco.Elver@ARM.com .precision(0) 22510612SMarco.Elver@ARM.com ; 22610612SMarco.Elver@ARM.com 22710612SMarco.Elver@ARM.com txBandwidth 22810612SMarco.Elver@ARM.com .name(name() + ".txBandwidth") 22910612SMarco.Elver@ARM.com .desc("Transmit Bandwidth (bits/s)") 23010612SMarco.Elver@ARM.com .precision(0) 23110612SMarco.Elver@ARM.com .prereq(txBytes) 23210612SMarco.Elver@ARM.com ; 23310612SMarco.Elver@ARM.com 23410612SMarco.Elver@ARM.com rxBandwidth 23510612SMarco.Elver@ARM.com .name(name() + ".rxBandwidth") 23610612SMarco.Elver@ARM.com .desc("Receive Bandwidth (bits/s)") 23710612SMarco.Elver@ARM.com .precision(0) 23810612SMarco.Elver@ARM.com .prereq(rxBytes) 23910612SMarco.Elver@ARM.com ; 24010612SMarco.Elver@ARM.com 24110612SMarco.Elver@ARM.com totBandwidth 24210612SMarco.Elver@ARM.com .name(name() + ".totBandwidth") 24310612SMarco.Elver@ARM.com .desc("Total Bandwidth (bits/s)") 24410612SMarco.Elver@ARM.com .precision(0) 24510612SMarco.Elver@ARM.com .prereq(totBytes) 24610612SMarco.Elver@ARM.com ; 24710612SMarco.Elver@ARM.com 24810612SMarco.Elver@ARM.com totPackets 24910612SMarco.Elver@ARM.com .name(name() + ".totPackets") 25010612SMarco.Elver@ARM.com .desc("Total Packets") 25110612SMarco.Elver@ARM.com .precision(0) 25210612SMarco.Elver@ARM.com .prereq(totBytes) 25310612SMarco.Elver@ARM.com ; 25410612SMarco.Elver@ARM.com 25510612SMarco.Elver@ARM.com totBytes 25610612SMarco.Elver@ARM.com .name(name() + ".totBytes") 25710612SMarco.Elver@ARM.com .desc("Total Bytes") 25810612SMarco.Elver@ARM.com .precision(0) 25910612SMarco.Elver@ARM.com .prereq(totBytes) 26010612SMarco.Elver@ARM.com ; 26110612SMarco.Elver@ARM.com 26210612SMarco.Elver@ARM.com totPacketRate 26310612SMarco.Elver@ARM.com .name(name() + ".totPPS") 26410612SMarco.Elver@ARM.com .desc("Total Tranmission Rate (packets/s)") 26510612SMarco.Elver@ARM.com .precision(0) 26610612SMarco.Elver@ARM.com .prereq(totBytes) 26710612SMarco.Elver@ARM.com ; 26810612SMarco.Elver@ARM.com 26910612SMarco.Elver@ARM.com txPacketRate 27010612SMarco.Elver@ARM.com .name(name() + ".txPPS") 27110612SMarco.Elver@ARM.com .desc("Packet Tranmission Rate (packets/s)") 27210612SMarco.Elver@ARM.com .precision(0) 27310612SMarco.Elver@ARM.com .prereq(txBytes) 27410612SMarco.Elver@ARM.com ; 27510612SMarco.Elver@ARM.com 27610612SMarco.Elver@ARM.com rxPacketRate 27710612SMarco.Elver@ARM.com .name(name() + ".rxPPS") 27810612SMarco.Elver@ARM.com .desc("Packet Reception Rate (packets/s)") 27910612SMarco.Elver@ARM.com .precision(0) 28010612SMarco.Elver@ARM.com .prereq(rxBytes) 28110612SMarco.Elver@ARM.com ; 28210612SMarco.Elver@ARM.com 28310612SMarco.Elver@ARM.com postedSwi 28410612SMarco.Elver@ARM.com .name(name() + ".postedSwi") 28510612SMarco.Elver@ARM.com .desc("number of software interrupts posted to CPU") 28610612SMarco.Elver@ARM.com .precision(0) 28710612SMarco.Elver@ARM.com ; 28810612SMarco.Elver@ARM.com 28910612SMarco.Elver@ARM.com totalSwi 29010612SMarco.Elver@ARM.com .name(name() + ".totalSwi") 29110612SMarco.Elver@ARM.com .desc("total number of Swi written to ISR") 29210612SMarco.Elver@ARM.com .precision(0) 29310612SMarco.Elver@ARM.com ; 29410612SMarco.Elver@ARM.com 29510612SMarco.Elver@ARM.com coalescedSwi 29610612SMarco.Elver@ARM.com .name(name() + ".coalescedSwi") 29710612SMarco.Elver@ARM.com .desc("average number of Swi's coalesced into each post") 29810612SMarco.Elver@ARM.com .precision(0) 29910612SMarco.Elver@ARM.com ; 30010612SMarco.Elver@ARM.com 30110612SMarco.Elver@ARM.com postedRxIdle 30210612SMarco.Elver@ARM.com .name(name() + ".postedRxIdle") 30310612SMarco.Elver@ARM.com .desc("number of rxIdle interrupts posted to CPU") 30410612SMarco.Elver@ARM.com .precision(0) 30510612SMarco.Elver@ARM.com ; 30610612SMarco.Elver@ARM.com 30710612SMarco.Elver@ARM.com totalRxIdle 30810612SMarco.Elver@ARM.com .name(name() + ".totalRxIdle") 30910612SMarco.Elver@ARM.com .desc("total number of RxIdle written to ISR") 31010612SMarco.Elver@ARM.com .precision(0) 31110612SMarco.Elver@ARM.com ; 31210612SMarco.Elver@ARM.com 31310612SMarco.Elver@ARM.com coalescedRxIdle 31410612SMarco.Elver@ARM.com .name(name() + ".coalescedRxIdle") 31510612SMarco.Elver@ARM.com .desc("average number of RxIdle's coalesced into each post") 31610612SMarco.Elver@ARM.com .precision(0) 31710612SMarco.Elver@ARM.com ; 31810612SMarco.Elver@ARM.com 31910612SMarco.Elver@ARM.com postedRxOk 32010612SMarco.Elver@ARM.com .name(name() + ".postedRxOk") 32110612SMarco.Elver@ARM.com .desc("number of RxOk interrupts posted to CPU") 32210612SMarco.Elver@ARM.com .precision(0) 32310612SMarco.Elver@ARM.com ; 32410612SMarco.Elver@ARM.com 32510612SMarco.Elver@ARM.com totalRxOk 32610612SMarco.Elver@ARM.com .name(name() + ".totalRxOk") 32710612SMarco.Elver@ARM.com .desc("total number of RxOk written to ISR") 32810612SMarco.Elver@ARM.com .precision(0) 32910612SMarco.Elver@ARM.com ; 33010612SMarco.Elver@ARM.com 33110612SMarco.Elver@ARM.com coalescedRxOk 33210612SMarco.Elver@ARM.com .name(name() + ".coalescedRxOk") 33310612SMarco.Elver@ARM.com .desc("average number of RxOk's coalesced into each post") 33410612SMarco.Elver@ARM.com .precision(0) 33510612SMarco.Elver@ARM.com ; 33610612SMarco.Elver@ARM.com 33710612SMarco.Elver@ARM.com postedRxDesc 33810612SMarco.Elver@ARM.com .name(name() + ".postedRxDesc") 33910612SMarco.Elver@ARM.com .desc("number of RxDesc interrupts posted to CPU") 34010612SMarco.Elver@ARM.com .precision(0) 34110612SMarco.Elver@ARM.com ; 34210612SMarco.Elver@ARM.com 34310612SMarco.Elver@ARM.com totalRxDesc 34410612SMarco.Elver@ARM.com .name(name() + ".totalRxDesc") 34510612SMarco.Elver@ARM.com .desc("total number of RxDesc written to ISR") 34610612SMarco.Elver@ARM.com .precision(0) 34710612SMarco.Elver@ARM.com ; 34810612SMarco.Elver@ARM.com 34910612SMarco.Elver@ARM.com coalescedRxDesc 35010612SMarco.Elver@ARM.com .name(name() + ".coalescedRxDesc") 35110612SMarco.Elver@ARM.com .desc("average number of RxDesc's coalesced into each post") 35210612SMarco.Elver@ARM.com .precision(0) 35310612SMarco.Elver@ARM.com ; 35410612SMarco.Elver@ARM.com 35510612SMarco.Elver@ARM.com postedTxOk 35610612SMarco.Elver@ARM.com .name(name() + ".postedTxOk") 35710612SMarco.Elver@ARM.com .desc("number of TxOk interrupts posted to CPU") 35810612SMarco.Elver@ARM.com .precision(0) 35910612SMarco.Elver@ARM.com ; 36010612SMarco.Elver@ARM.com 36110612SMarco.Elver@ARM.com totalTxOk 36210612SMarco.Elver@ARM.com .name(name() + ".totalTxOk") 36310612SMarco.Elver@ARM.com .desc("total number of TxOk written to ISR") 36410612SMarco.Elver@ARM.com .precision(0) 36510612SMarco.Elver@ARM.com ; 36610612SMarco.Elver@ARM.com 36710612SMarco.Elver@ARM.com coalescedTxOk 36810612SMarco.Elver@ARM.com .name(name() + ".coalescedTxOk") 36910612SMarco.Elver@ARM.com .desc("average number of TxOk's coalesced into each post") 37010612SMarco.Elver@ARM.com .precision(0) 37110612SMarco.Elver@ARM.com ; 37210612SMarco.Elver@ARM.com 37310612SMarco.Elver@ARM.com postedTxIdle 37410612SMarco.Elver@ARM.com .name(name() + ".postedTxIdle") 375 .desc("number of TxIdle interrupts posted to CPU") 376 .precision(0) 377 ; 378 379 totalTxIdle 380 .name(name() + ".totalTxIdle") 381 .desc("total number of TxIdle written to ISR") 382 .precision(0) 383 ; 384 385 coalescedTxIdle 386 .name(name() + ".coalescedTxIdle") 387 .desc("average number of TxIdle's coalesced into each post") 388 .precision(0) 389 ; 390 391 postedTxDesc 392 .name(name() + ".postedTxDesc") 393 .desc("number of TxDesc interrupts posted to CPU") 394 .precision(0) 395 ; 396 397 totalTxDesc 398 .name(name() + ".totalTxDesc") 399 .desc("total number of TxDesc written to ISR") 400 .precision(0) 401 ; 402 403 coalescedTxDesc 404 .name(name() + ".coalescedTxDesc") 405 .desc("average number of TxDesc's coalesced into each post") 406 .precision(0) 407 ; 408 409 postedRxOrn 410 .name(name() + ".postedRxOrn") 411 .desc("number of RxOrn posted to CPU") 412 .precision(0) 413 ; 414 415 totalRxOrn 416 .name(name() + ".totalRxOrn") 417 .desc("total number of RxOrn written to ISR") 418 .precision(0) 419 ; 420 421 coalescedRxOrn 422 .name(name() + ".coalescedRxOrn") 423 .desc("average number of RxOrn's coalesced into each post") 424 .precision(0) 425 ; 426 427 coalescedTotal 428 .name(name() + ".coalescedTotal") 429 .desc("average number of interrupts coalesced into each post") 430 .precision(0) 431 ; 432 433 postedInterrupts 434 .name(name() + ".postedInterrupts") 435 .desc("number of posts to CPU") 436 .precision(0) 437 ; 438 439 droppedPackets 440 .name(name() + ".droppedPackets") 441 .desc("number of packets dropped") 442 .precision(0) 443 ; 444 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; 453 454 coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 455 totalTxOk + totalTxIdle + totalTxDesc + 456 totalRxOrn) / postedInterrupts; 457 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; 463 464 txPacketRate = txPackets / simSeconds; 465 rxPacketRate = rxPackets / simSeconds; 466} 467 468 469/** 470 * This is to write to the PCI general configuration registers 471 */ 472Tick 473NSGigE::writeConfig(PacketPtr pkt) 474{ 475 int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 476 if (offset < PCI_DEVICE_SPECIFIC) 477 PciDev::writeConfig(pkt); 478 else 479 panic("Device specific PCI config space not implemented!\n"); 480 481 switch (offset) { 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 485 case PCI_COMMAND: 486 if (config.data[offset] & PCI_CMD_IOSE) 487 ioEnable = true; 488 else 489 ioEnable = false; 490 break; 491 } 492 493 return configDelay; 494} 495 496EtherInt* 497NSGigE::getEthPort(const std::string &if_name, int idx) 498{ 499 if (if_name == "interface") { 500 if (interface->getPeer()) 501 panic("interface already connected to\n"); 502 return interface; 503 } 504 return NULL; 505} 506 507/** 508 * This reads the device registers, which are detailed in the NS83820 509 * spec sheet 510 */ 511Tick 512NSGigE::read(PacketPtr pkt) 513{ 514 assert(ioEnable); 515 516 pkt->allocate(); 517 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()); 522 523 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(); 536 return pioDelay; 537 } else if (daddr > 0x3FC) 538 panic("Something is messed up!\n"); 539 540 assert(pkt->getSize() == sizeof(uint32_t)); 541 uint32_t ® = *pkt->getPtr<uint32_t>(); 542 uint16_t rfaddr; 543 544 switch (daddr) { 545 case CR: 546 reg = regs.command; 547 //these are supposed to be cleared on a read 548 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 549 break; 550 551 case CFGR: 552 reg = regs.config; 553 break; 554 555 case MEAR: 556 reg = regs.mear; 557 break; 558 559 case PTSCR: 560 reg = regs.ptscr; 561 break; 562 563 case ISR: 564 reg = regs.isr; 565 devIntrClear(ISR_ALL); 566 break; 567 568 case IMR: 569 reg = regs.imr; 570 break; 571 572 case IER: 573 reg = regs.ier; 574 break; 575 576 case IHR: 577 reg = regs.ihr; 578 break; 579 580 case TXDP: 581 reg = regs.txdp; 582 break; 583 584 case TXDP_HI: 585 reg = regs.txdp_hi; 586 break; 587 588 case TX_CFG: 589 reg = regs.txcfg; 590 break; 591 592 case GPIOR: 593 reg = regs.gpior; 594 break; 595 596 case RXDP: 597 reg = regs.rxdp; 598 break; 599 600 case RXDP_HI: 601 reg = regs.rxdp_hi; 602 break; 603 604 case RX_CFG: 605 reg = regs.rxcfg; 606 break; 607 608 case PQCR: 609 reg = regs.pqcr; 610 break; 611 612 case WCSR: 613 reg = regs.wcsr; 614 break; 615 616 case PCR: 617 reg = regs.pcr; 618 break; 619 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 624 // wrote to RFCR 625 case RFCR: 626 reg = regs.rfcr; 627 break; 628 629 case RFDR: 630 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 631 switch (rfaddr) { 632 // Read from perfect match ROM octets 633 case 0x000: 634 reg = rom.perfectMatch[1]; 635 reg = reg << 8; 636 reg += rom.perfectMatch[0]; 637 break; 638 case 0x002: 639 reg = rom.perfectMatch[3] << 8; 640 reg += rom.perfectMatch[2]; 641 break; 642 case 0x004: 643 reg = rom.perfectMatch[5] << 8; 644 reg += rom.perfectMatch[4]; 645 break; 646 default: 647 // Read filter hash table 648 if (rfaddr >= FHASH_ADDR && 649 rfaddr < FHASH_ADDR + FHASH_SIZE) { 650 651 // Only word-aligned reads supported 652 if (rfaddr % 2) 653 panic("unaligned read from filter hash table!"); 654 655 reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 656 reg += rom.filterHash[rfaddr - FHASH_ADDR]; 657 break; 658 } 659 660 panic("reading RFDR for something other than pattern" 661 " matching or hashing! %#x\n", rfaddr); 662 } 663 break; 664 665 case SRR: 666 reg = regs.srr; 667 break; 668 669 case MIBC: 670 reg = regs.mibc; 671 reg &= ~(MIBC_MIBS | MIBC_ACLR); 672 break; 673 674 case VRCR: 675 reg = regs.vrcr; 676 break; 677 678 case VTCR: 679 reg = regs.vtcr; 680 break; 681 682 case VDR: 683 reg = regs.vdr; 684 break; 685 686 case CCSR: 687 reg = regs.ccsr; 688 break; 689 690 case TBICR: 691 reg = regs.tbicr; 692 break; 693 694 case TBISR: 695 reg = regs.tbisr; 696 break; 697 698 case TANAR: 699 reg = regs.tanar; 700 break; 701 702 case TANLPAR: 703 reg = regs.tanlpar; 704 break; 705 706 case TANER: 707 reg = regs.taner; 708 break; 709 710 case TESR: 711 reg = regs.tesr; 712 break; 713 714 case M5REG: 715 reg = 0; 716 if (params()->rx_thread) 717 reg |= M5REG_RX_THREAD; 718 if (params()->tx_thread) 719 reg |= M5REG_TX_THREAD; 720 if (params()->rss) 721 reg |= M5REG_RSS; 722 break; 723 724 default: 725 panic("reading unimplemented register: addr=%#x", daddr); 726 } 727 728 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 729 daddr, reg, reg); 730 731 pkt->makeAtomicResponse(); 732 return pioDelay; 733} 734 735Tick 736NSGigE::write(PacketPtr pkt) 737{ 738 assert(ioEnable); 739 740 Addr daddr = pkt->getAddr() & 0xfff; 741 DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 742 daddr, pkt->getAddr(), pkt->getSize()); 743 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"); 750 751 if (pkt->getSize() == sizeof(uint32_t)) { 752 uint32_t reg = pkt->get<uint32_t>(); 753 uint16_t rfaddr; 754 755 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 756 757 switch (daddr) { 758 case CR: 759 regs.command = reg; 760 if (reg & CR_TXD) { 761 txEnable = false; 762 } else if (reg & CR_TXE) { 763 txEnable = true; 764 765 // the kernel is enabling the transmit machine 766 if (txState == txIdle) 767 txKick(); 768 } 769 770 if (reg & CR_RXD) { 771 rxEnable = false; 772 } else if (reg & CR_RXE) { 773 rxEnable = true; 774 775 if (rxState == rxIdle) 776 rxKick(); 777 } 778 779 if (reg & CR_TXR) 780 txReset(); 781 782 if (reg & CR_RXR) 783 rxReset(); 784 785 if (reg & CR_SWI) 786 devIntrPost(ISR_SWI); 787 788 if (reg & CR_RST) { 789 txReset(); 790 rxReset(); 791 792 regsReset(); 793 } 794 break; 795 796 case CFGR: 797 if (reg & CFGR_LNKSTS || 798 reg & CFGR_SPDSTS || 799 reg & CFGR_DUPSTS || 800 reg & CFGR_RESERVED || 801 reg & CFGR_T64ADDR || 802 reg & CFGR_PCI64_DET) 803 804 // First clear all writable bits 805 regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 806 CFGR_RESERVED | CFGR_T64ADDR | 807 CFGR_PCI64_DET; 808 // Now set the appropriate writable bits 809 regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 810 CFGR_RESERVED | CFGR_T64ADDR | 811 CFGR_PCI64_DET); 812 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) ; 818 819 if (reg & CFGR_AUTO_1000) 820 panic("CFGR_AUTO_1000 not implemented!\n"); 821 822 if (reg & CFGR_PINT_DUPSTS || 823 reg & CFGR_PINT_LNKSTS || 824 reg & CFGR_PINT_SPDSTS) 825 ; 826 827 if (reg & CFGR_TMRTEST) ; 828 if (reg & CFGR_MRM_DIS) ; 829 if (reg & CFGR_MWI_DIS) ; 830 831 if (reg & CFGR_T64ADDR) ; 832 // panic("CFGR_T64ADDR is read only register!\n"); 833 834 if (reg & CFGR_PCI64_DET) 835 panic("CFGR_PCI64_DET is read only register!\n"); 836 837 if (reg & CFGR_DATA64_EN) ; 838 if (reg & CFGR_M64ADDR) ; 839 if (reg & CFGR_PHY_RST) ; 840 if (reg & CFGR_PHY_DIS) ; 841 842 if (reg & CFGR_EXTSTS_EN) 843 extstsEnable = true; 844 else 845 extstsEnable = false; 846 847 if (reg & CFGR_REQALG) ; 848 if (reg & CFGR_SB) ; 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) ; 855 break; 856 857 case MEAR: 858 // Clear writable bits 859 regs.mear &= MEAR_EEDO; 860 // Set appropriate writable bits 861 regs.mear |= reg & ~MEAR_EEDO; 862 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) 868 eepromKick(); 869 } 870 else { 871 eepromState = eepromStart; 872 regs.mear &= ~MEAR_EEDI; 873 } 874 875 eepromClk = reg & MEAR_EECLK; 876 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) ; 881 break; 882 883 case PTSCR: 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; 893 break; 894 895 case ISR: /* writing to the ISR has no effect */ 896 panic("ISR is a read only register!\n"); 897 898 case IMR: 899 regs.imr = reg; 900 devIntrChangeMask(); 901 break; 902 903 case IER: 904 regs.ier = reg; 905 break; 906 907 case IHR: 908 regs.ihr = reg; 909 /* not going to implement real interrupt holdoff */ 910 break; 911 912 case TXDP: 913 regs.txdp = (reg & 0xFFFFFFFC); 914 assert(txState == txIdle); 915 CTDD = false; 916 break; 917 918 case TXDP_HI: 919 regs.txdp_hi = reg; 920 break; 921 922 case TX_CFG: 923 regs.txcfg = reg; 924#if 0 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) { 930 /* 931 * this could easily be implemented, but considering 932 * the network is just a fake pipe, wouldn't make 933 * sense to do this 934 */ 935 } 936 937 if (reg & TX_CFG_BRST_DIS) ; 938#endif 939 940#if 0 941 /* we handle our own DMA, ignore the kernel's exhortations */ 942 if (reg & TX_CFG_MXDMA) ; 943#endif 944 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 949 950 break; 951 952 case GPIOR: 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 */ 959 break; 960 961 case RXDP: 962 regs.rxdp = reg; 963 CRDD = false; 964 break; 965 966 case RXDP_HI: 967 regs.rxdp_hi = reg; 968 break; 969 970 case RX_CFG: 971 regs.rxcfg = reg; 972#if 0 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) ; 979 980 /* we handle our own DMA, ignore what kernel says about it */ 981 if (reg & RX_CFG_MXDMA) ; 982 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)) ; 987#endif 988 break; 989 990 case PQCR: 991 /* there is no priority queueing used in the linux 2.6 driver */ 992 regs.pqcr = reg; 993 break; 994 995 case WCSR: 996 /* not going to implement wake on LAN */ 997 regs.wcsr = reg; 998 break; 999 1000 case PCR: 1001 /* not going to implement pause control */ 1002 regs.pcr = reg; 1003 break; 1004 1005 case RFCR: 1006 regs.rfcr = reg; 1007 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; 1015 1016#if 0 1017 if (reg & RFCR_APAT) 1018 panic("RFCR_APAT not implemented!\n"); 1019#endif 1020 if (reg & RFCR_UHEN) 1021 panic("Unicast hash filtering not used by drivers!\n"); 1022 1023 if (reg & RFCR_ULM) 1024 panic("RFCR_ULM not implemented!\n"); 1025 1026 break; 1027 1028 case RFDR: 1029 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 1030 switch (rfaddr) { 1031 case 0x000: 1032 rom.perfectMatch[0] = (uint8_t)reg; 1033 rom.perfectMatch[1] = (uint8_t)(reg >> 8); 1034 break; 1035 case 0x002: 1036 rom.perfectMatch[2] = (uint8_t)reg; 1037 rom.perfectMatch[3] = (uint8_t)(reg >> 8); 1038 break; 1039 case 0x004: 1040 rom.perfectMatch[4] = (uint8_t)reg; 1041 rom.perfectMatch[5] = (uint8_t)(reg >> 8); 1042 break; 1043 default: 1044 1045 if (rfaddr >= FHASH_ADDR && 1046 rfaddr < FHASH_ADDR + FHASH_SIZE) { 1047 1048 // Only word-aligned writes supported 1049 if (rfaddr % 2) 1050 panic("unaligned write to filter hash table!"); 1051 1052 rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 1053 rom.filterHash[rfaddr - FHASH_ADDR + 1] 1054 = (uint8_t)(reg >> 8); 1055 break; 1056 } 1057 panic("writing RFDR for something other than pattern matching\ 1058 or hashing! %#x\n", rfaddr); 1059 } 1060 1061 case BRAR: 1062 regs.brar = reg; 1063 break; 1064 1065 case BRDR: 1066 panic("the driver never uses BRDR, something is wrong!\n"); 1067 1068 case SRR: 1069 panic("SRR is read only register!\n"); 1070 1071 case MIBC: 1072 panic("the driver never uses MIBC, something is wrong!\n"); 1073 1074 case VRCR: 1075 regs.vrcr = reg; 1076 break; 1077 1078 case VTCR: 1079 regs.vtcr = reg; 1080 break; 1081 1082 case VDR: 1083 panic("the driver never uses VDR, something is wrong!\n"); 1084 1085 case CCSR: 1086 /* not going to implement clockrun stuff */ 1087 regs.ccsr = reg; 1088 break; 1089 1090 case TBICR: 1091 regs.tbicr = reg; 1092 if (reg & TBICR_MR_LOOPBACK) 1093 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 1094 1095 if (reg & TBICR_MR_AN_ENABLE) { 1096 regs.tanlpar = regs.tanar; 1097 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 1098 } 1099 1100#if 0 1101 if (reg & TBICR_MR_RESTART_AN) ; 1102#endif 1103 1104 break; 1105 1106 case TBISR: 1107 panic("TBISR is read only register!\n"); 1108 1109 case TANAR: 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); 1113 1114 // Pause capability unimplemented 1115#if 0 1116 if (reg & TANAR_PS2) ; 1117 if (reg & TANAR_PS1) ; 1118#endif 1119 1120 break; 1121 1122 case TANLPAR: 1123 panic("this should only be written to by the fake phy!\n"); 1124 1125 case TANER: 1126 panic("TANER is read only register!\n"); 1127 1128 case TESR: 1129 regs.tesr = reg; 1130 break; 1131 1132 default: 1133 panic("invalid register access daddr=%#x", daddr); 1134 } 1135 } else { 1136 panic("Invalid Request Size"); 1137 } 1138 pkt->makeAtomicResponse(); 1139 return pioDelay; 1140} 1141 1142void 1143NSGigE::devIntrPost(uint32_t interrupts) 1144{ 1145 if (interrupts & ISR_RESERVE) 1146 panic("Cannot set a reserved interrupt"); 1147 1148 if (interrupts & ISR_NOIMPL) 1149 warn("interrupt not implemented %#x\n", interrupts); 1150 1151 interrupts &= ISR_IMPL; 1152 regs.isr |= interrupts; 1153 1154 if (interrupts & regs.imr) { 1155 if (interrupts & ISR_SWI) { 1156 totalSwi++; 1157 } 1158 if (interrupts & ISR_RXIDLE) { 1159 totalRxIdle++; 1160 } 1161 if (interrupts & ISR_RXOK) { 1162 totalRxOk++; 1163 } 1164 if (interrupts & ISR_RXDESC) { 1165 totalRxDesc++; 1166 } 1167 if (interrupts & ISR_TXOK) { 1168 totalTxOk++; 1169 } 1170 if (interrupts & ISR_TXIDLE) { 1171 totalTxIdle++; 1172 } 1173 if (interrupts & ISR_TXDESC) { 1174 totalTxDesc++; 1175 } 1176 if (interrupts & ISR_RXORN) { 1177 totalRxOrn++; 1178 } 1179 } 1180 1181 DPRINTF(EthernetIntr, 1182 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 1183 interrupts, regs.isr, regs.imr); 1184 1185 if ((regs.isr & regs.imr)) { 1186 Tick when = curTick; 1187 if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 1188 when += intrDelay; 1189 cpuIntrPost(when); 1190 } 1191} 1192 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 1196 of expanding use. 1197*/ 1198void 1199NSGigE::devIntrClear(uint32_t interrupts) 1200{ 1201 if (interrupts & ISR_RESERVE) 1202 panic("Cannot clear a reserved interrupt"); 1203 1204 if (regs.isr & regs.imr & ISR_SWI) { 1205 postedSwi++; 1206 } 1207 if (regs.isr & regs.imr & ISR_RXIDLE) { 1208 postedRxIdle++; 1209 } 1210 if (regs.isr & regs.imr & ISR_RXOK) { 1211 postedRxOk++; 1212 } 1213 if (regs.isr & regs.imr & ISR_RXDESC) { 1214 postedRxDesc++; 1215 } 1216 if (regs.isr & regs.imr & ISR_TXOK) { 1217 postedTxOk++; 1218 } 1219 if (regs.isr & regs.imr & ISR_TXIDLE) { 1220 postedTxIdle++; 1221 } 1222 if (regs.isr & regs.imr & ISR_TXDESC) { 1223 postedTxDesc++; 1224 } 1225 if (regs.isr & regs.imr & ISR_RXORN) { 1226 postedRxOrn++; 1227 } 1228 1229 if (regs.isr & regs.imr & ISR_IMPL) 1230 postedInterrupts++; 1231 1232 interrupts &= ~ISR_NOIMPL; 1233 regs.isr &= ~interrupts; 1234 1235 DPRINTF(EthernetIntr, 1236 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 1237 interrupts, regs.isr, regs.imr); 1238 1239 if (!(regs.isr & regs.imr)) 1240 cpuIntrClear(); 1241} 1242 1243void 1244NSGigE::devIntrChangeMask() 1245{ 1246 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 1247 regs.isr, regs.imr, regs.isr & regs.imr); 1248 1249 if (regs.isr & regs.imr) 1250 cpuIntrPost(curTick); 1251 else 1252 cpuIntrClear(); 1253} 1254 1255void 1256NSGigE::cpuIntrPost(Tick when) 1257{ 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) 1263 /** 1264 * @todo this warning should be removed and the intrTick code should 1265 * be fixed. 1266 */ 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", 1271 intrTick); 1272 return; 1273 } 1274 1275 intrTick = when; 1276 if (intrTick < curTick) { 1277 debug_break(); 1278 intrTick = curTick; 1279 } 1280 1281 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 1282 intrTick); 1283 1284 if (intrEvent) 1285 intrEvent->squash(); 1286 intrEvent = new IntrEvent(this, intrTick, true); 1287} 1288 1289void 1290NSGigE::cpuInterrupt() 1291{ 1292 assert(intrTick == curTick); 1293 1294 // Whether or not there's a pending interrupt, we don't care about 1295 // it anymore 1296 intrEvent = 0; 1297 intrTick = 0; 1298 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"); 1303 } else { 1304 // Send interrupt 1305 cpuPendingIntr = true; 1306 1307 DPRINTF(EthernetIntr, "posting interrupt\n"); 1308 intrPost(); 1309 } 1310} 1311 1312void 1313NSGigE::cpuIntrClear() 1314{ 1315 if (!cpuPendingIntr) 1316 return; 1317 1318 if (intrEvent) { 1319 intrEvent->squash(); 1320 intrEvent = 0; 1321 } 1322 1323 intrTick = 0; 1324 1325 cpuPendingIntr = false; 1326 1327 DPRINTF(EthernetIntr, "clearing interrupt\n"); 1328 intrClear(); 1329} 1330 1331bool 1332NSGigE::cpuIntrPending() const 1333{ return cpuPendingIntr; } 1334 1335void 1336NSGigE::txReset() 1337{ 1338 1339 DPRINTF(Ethernet, "transmit reset\n"); 1340 1341 CTDD = false; 1342 txEnable = false;; 1343 txFragPtr = 0; 1344 assert(txDescCnt == 0); 1345 txFifo.clear(); 1346 txState = txIdle; 1347 assert(txDmaState == dmaIdle); 1348} 1349 1350void 1351NSGigE::rxReset() 1352{ 1353 DPRINTF(Ethernet, "receive reset\n"); 1354 1355 CRDD = false; 1356 assert(rxPktBytes == 0); 1357 rxEnable = false; 1358 rxFragPtr = 0; 1359 assert(rxDescCnt == 0); 1360 assert(rxDmaState == dmaIdle); 1361 rxFifo.clear(); 1362 rxState = rxIdle; 1363} 1364 1365void 1366NSGigE::regsReset() 1367{ 1368 memset(®s, 0, sizeof(regs)); 1369 regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 1370 regs.mear = 0x12; 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; 1379 1380 extstsEnable = false; 1381 acceptBroadcast = false; 1382 acceptMulticast = false; 1383 acceptUnicast = false; 1384 acceptPerfect = false; 1385 acceptArp = false; 1386} 1387 1388bool 1389NSGigE::doRxDmaRead() 1390{ 1391 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1392 rxDmaState = dmaReading; 1393 1394 if (dmaPending() || getState() != Running) 1395 rxDmaState = dmaReadWaiting; 1396 else 1397 dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 1398 1399 return true; 1400} 1401 1402void 1403NSGigE::rxDmaReadDone() 1404{ 1405 assert(rxDmaState == dmaReading); 1406 rxDmaState = dmaIdle; 1407 1408 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1409 rxDmaAddr, rxDmaLen); 1410 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1411 1412 // If the transmit state machine has a pending DMA, let it go first 1413 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1414 txKick(); 1415 1416 rxKick(); 1417} 1418 1419bool 1420NSGigE::doRxDmaWrite() 1421{ 1422 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1423 rxDmaState = dmaWriting; 1424 1425 if (dmaPending() || getState() != Running) 1426 rxDmaState = dmaWriteWaiting; 1427 else 1428 dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 1429 return true; 1430} 1431 1432void 1433NSGigE::rxDmaWriteDone() 1434{ 1435 assert(rxDmaState == dmaWriting); 1436 rxDmaState = dmaIdle; 1437 1438 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1439 rxDmaAddr, rxDmaLen); 1440 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1441 1442 // If the transmit state machine has a pending DMA, let it go first 1443 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1444 txKick(); 1445 1446 rxKick(); 1447} 1448 1449void 1450NSGigE::rxKick() 1451{ 1452 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1453 1454 DPRINTF(EthernetSM, 1455 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 1456 NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 1457 1458 Addr link, bufptr; 1459 uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 1460 uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1461 1462 next: 1463 if (clock) { 1464 if (rxKickTick > curTick) { 1465 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1466 rxKickTick); 1467 1468 goto exit; 1469 } 1470 1471 // Go to the next state machine clock tick. 1472 rxKickTick = curTick + cycles(1); 1473 } 1474 1475 switch(rxDmaState) { 1476 case dmaReadWaiting: 1477 if (doRxDmaRead()) 1478 goto exit; 1479 break; 1480 case dmaWriteWaiting: 1481 if (doRxDmaWrite()) 1482 goto exit; 1483 break; 1484 default: 1485 break; 1486 } 1487 1488 link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 1489 bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 1490 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. 1498 switch (rxState) { 1499 case rxIdle: 1500 if (!rxEnable) { 1501 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1502 goto exit; 1503 } 1504 1505 if (CRDD) { 1506 rxState = rxDescRefr; 1507 1508 rxDmaAddr = regs.rxdp & 0x3fffffff; 1509 rxDmaData = 1510 is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 1511 rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1512 rxDmaFree = dmaDescFree; 1513 1514 descDmaReads++; 1515 descDmaRdBytes += rxDmaLen; 1516 1517 if (doRxDmaRead()) 1518 goto exit; 1519 } else { 1520 rxState = rxDescRead; 1521 1522 rxDmaAddr = regs.rxdp & 0x3fffffff; 1523 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1524 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1525 rxDmaFree = dmaDescFree; 1526 1527 descDmaReads++; 1528 descDmaRdBytes += rxDmaLen; 1529 1530 if (doRxDmaRead()) 1531 goto exit; 1532 } 1533 break; 1534 1535 case rxDescRefr: 1536 if (rxDmaState != dmaIdle) 1537 goto exit; 1538 1539 rxState = rxAdvance; 1540 break; 1541 1542 case rxDescRead: 1543 if (rxDmaState != dmaIdle) 1544 goto exit; 1545 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); 1551 1552 if (cmdsts & CMDSTS_OWN) { 1553 devIntrPost(ISR_RXIDLE); 1554 rxState = rxIdle; 1555 goto exit; 1556 } else { 1557 rxState = rxFifoBlock; 1558 rxFragPtr = bufptr; 1559 rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1560 } 1561 break; 1562 1563 case rxFifoBlock: 1564 if (!rxPacket) { 1565 /** 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. 1569 */ 1570 if (rxFifo.empty()) 1571 goto exit; 1572 1573 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1574 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; 1579 1580#if TRACING_ON 1581 if (DTRACE(Ethernet)) { 1582 IpPtr ip(rxPacket); 1583 if (ip) { 1584 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1585 TcpPtr tcp(ip); 1586 if (tcp) { 1587 DPRINTF(Ethernet, 1588 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1589 tcp->sport(), tcp->dport(), tcp->seq(), 1590 tcp->ack()); 1591 } 1592 } 1593 } 1594#endif 1595 1596 // sanity check - i think the driver behaves like this 1597 assert(rxDescCnt >= rxPktBytes); 1598 rxFifo.pop(); 1599 } 1600 1601 1602 // dont' need the && rxDescCnt > 0 if driver sanity check 1603 // above holds 1604 if (rxPktBytes > 0) { 1605 rxState = rxFragWrite; 1606 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1607 // check holds 1608 rxXferLen = rxPktBytes; 1609 1610 rxDmaAddr = rxFragPtr & 0x3fffffff; 1611 rxDmaData = rxPacketBufPtr; 1612 rxDmaLen = rxXferLen; 1613 rxDmaFree = dmaDataFree; 1614 1615 if (doRxDmaWrite()) 1616 goto exit; 1617 1618 } else { 1619 rxState = rxDescWrite; 1620 1621 //if (rxPktBytes == 0) { /* packet is done */ 1622 assert(rxPktBytes == 0); 1623 DPRINTF(EthernetSM, "done with receiving packet\n"); 1624 1625 cmdsts |= CMDSTS_OWN; 1626 cmdsts &= ~CMDSTS_MORE; 1627 cmdsts |= CMDSTS_OK; 1628 cmdsts &= 0xffff0000; 1629 cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1630 1631#if 0 1632 /* 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 1638 */ 1639 if (rxFilterEnable) { 1640 cmdsts &= ~CMDSTS_DEST_MASK; 1641 const EthAddr &dst = rxFifoFront()->dst(); 1642 if (dst->unicast()) 1643 cmdsts |= CMDSTS_DEST_SELF; 1644 if (dst->multicast()) 1645 cmdsts |= CMDSTS_DEST_MULTI; 1646 if (dst->broadcast()) 1647 cmdsts |= CMDSTS_DEST_MASK; 1648 } 1649#endif 1650 1651 IpPtr ip(rxPacket); 1652 if (extstsEnable && ip) { 1653 extsts |= EXTSTS_IPPKT; 1654 rxIpChecksums++; 1655 if (cksum(ip) != 0) { 1656 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1657 extsts |= EXTSTS_IPERR; 1658 } 1659 TcpPtr tcp(ip); 1660 UdpPtr udp(ip); 1661 if (tcp) { 1662 extsts |= EXTSTS_TCPPKT; 1663 rxTcpChecksums++; 1664 if (cksum(tcp) != 0) { 1665 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1666 extsts |= EXTSTS_TCPERR; 1667 1668 } 1669 } else if (udp) { 1670 extsts |= EXTSTS_UDPPKT; 1671 rxUdpChecksums++; 1672 if (cksum(udp) != 0) { 1673 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1674 extsts |= EXTSTS_UDPERR; 1675 } 1676 } 1677 } 1678 rxPacket = 0; 1679 1680 /* 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. 1685 */ 1686 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); 1693 1694 rxDmaAddr = regs.rxdp & 0x3fffffff; 1695 rxDmaData = &cmdsts; 1696 if (is64bit) { 1697 rxDmaAddr += offsetof(ns_desc64, cmdsts); 1698 rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 1699 } else { 1700 rxDmaAddr += offsetof(ns_desc32, cmdsts); 1701 rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 1702 } 1703 rxDmaFree = dmaDescFree; 1704 1705 descDmaWrites++; 1706 descDmaWrBytes += rxDmaLen; 1707 1708 if (doRxDmaWrite()) 1709 goto exit; 1710 } 1711 break; 1712 1713 case rxFragWrite: 1714 if (rxDmaState != dmaIdle) 1715 goto exit; 1716 1717 rxPacketBufPtr += rxXferLen; 1718 rxFragPtr += rxXferLen; 1719 rxPktBytes -= rxXferLen; 1720 1721 rxState = rxFifoBlock; 1722 break; 1723 1724 case rxDescWrite: 1725 if (rxDmaState != dmaIdle) 1726 goto exit; 1727 1728 assert(cmdsts & CMDSTS_OWN); 1729 1730 assert(rxPacket == 0); 1731 devIntrPost(ISR_RXOK); 1732 1733 if (cmdsts & CMDSTS_INTR) 1734 devIntrPost(ISR_RXDESC); 1735 1736 if (!rxEnable) { 1737 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1738 rxState = rxIdle; 1739 goto exit; 1740 } else 1741 rxState = rxAdvance; 1742 break; 1743 1744 case rxAdvance: 1745 if (link == 0) { 1746 devIntrPost(ISR_RXIDLE); 1747 rxState = rxIdle; 1748 CRDD = true; 1749 goto exit; 1750 } else { 1751 if (rxDmaState != dmaIdle) 1752 goto exit; 1753 rxState = rxDescRead; 1754 regs.rxdp = link; 1755 CRDD = false; 1756 1757 rxDmaAddr = regs.rxdp & 0x3fffffff; 1758 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1759 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1760 rxDmaFree = dmaDescFree; 1761 1762 if (doRxDmaRead()) 1763 goto exit; 1764 } 1765 break; 1766 1767 default: 1768 panic("Invalid rxState!"); 1769 } 1770 1771 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1772 NsRxStateStrings[rxState]); 1773 goto next; 1774 1775 exit: 1776 /** 1777 * @todo do we want to schedule a future kick? 1778 */ 1779 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1780 NsRxStateStrings[rxState]); 1781 1782 if (clock && !rxKickEvent.scheduled()) 1783 rxKickEvent.schedule(rxKickTick); 1784} 1785 1786void 1787NSGigE::transmit() 1788{ 1789 if (txFifo.empty()) { 1790 DPRINTF(Ethernet, "nothing to transmit\n"); 1791 return; 1792 } 1793 1794 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1795 txFifo.size()); 1796 if (interface->sendPacket(txFifo.front())) { 1797#if TRACING_ON 1798 if (DTRACE(Ethernet)) { 1799 IpPtr ip(txFifo.front()); 1800 if (ip) { 1801 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1802 TcpPtr tcp(ip); 1803 if (tcp) { 1804 DPRINTF(Ethernet, 1805 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1806 tcp->sport(), tcp->dport(), tcp->seq(), 1807 tcp->ack()); 1808 } 1809 } 1810 } 1811#endif 1812 1813 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1814 txBytes += txFifo.front()->length; 1815 txPackets++; 1816 1817 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1818 txFifo.avail()); 1819 txFifo.pop(); 1820 1821 /* 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. 1827 */ 1828 devIntrPost(ISR_TXOK); 1829 } 1830 1831 if (!txFifo.empty() && !txEvent.scheduled()) { 1832 DPRINTF(Ethernet, "reschedule transmit\n"); 1833 txEvent.schedule(curTick + retryTime); 1834 } 1835} 1836 1837bool 1838NSGigE::doTxDmaRead() 1839{ 1840 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1841 txDmaState = dmaReading; 1842 1843 if (dmaPending() || getState() != Running) 1844 txDmaState = dmaReadWaiting; 1845 else 1846 dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 1847 1848 return true; 1849} 1850 1851void 1852NSGigE::txDmaReadDone() 1853{ 1854 assert(txDmaState == dmaReading); 1855 txDmaState = dmaIdle; 1856 1857 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1858 txDmaAddr, txDmaLen); 1859 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1860 1861 // If the receive state machine has a pending DMA, let it go first 1862 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1863 rxKick(); 1864 1865 txKick(); 1866} 1867 1868bool 1869NSGigE::doTxDmaWrite() 1870{ 1871 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1872 txDmaState = dmaWriting; 1873 1874 if (dmaPending() || getState() != Running) 1875 txDmaState = dmaWriteWaiting; 1876 else 1877 dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1878 return true; 1879} 1880 1881void 1882NSGigE::txDmaWriteDone() 1883{ 1884 assert(txDmaState == dmaWriting); 1885 txDmaState = dmaIdle; 1886 1887 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1888 txDmaAddr, txDmaLen); 1889 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1890 1891 // If the receive state machine has a pending DMA, let it go first 1892 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1893 rxKick(); 1894 1895 txKick(); 1896} 1897 1898void 1899NSGigE::txKick() 1900{ 1901 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1902 1903 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 1904 NsTxStateStrings[txState], is64bit ? 64 : 32); 1905 1906 Addr link, bufptr; 1907 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 1908 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1909 1910 next: 1911 if (clock) { 1912 if (txKickTick > curTick) { 1913 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1914 txKickTick); 1915 goto exit; 1916 } 1917 1918 // Go to the next state machine clock tick. 1919 txKickTick = curTick + cycles(1); 1920 } 1921 1922 switch(txDmaState) { 1923 case dmaReadWaiting: 1924 if (doTxDmaRead()) 1925 goto exit; 1926 break; 1927 case dmaWriteWaiting: 1928 if (doTxDmaWrite()) 1929 goto exit; 1930 break; 1931 default: 1932 break; 1933 } 1934 1935 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 1936 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1937 switch (txState) { 1938 case txIdle: 1939 if (!txEnable) { 1940 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1941 goto exit; 1942 } 1943 1944 if (CTDD) { 1945 txState = txDescRefr; 1946 1947 txDmaAddr = regs.txdp & 0x3fffffff; 1948 txDmaData = 1949 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 1950 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1951 txDmaFree = dmaDescFree; 1952 1953 descDmaReads++; 1954 descDmaRdBytes += txDmaLen; 1955 1956 if (doTxDmaRead()) 1957 goto exit; 1958 1959 } else { 1960 txState = txDescRead; 1961 1962 txDmaAddr = regs.txdp & 0x3fffffff; 1963 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 1964 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1965 txDmaFree = dmaDescFree; 1966 1967 descDmaReads++; 1968 descDmaRdBytes += txDmaLen; 1969 1970 if (doTxDmaRead()) 1971 goto exit; 1972 } 1973 break; 1974 1975 case txDescRefr: 1976 if (txDmaState != dmaIdle) 1977 goto exit; 1978 1979 txState = txAdvance; 1980 break; 1981 1982 case txDescRead: 1983 if (txDmaState != dmaIdle) 1984 goto exit; 1985 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); 1991 1992 if (cmdsts & CMDSTS_OWN) { 1993 txState = txFifoBlock; 1994 txFragPtr = bufptr; 1995 txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1996 } else { 1997 devIntrPost(ISR_TXIDLE); 1998 txState = txIdle; 1999 goto exit; 2000 } 2001 break; 2002 2003 case txFifoBlock: 2004 if (!txPacket) { 2005 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2006 txPacket = new EthPacketData(16384); 2007 txPacketBufPtr = txPacket->data; 2008 } 2009 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; 2015 2016 cmdsts &= ~CMDSTS_OWN; 2017 2018 txDmaAddr = regs.txdp & 0x3fffffff; 2019 txDmaData = &cmdsts; 2020 if (is64bit) { 2021 txDmaAddr += offsetof(ns_desc64, cmdsts); 2022 txDmaLen = sizeof(txDesc64.cmdsts); 2023 } else { 2024 txDmaAddr += offsetof(ns_desc32, cmdsts); 2025 txDmaLen = sizeof(txDesc32.cmdsts); 2026 } 2027 txDmaFree = dmaDescFree; 2028 2029 if (doTxDmaWrite()) 2030 goto exit; 2031 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) { 2036 IpPtr ip(txPacket); 2037 if (extsts & EXTSTS_UDPPKT) { 2038 UdpPtr udp(ip); 2039 udp->sum(0); 2040 udp->sum(cksum(udp)); 2041 txUdpChecksums++; 2042 } else if (extsts & EXTSTS_TCPPKT) { 2043 TcpPtr tcp(ip); 2044 tcp->sum(0); 2045 tcp->sum(cksum(tcp)); 2046 txTcpChecksums++; 2047 } 2048 if (extsts & EXTSTS_IPPKT) { 2049 ip->sum(0); 2050 ip->sum(cksum(ip)); 2051 txIpChecksums++; 2052 } 2053 } 2054 2055 txPacket->length = txPacketBufPtr - txPacket->data; 2056 // this is just because the receive can't handle a 2057 // packet bigger want to make sure 2058 if (txPacket->length > 1514) 2059 panic("transmit packet too large, %s > 1514\n", 2060 txPacket->length); 2061 2062#ifndef NDEBUG 2063 bool success = 2064#endif 2065 txFifo.push(txPacket); 2066 assert(success); 2067 2068 /* 2069 * this following section is not tqo spec, but 2070 * functionally shouldn't be any different. normally, 2071 * the chip will wait til the transmit has occurred 2072 * before writing back the descriptor because it has 2073 * to wait to see that it was successfully transmitted 2074 * to decide whether to set CMDSTS_OK or not. 2075 * however, in the simulator since it is always 2076 * successfully transmitted, and writing it exactly to 2077 * spec would complicate the code, we just do it here 2078 */ 2079 2080 cmdsts &= ~CMDSTS_OWN; 2081 cmdsts |= CMDSTS_OK; 2082 2083 DPRINTF(EthernetDesc, 2084 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2085 cmdsts, extsts); 2086 2087 txDmaFree = dmaDescFree; 2088 txDmaAddr = regs.txdp & 0x3fffffff; 2089 txDmaData = &cmdsts; 2090 if (is64bit) { 2091 txDmaAddr += offsetof(ns_desc64, cmdsts); 2092 txDmaLen = 2093 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 2094 } else { 2095 txDmaAddr += offsetof(ns_desc32, cmdsts); 2096 txDmaLen = 2097 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 2098 } 2099 2100 descDmaWrites++; 2101 descDmaWrBytes += txDmaLen; 2102 2103 transmit(); 2104 txPacket = 0; 2105 2106 if (!txEnable) { 2107 DPRINTF(EthernetSM, "halting TX state machine\n"); 2108 txState = txIdle; 2109 goto exit; 2110 } else 2111 txState = txAdvance; 2112 2113 if (doTxDmaWrite()) 2114 goto exit; 2115 } 2116 } else { 2117 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2118 if (!txFifo.full()) { 2119 txState = txFragRead; 2120 2121 /* 2122 * The number of bytes transferred is either whatever 2123 * is left in the descriptor (txDescCnt), or if there 2124 * is not enough room in the fifo, just whatever room 2125 * is left in the fifo 2126 */ 2127 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2128 2129 txDmaAddr = txFragPtr & 0x3fffffff; 2130 txDmaData = txPacketBufPtr; 2131 txDmaLen = txXferLen; 2132 txDmaFree = dmaDataFree; 2133 2134 if (doTxDmaRead()) 2135 goto exit; 2136 } else { 2137 txState = txFifoBlock; 2138 transmit(); 2139 2140 goto exit; 2141 } 2142 2143 } 2144 break; 2145 2146 case txFragRead: 2147 if (txDmaState != dmaIdle) 2148 goto exit; 2149 2150 txPacketBufPtr += txXferLen; 2151 txFragPtr += txXferLen; 2152 txDescCnt -= txXferLen; 2153 txFifo.reserve(txXferLen); 2154 2155 txState = txFifoBlock; 2156 break; 2157 2158 case txDescWrite: 2159 if (txDmaState != dmaIdle) 2160 goto exit; 2161 2162 if (cmdsts & CMDSTS_INTR) 2163 devIntrPost(ISR_TXDESC); 2164 2165 if (!txEnable) { 2166 DPRINTF(EthernetSM, "halting TX state machine\n"); 2167 txState = txIdle; 2168 goto exit; 2169 } else 2170 txState = txAdvance; 2171 break; 2172 2173 case txAdvance: 2174 if (link == 0) { 2175 devIntrPost(ISR_TXIDLE); 2176 txState = txIdle; 2177 goto exit; 2178 } else { 2179 if (txDmaState != dmaIdle) 2180 goto exit; 2181 txState = txDescRead; 2182 regs.txdp = link; 2183 CTDD = false; 2184 2185 txDmaAddr = link & 0x3fffffff; 2186 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 2187 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 2188 txDmaFree = dmaDescFree; 2189 2190 if (doTxDmaRead()) 2191 goto exit; 2192 } 2193 break; 2194 2195 default: 2196 panic("invalid state"); 2197 } 2198 2199 DPRINTF(EthernetSM, "entering next txState=%s\n", 2200 NsTxStateStrings[txState]); 2201 goto next; 2202 2203 exit: 2204 /** 2205 * @todo do we want to schedule a future kick? 2206 */ 2207 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2208 NsTxStateStrings[txState]); 2209 2210 if (clock && !txKickEvent.scheduled()) 2211 txKickEvent.schedule(txKickTick); 2212} 2213 2214/** 2215 * Advance the EEPROM state machine 2216 * Called on rising edge of EEPROM clock bit in MEAR 2217 */ 2218void 2219NSGigE::eepromKick() 2220{ 2221 switch (eepromState) { 2222 2223 case eepromStart: 2224 2225 // Wait for start bit 2226 if (regs.mear & MEAR_EEDI) { 2227 // Set up to get 2 opcode bits 2228 eepromState = eepromGetOpcode; 2229 eepromBitsToRx = 2; 2230 eepromOpcode = 0; 2231 } 2232 break; 2233 2234 case eepromGetOpcode: 2235 eepromOpcode <<= 1; 2236 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 2237 --eepromBitsToRx; 2238 2239 // Done getting opcode 2240 if (eepromBitsToRx == 0) { 2241 if (eepromOpcode != EEPROM_READ) 2242 panic("only EEPROM reads are implemented!"); 2243 2244 // Set up to get address 2245 eepromState = eepromGetAddress; 2246 eepromBitsToRx = 6; 2247 eepromAddress = 0; 2248 } 2249 break; 2250 2251 case eepromGetAddress: 2252 eepromAddress <<= 1; 2253 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 2254 --eepromBitsToRx; 2255 2256 // Done getting address 2257 if (eepromBitsToRx == 0) { 2258 2259 if (eepromAddress >= EEPROM_SIZE) 2260 panic("EEPROM read access out of range!"); 2261 2262 switch (eepromAddress) { 2263 2264 case EEPROM_PMATCH2_ADDR: 2265 eepromData = rom.perfectMatch[5]; 2266 eepromData <<= 8; 2267 eepromData += rom.perfectMatch[4]; 2268 break; 2269 2270 case EEPROM_PMATCH1_ADDR: 2271 eepromData = rom.perfectMatch[3]; 2272 eepromData <<= 8; 2273 eepromData += rom.perfectMatch[2]; 2274 break; 2275 2276 case EEPROM_PMATCH0_ADDR: 2277 eepromData = rom.perfectMatch[1]; 2278 eepromData <<= 8; 2279 eepromData += rom.perfectMatch[0]; 2280 break; 2281 2282 default: 2283 panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 2284 } 2285 // Set up to read data 2286 eepromState = eepromRead; 2287 eepromBitsToRx = 16; 2288 2289 // Clear data in bit 2290 regs.mear &= ~MEAR_EEDI; 2291 } 2292 break; 2293 2294 case eepromRead: 2295 // Clear Data Out bit 2296 regs.mear &= ~MEAR_EEDO; 2297 // Set bit to value of current EEPROM bit 2298 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 2299 2300 eepromData <<= 1; 2301 --eepromBitsToRx; 2302 2303 // All done 2304 if (eepromBitsToRx == 0) { 2305 eepromState = eepromStart; 2306 } 2307 break; 2308 2309 default: 2310 panic("invalid EEPROM state"); 2311 } 2312 2313} 2314 2315void 2316NSGigE::transferDone() 2317{ 2318 if (txFifo.empty()) { 2319 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2320 return; 2321 } 2322 2323 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2324 2325 txEvent.reschedule(curTick + cycles(1), true); 2326} 2327 2328bool 2329NSGigE::rxFilter(const EthPacketPtr &packet) 2330{ 2331 EthPtr eth = packet; 2332 bool drop = true; 2333 string type; 2334 2335 const EthAddr &dst = eth->dst(); 2336 if (dst.unicast()) { 2337 // If we're accepting all unicast addresses 2338 if (acceptUnicast) 2339 drop = false; 2340 2341 // If we make a perfect match 2342 if (acceptPerfect && dst == rom.perfectMatch) 2343 drop = false; 2344 2345 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2346 drop = false; 2347 2348 } else if (dst.broadcast()) { 2349 // if we're accepting broadcasts 2350 if (acceptBroadcast) 2351 drop = false; 2352 2353 } else if (dst.multicast()) { 2354 // if we're accepting all multicasts 2355 if (acceptMulticast) 2356 drop = false; 2357 2358 // Multicast hashing faked - all packets accepted 2359 if (multicastHashEnable) 2360 drop = false; 2361 } 2362 2363 if (drop) { 2364 DPRINTF(Ethernet, "rxFilter drop\n"); 2365 DDUMP(EthernetData, packet->data, packet->length); 2366 } 2367 2368 return drop; 2369} 2370 2371bool 2372NSGigE::recvPacket(EthPacketPtr packet) 2373{ 2374 rxBytes += packet->length; 2375 rxPackets++; 2376 2377 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2378 rxFifo.avail()); 2379 2380 if (!rxEnable) { 2381 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2382 return true; 2383 } 2384 2385 if (!rxFilterEnable) { 2386 DPRINTF(Ethernet, 2387 "receive packet filtering disabled . . . packet dropped\n"); 2388 return true; 2389 } 2390 2391 if (rxFilter(packet)) { 2392 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2393 return true; 2394 } 2395 2396 if (rxFifo.avail() < packet->length) { 2397#if TRACING_ON 2398 IpPtr ip(packet); 2399 TcpPtr tcp(ip); 2400 if (ip) { 2401 DPRINTF(Ethernet, 2402 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2403 ip->id()); 2404 if (tcp) { 2405 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2406 } 2407 } 2408#endif 2409 droppedPackets++; 2410 devIntrPost(ISR_RXORN); 2411 return false; 2412 } 2413 2414 rxFifo.push(packet); 2415 2416 rxKick(); 2417 return true; 2418} 2419 2420 2421void 2422NSGigE::resume() 2423{ 2424 SimObject::resume(); 2425 2426 // During drain we could have left the state machines in a waiting state and 2427 // they wouldn't get out until some other event occured to kick them. 2428 // This way they'll get out immediately 2429 txKick(); 2430 rxKick(); 2431} 2432 2433 2434//===================================================================== 2435// 2436// 2437void 2438NSGigE::serialize(ostream &os) 2439{ 2440 // Serialize the PciDev base class 2441 PciDev::serialize(os); 2442 2443 /* 2444 * Finalize any DMA events now. 2445 */ 2446 // @todo will mem system save pending dma? 2447 2448 /* 2449 * Serialize the device registers 2450 */ 2451 SERIALIZE_SCALAR(regs.command); 2452 SERIALIZE_SCALAR(regs.config); 2453 SERIALIZE_SCALAR(regs.mear); 2454 SERIALIZE_SCALAR(regs.ptscr); 2455 SERIALIZE_SCALAR(regs.isr); 2456 SERIALIZE_SCALAR(regs.imr); 2457 SERIALIZE_SCALAR(regs.ier); 2458 SERIALIZE_SCALAR(regs.ihr); 2459 SERIALIZE_SCALAR(regs.txdp); 2460 SERIALIZE_SCALAR(regs.txdp_hi); 2461 SERIALIZE_SCALAR(regs.txcfg); 2462 SERIALIZE_SCALAR(regs.gpior); 2463 SERIALIZE_SCALAR(regs.rxdp); 2464 SERIALIZE_SCALAR(regs.rxdp_hi); 2465 SERIALIZE_SCALAR(regs.rxcfg); 2466 SERIALIZE_SCALAR(regs.pqcr); 2467 SERIALIZE_SCALAR(regs.wcsr); 2468 SERIALIZE_SCALAR(regs.pcr); 2469 SERIALIZE_SCALAR(regs.rfcr); 2470 SERIALIZE_SCALAR(regs.rfdr); 2471 SERIALIZE_SCALAR(regs.brar); 2472 SERIALIZE_SCALAR(regs.brdr); 2473 SERIALIZE_SCALAR(regs.srr); 2474 SERIALIZE_SCALAR(regs.mibc); 2475 SERIALIZE_SCALAR(regs.vrcr); 2476 SERIALIZE_SCALAR(regs.vtcr); 2477 SERIALIZE_SCALAR(regs.vdr); 2478 SERIALIZE_SCALAR(regs.ccsr); 2479 SERIALIZE_SCALAR(regs.tbicr); 2480 SERIALIZE_SCALAR(regs.tbisr); 2481 SERIALIZE_SCALAR(regs.tanar); 2482 SERIALIZE_SCALAR(regs.tanlpar); 2483 SERIALIZE_SCALAR(regs.taner); 2484 SERIALIZE_SCALAR(regs.tesr); 2485 2486 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2487 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2488 2489 SERIALIZE_SCALAR(ioEnable); 2490 2491 /* 2492 * Serialize the data Fifos 2493 */ 2494 rxFifo.serialize("rxFifo", os); 2495 txFifo.serialize("txFifo", os); 2496 2497 /* 2498 * Serialize the various helper variables 2499 */ 2500 bool txPacketExists = txPacket; 2501 SERIALIZE_SCALAR(txPacketExists); 2502 if (txPacketExists) { 2503 txPacket->length = txPacketBufPtr - txPacket->data; 2504 txPacket->serialize("txPacket", os); 2505 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2506 SERIALIZE_SCALAR(txPktBufPtr); 2507 } 2508 2509 bool rxPacketExists = rxPacket; 2510 SERIALIZE_SCALAR(rxPacketExists); 2511 if (rxPacketExists) { 2512 rxPacket->serialize("rxPacket", os); 2513 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2514 SERIALIZE_SCALAR(rxPktBufPtr); 2515 } 2516 2517 SERIALIZE_SCALAR(txXferLen); 2518 SERIALIZE_SCALAR(rxXferLen); 2519 2520 /* 2521 * Serialize Cached Descriptors 2522 */ 2523 SERIALIZE_SCALAR(rxDesc64.link); 2524 SERIALIZE_SCALAR(rxDesc64.bufptr); 2525 SERIALIZE_SCALAR(rxDesc64.cmdsts); 2526 SERIALIZE_SCALAR(rxDesc64.extsts); 2527 SERIALIZE_SCALAR(txDesc64.link); 2528 SERIALIZE_SCALAR(txDesc64.bufptr); 2529 SERIALIZE_SCALAR(txDesc64.cmdsts); 2530 SERIALIZE_SCALAR(txDesc64.extsts); 2531 SERIALIZE_SCALAR(rxDesc32.link); 2532 SERIALIZE_SCALAR(rxDesc32.bufptr); 2533 SERIALIZE_SCALAR(rxDesc32.cmdsts); 2534 SERIALIZE_SCALAR(rxDesc32.extsts); 2535 SERIALIZE_SCALAR(txDesc32.link); 2536 SERIALIZE_SCALAR(txDesc32.bufptr); 2537 SERIALIZE_SCALAR(txDesc32.cmdsts); 2538 SERIALIZE_SCALAR(txDesc32.extsts); 2539 SERIALIZE_SCALAR(extstsEnable); 2540 2541 /* 2542 * Serialize tx state machine 2543 */ 2544 int txState = this->txState; 2545 SERIALIZE_SCALAR(txState); 2546 SERIALIZE_SCALAR(txEnable); 2547 SERIALIZE_SCALAR(CTDD); 2548 SERIALIZE_SCALAR(txFragPtr); 2549 SERIALIZE_SCALAR(txDescCnt); 2550 int txDmaState = this->txDmaState; 2551 SERIALIZE_SCALAR(txDmaState); 2552 SERIALIZE_SCALAR(txKickTick); 2553 2554 /* 2555 * Serialize rx state machine 2556 */ 2557 int rxState = this->rxState; 2558 SERIALIZE_SCALAR(rxState); 2559 SERIALIZE_SCALAR(rxEnable); 2560 SERIALIZE_SCALAR(CRDD); 2561 SERIALIZE_SCALAR(rxPktBytes); 2562 SERIALIZE_SCALAR(rxFragPtr); 2563 SERIALIZE_SCALAR(rxDescCnt); 2564 int rxDmaState = this->rxDmaState; 2565 SERIALIZE_SCALAR(rxDmaState); 2566 SERIALIZE_SCALAR(rxKickTick); 2567 2568 /* 2569 * Serialize EEPROM state machine 2570 */ 2571 int eepromState = this->eepromState; 2572 SERIALIZE_SCALAR(eepromState); 2573 SERIALIZE_SCALAR(eepromClk); 2574 SERIALIZE_SCALAR(eepromBitsToRx); 2575 SERIALIZE_SCALAR(eepromOpcode); 2576 SERIALIZE_SCALAR(eepromAddress); 2577 SERIALIZE_SCALAR(eepromData); 2578 2579 /* 2580 * If there's a pending transmit, store the time so we can 2581 * reschedule it later 2582 */ 2583 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2584 SERIALIZE_SCALAR(transmitTick); 2585 2586 /* 2587 * receive address filter settings 2588 */ 2589 SERIALIZE_SCALAR(rxFilterEnable); 2590 SERIALIZE_SCALAR(acceptBroadcast); 2591 SERIALIZE_SCALAR(acceptMulticast); 2592 SERIALIZE_SCALAR(acceptUnicast); 2593 SERIALIZE_SCALAR(acceptPerfect); 2594 SERIALIZE_SCALAR(acceptArp); 2595 SERIALIZE_SCALAR(multicastHashEnable); 2596 2597 /* 2598 * Keep track of pending interrupt status. 2599 */ 2600 SERIALIZE_SCALAR(intrTick); 2601 SERIALIZE_SCALAR(cpuPendingIntr); 2602 Tick intrEventTick = 0; 2603 if (intrEvent) 2604 intrEventTick = intrEvent->when(); 2605 SERIALIZE_SCALAR(intrEventTick); 2606 2607} 2608 2609void 2610NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2611{ 2612 // Unserialize the PciDev base class 2613 PciDev::unserialize(cp, section); 2614 2615 UNSERIALIZE_SCALAR(regs.command); 2616 UNSERIALIZE_SCALAR(regs.config); 2617 UNSERIALIZE_SCALAR(regs.mear); 2618 UNSERIALIZE_SCALAR(regs.ptscr); 2619 UNSERIALIZE_SCALAR(regs.isr); 2620 UNSERIALIZE_SCALAR(regs.imr); 2621 UNSERIALIZE_SCALAR(regs.ier); 2622 UNSERIALIZE_SCALAR(regs.ihr); 2623 UNSERIALIZE_SCALAR(regs.txdp); 2624 UNSERIALIZE_SCALAR(regs.txdp_hi); 2625 UNSERIALIZE_SCALAR(regs.txcfg); 2626 UNSERIALIZE_SCALAR(regs.gpior); 2627 UNSERIALIZE_SCALAR(regs.rxdp); 2628 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2629 UNSERIALIZE_SCALAR(regs.rxcfg); 2630 UNSERIALIZE_SCALAR(regs.pqcr); 2631 UNSERIALIZE_SCALAR(regs.wcsr); 2632 UNSERIALIZE_SCALAR(regs.pcr); 2633 UNSERIALIZE_SCALAR(regs.rfcr); 2634 UNSERIALIZE_SCALAR(regs.rfdr); 2635 UNSERIALIZE_SCALAR(regs.brar); 2636 UNSERIALIZE_SCALAR(regs.brdr); 2637 UNSERIALIZE_SCALAR(regs.srr); 2638 UNSERIALIZE_SCALAR(regs.mibc); 2639 UNSERIALIZE_SCALAR(regs.vrcr); 2640 UNSERIALIZE_SCALAR(regs.vtcr); 2641 UNSERIALIZE_SCALAR(regs.vdr); 2642 UNSERIALIZE_SCALAR(regs.ccsr); 2643 UNSERIALIZE_SCALAR(regs.tbicr); 2644 UNSERIALIZE_SCALAR(regs.tbisr); 2645 UNSERIALIZE_SCALAR(regs.tanar); 2646 UNSERIALIZE_SCALAR(regs.tanlpar); 2647 UNSERIALIZE_SCALAR(regs.taner); 2648 UNSERIALIZE_SCALAR(regs.tesr); 2649 2650 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2651 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2652 2653 UNSERIALIZE_SCALAR(ioEnable); 2654 2655 /* 2656 * unserialize the data fifos 2657 */ 2658 rxFifo.unserialize("rxFifo", cp, section); 2659 txFifo.unserialize("txFifo", cp, section); 2660 2661 /* 2662 * unserialize the various helper variables 2663 */ 2664 bool txPacketExists; 2665 UNSERIALIZE_SCALAR(txPacketExists); 2666 if (txPacketExists) { 2667 txPacket = new EthPacketData(16384); 2668 txPacket->unserialize("txPacket", cp, section); 2669 uint32_t txPktBufPtr; 2670 UNSERIALIZE_SCALAR(txPktBufPtr); 2671 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2672 } else 2673 txPacket = 0; 2674 2675 bool rxPacketExists; 2676 UNSERIALIZE_SCALAR(rxPacketExists); 2677 rxPacket = 0; 2678 if (rxPacketExists) { 2679 rxPacket = new EthPacketData(16384); 2680 rxPacket->unserialize("rxPacket", cp, section); 2681 uint32_t rxPktBufPtr; 2682 UNSERIALIZE_SCALAR(rxPktBufPtr); 2683 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2684 } else 2685 rxPacket = 0; 2686 2687 UNSERIALIZE_SCALAR(txXferLen); 2688 UNSERIALIZE_SCALAR(rxXferLen); 2689 2690 /* 2691 * Unserialize Cached Descriptors 2692 */ 2693 UNSERIALIZE_SCALAR(rxDesc64.link); 2694 UNSERIALIZE_SCALAR(rxDesc64.bufptr); 2695 UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 2696 UNSERIALIZE_SCALAR(rxDesc64.extsts); 2697 UNSERIALIZE_SCALAR(txDesc64.link); 2698 UNSERIALIZE_SCALAR(txDesc64.bufptr); 2699 UNSERIALIZE_SCALAR(txDesc64.cmdsts); 2700 UNSERIALIZE_SCALAR(txDesc64.extsts); 2701 UNSERIALIZE_SCALAR(rxDesc32.link); 2702 UNSERIALIZE_SCALAR(rxDesc32.bufptr); 2703 UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 2704 UNSERIALIZE_SCALAR(rxDesc32.extsts); 2705 UNSERIALIZE_SCALAR(txDesc32.link); 2706 UNSERIALIZE_SCALAR(txDesc32.bufptr); 2707 UNSERIALIZE_SCALAR(txDesc32.cmdsts); 2708 UNSERIALIZE_SCALAR(txDesc32.extsts); 2709 UNSERIALIZE_SCALAR(extstsEnable); 2710 2711 /* 2712 * unserialize tx state machine 2713 */ 2714 int txState; 2715 UNSERIALIZE_SCALAR(txState); 2716 this->txState = (TxState) txState; 2717 UNSERIALIZE_SCALAR(txEnable); 2718 UNSERIALIZE_SCALAR(CTDD); 2719 UNSERIALIZE_SCALAR(txFragPtr); 2720 UNSERIALIZE_SCALAR(txDescCnt); 2721 int txDmaState; 2722 UNSERIALIZE_SCALAR(txDmaState); 2723 this->txDmaState = (DmaState) txDmaState; 2724 UNSERIALIZE_SCALAR(txKickTick); 2725 if (txKickTick) 2726 txKickEvent.schedule(txKickTick); 2727 2728 /* 2729 * unserialize rx state machine 2730 */ 2731 int rxState; 2732 UNSERIALIZE_SCALAR(rxState); 2733 this->rxState = (RxState) rxState; 2734 UNSERIALIZE_SCALAR(rxEnable); 2735 UNSERIALIZE_SCALAR(CRDD); 2736 UNSERIALIZE_SCALAR(rxPktBytes); 2737 UNSERIALIZE_SCALAR(rxFragPtr); 2738 UNSERIALIZE_SCALAR(rxDescCnt); 2739 int rxDmaState; 2740 UNSERIALIZE_SCALAR(rxDmaState); 2741 this->rxDmaState = (DmaState) rxDmaState; 2742 UNSERIALIZE_SCALAR(rxKickTick); 2743 if (rxKickTick) 2744 rxKickEvent.schedule(rxKickTick); 2745 2746 /* 2747 * Unserialize EEPROM state machine 2748 */ 2749 int eepromState; 2750 UNSERIALIZE_SCALAR(eepromState); 2751 this->eepromState = (EEPROMState) eepromState; 2752 UNSERIALIZE_SCALAR(eepromClk); 2753 UNSERIALIZE_SCALAR(eepromBitsToRx); 2754 UNSERIALIZE_SCALAR(eepromOpcode); 2755 UNSERIALIZE_SCALAR(eepromAddress); 2756 UNSERIALIZE_SCALAR(eepromData); 2757 2758 /* 2759 * If there's a pending transmit, reschedule it now 2760 */ 2761 Tick transmitTick; 2762 UNSERIALIZE_SCALAR(transmitTick); 2763 if (transmitTick) 2764 txEvent.schedule(curTick + transmitTick); 2765 2766 /* 2767 * unserialize receive address filter settings 2768 */ 2769 UNSERIALIZE_SCALAR(rxFilterEnable); 2770 UNSERIALIZE_SCALAR(acceptBroadcast); 2771 UNSERIALIZE_SCALAR(acceptMulticast); 2772 UNSERIALIZE_SCALAR(acceptUnicast); 2773 UNSERIALIZE_SCALAR(acceptPerfect); 2774 UNSERIALIZE_SCALAR(acceptArp); 2775 UNSERIALIZE_SCALAR(multicastHashEnable); 2776 2777 /* 2778 * Keep track of pending interrupt status. 2779 */ 2780 UNSERIALIZE_SCALAR(intrTick); 2781 UNSERIALIZE_SCALAR(cpuPendingIntr); 2782 Tick intrEventTick; 2783 UNSERIALIZE_SCALAR(intrEventTick); 2784 if (intrEventTick) { 2785 intrEvent = new IntrEvent(this, intrEventTick, true); 2786 } 2787} 2788 2789NSGigE * 2790NSGigEParams::create() 2791{ 2792 return new NSGigE(this); 2793} 2794