ns_gige.cc revision 1072
19793Sakash.bagdia@arm.com/* 27586SAli.Saidi@arm.com * Copyright (c) 2004 The Regents of The University of Michigan 37586SAli.Saidi@arm.com * All rights reserved. 47586SAli.Saidi@arm.com * 57586SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without 67586SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are 77586SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright 87586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer; 97586SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright 107586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the 117586SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution; 127586SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its 1310118Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 1410118Snilay@cs.wisc.edu * this software without specific prior written permission. 153970Sgblack@eecs.umich.edu * 163005Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173005Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183005Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193005Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203005Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213005Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223005Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233005Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243005Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253005Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263005Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273005Sstever@eecs.umich.edu */ 283005Sstever@eecs.umich.edu 293005Sstever@eecs.umich.edu/* @file 303005Sstever@eecs.umich.edu * Device module for modelling the National Semiconductor 313005Sstever@eecs.umich.edu * DP83820 ethernet controller. Does not support priority queueing 323005Sstever@eecs.umich.edu */ 333005Sstever@eecs.umich.edu#include <cstdio> 343005Sstever@eecs.umich.edu#include <deque> 353005Sstever@eecs.umich.edu#include <string> 363005Sstever@eecs.umich.edu 373005Sstever@eecs.umich.edu#include "base/inet.hh" 383005Sstever@eecs.umich.edu#include "cpu/exec_context.hh" 393005Sstever@eecs.umich.edu#include "cpu/intr_control.hh" 403005Sstever@eecs.umich.edu#include "dev/dma.hh" 413005Sstever@eecs.umich.edu#include "dev/etherlink.hh" 4210118Snilay@cs.wisc.edu#include "dev/ns_gige.hh" 433005Sstever@eecs.umich.edu#include "dev/pciconfigall.hh" 446654Snate@binkert.org#include "dev/tsunami_cchip.hh" 456654Snate@binkert.org#include "mem/bus/bus.hh" 462889SN/A#include "mem/bus/dma_interface.hh" 472710SN/A#include "mem/bus/pio_interface.hh" 486654Snate@binkert.org#include "mem/bus/pio_interface_impl.hh" 496654Snate@binkert.org#include "mem/functional_mem/memory_control.hh" 506654Snate@binkert.org#include "mem/functional_mem/physical_memory.hh" 515457Ssaidi@eecs.umich.edu#include "sim/builder.hh" 526654Snate@binkert.org#include "sim/debug.hh" 5310118Snilay@cs.wisc.edu#include "sim/host.hh" 5410118Snilay@cs.wisc.edu#include "sim/sim_stats.hh" 5510118Snilay@cs.wisc.edu#include "targetarch/vtophys.hh" 566654Snate@binkert.org 572934SN/Aconst char *NsRxStateStrings[] = 582549SN/A{ 592995SN/A "rxIdle", 603395Shsul@eecs.umich.edu "rxDescRefr", 616981SLisa.Hsu@amd.com "rxDescRead", 629836Sandreas.hansson@arm.com "rxFifoBlock", 633448Shsul@eecs.umich.edu "rxFragWrite", 648920Snilay@cs.wisc.edu "rxDescWrite", 653444Sktlim@umich.edu "rxAdvance" 663304Sstever@eecs.umich.edu}; 679653SAndreas.Sandberg@ARM.com 689653SAndreas.Sandberg@ARM.comconst char *NsTxStateStrings[] = 699653SAndreas.Sandberg@ARM.com{ 709653SAndreas.Sandberg@ARM.com "txIdle", 719653SAndreas.Sandberg@ARM.com "txDescRefr", 729653SAndreas.Sandberg@ARM.com "txDescRead", 739653SAndreas.Sandberg@ARM.com "txFifoBlock", 7410594Sgabeblack@google.com "txFragRead", 7510594Sgabeblack@google.com "txDescWrite", 7610594Sgabeblack@google.com "txAdvance" 7710594Sgabeblack@google.com}; 7810594Sgabeblack@google.com 7910594Sgabeblack@google.comconst char *NsDmaState[] = 8010594Sgabeblack@google.com{ 8110594Sgabeblack@google.com "dmaIdle", 8210594Sgabeblack@google.com "dmaReading", 8310594Sgabeblack@google.com "dmaWriting", 8410594Sgabeblack@google.com "dmaReadWaiting", 8510119Snilay@cs.wisc.edu "dmaWriteWaiting" 8610594Sgabeblack@google.com}; 8710119Snilay@cs.wisc.edu 8810594Sgabeblack@google.comusing namespace std; 8910594Sgabeblack@google.com 9010119Snilay@cs.wisc.edu// helper function declarations 9110594Sgabeblack@google.com// These functions reverse Endianness so we can evaluate network data 9210119Snilay@cs.wisc.edu// correctly 9310594Sgabeblack@google.comuint16_t reverseEnd16(uint16_t); 9410119Snilay@cs.wisc.eduuint32_t reverseEnd32(uint32_t); 9510119Snilay@cs.wisc.edu 9610594Sgabeblack@google.com/////////////////////////////////////////////////////////////////////// 9710119Snilay@cs.wisc.edu// 9810512SAli.Saidi@ARM.com// NSGigE PCI Device 9910512SAli.Saidi@ARM.com// 10010594Sgabeblack@google.comNSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, 10110594Sgabeblack@google.com PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, 10210119Snilay@cs.wisc.edu MemoryController *mmu, HierParams *hier, Bus *header_bus, 10310119Snilay@cs.wisc.edu Bus *payload_bus, Tick pio_latency, bool dma_desc_free, 10410119Snilay@cs.wisc.edu bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, 10510119Snilay@cs.wisc.edu Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, 1062566SN/A PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, 10710119Snilay@cs.wisc.edu uint32_t func, bool rx_filter, const int eaddr[6], 10810119Snilay@cs.wisc.edu uint32_t tx_fifo_size, uint32_t rx_fifo_size) 1099665Sandreas.hansson@arm.com : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), 11010119Snilay@cs.wisc.edu maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), 11110119Snilay@cs.wisc.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 11210119Snilay@cs.wisc.edu txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), 11310119Snilay@cs.wisc.edu CTDD(false), txFifoAvail(tx_fifo_size), 11410119Snilay@cs.wisc.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 11510119Snilay@cs.wisc.edu rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), 11610119Snilay@cs.wisc.edu rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 11710119Snilay@cs.wisc.edu rxDmaReadEvent(this), rxDmaWriteEvent(this), 11810119Snilay@cs.wisc.edu txDmaReadEvent(this), txDmaWriteEvent(this), 11910119Snilay@cs.wisc.edu dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free), 12010119Snilay@cs.wisc.edu txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0), 12110119Snilay@cs.wisc.edu txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false), 12210119Snilay@cs.wisc.edu acceptMulticast(false), acceptUnicast(false), 12310119Snilay@cs.wisc.edu acceptPerfect(false), acceptArp(false), 12410119Snilay@cs.wisc.edu physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), 12510119Snilay@cs.wisc.edu intrEvent(0), interface(0) 12610119Snilay@cs.wisc.edu{ 12710119Snilay@cs.wisc.edu tsunami->ethernet = this; 12810119Snilay@cs.wisc.edu 12910119Snilay@cs.wisc.edu if (header_bus) { 13010119Snilay@cs.wisc.edu pioInterface = newPioInterface(name, hier, header_bus, this, 13110119Snilay@cs.wisc.edu &NSGigE::cacheAccess); 13210119Snilay@cs.wisc.edu 13310119Snilay@cs.wisc.edu pioLatency = pio_latency * header_bus->clockRatio; 13410119Snilay@cs.wisc.edu 13510119Snilay@cs.wisc.edu if (payload_bus) 13610119Snilay@cs.wisc.edu dmaInterface = new DMAInterface<Bus>(name + ".dma", 13710119Snilay@cs.wisc.edu header_bus, payload_bus, 1); 13810119Snilay@cs.wisc.edu else 13910119Snilay@cs.wisc.edu dmaInterface = new DMAInterface<Bus>(name + ".dma", 14010119Snilay@cs.wisc.edu header_bus, header_bus, 1); 14110119Snilay@cs.wisc.edu } else if (payload_bus) { 14210119Snilay@cs.wisc.edu pioInterface = newPioInterface(name, hier, payload_bus, this, 14310119Snilay@cs.wisc.edu &NSGigE::cacheAccess); 14410119Snilay@cs.wisc.edu 14510119Snilay@cs.wisc.edu pioLatency = pio_latency * payload_bus->clockRatio; 14610119Snilay@cs.wisc.edu 14710119Snilay@cs.wisc.edu dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, 14810119Snilay@cs.wisc.edu payload_bus, 1); 14910119Snilay@cs.wisc.edu } 15010119Snilay@cs.wisc.edu 15110119Snilay@cs.wisc.edu 15210519Snilay@cs.wisc.edu intrDelay = US2Ticks(intr_delay); 15310519Snilay@cs.wisc.edu dmaReadDelay = dma_read_delay; 15410119Snilay@cs.wisc.edu dmaWriteDelay = dma_write_delay; 15510119Snilay@cs.wisc.edu dmaReadFactor = dma_read_factor; 15610119Snilay@cs.wisc.edu dmaWriteFactor = dma_write_factor; 15710119Snilay@cs.wisc.edu 15810119Snilay@cs.wisc.edu regsReset(); 15910547Snilay@cs.wisc.edu rom.perfectMatch[0] = eaddr[0]; 16010547Snilay@cs.wisc.edu rom.perfectMatch[1] = eaddr[1]; 16110547Snilay@cs.wisc.edu rom.perfectMatch[2] = eaddr[2]; 16210547Snilay@cs.wisc.edu rom.perfectMatch[3] = eaddr[3]; 16310119Snilay@cs.wisc.edu rom.perfectMatch[4] = eaddr[4]; 16410119Snilay@cs.wisc.edu rom.perfectMatch[5] = eaddr[5]; 16510119Snilay@cs.wisc.edu} 16610119Snilay@cs.wisc.edu 16710119Snilay@cs.wisc.eduNSGigE::~NSGigE() 16810119Snilay@cs.wisc.edu{} 16910119Snilay@cs.wisc.edu 17010119Snilay@cs.wisc.eduvoid 17110120Snilay@cs.wisc.eduNSGigE::regStats() 17210120Snilay@cs.wisc.edu{ 17310119Snilay@cs.wisc.edu txBytes 17410119Snilay@cs.wisc.edu .name(name() + ".txBytes") 17510120Snilay@cs.wisc.edu .desc("Bytes Transmitted") 17610120Snilay@cs.wisc.edu .prereq(txBytes) 17710119Snilay@cs.wisc.edu ; 17810120Snilay@cs.wisc.edu 17910120Snilay@cs.wisc.edu rxBytes 18010120Snilay@cs.wisc.edu .name(name() + ".rxBytes") 18110119Snilay@cs.wisc.edu .desc("Bytes Received") 1822995SN/A .prereq(rxBytes) 18310119Snilay@cs.wisc.edu ; 18410119Snilay@cs.wisc.edu 18510119Snilay@cs.wisc.edu txPackets 18610119Snilay@cs.wisc.edu .name(name() + ".txPackets") 18710119Snilay@cs.wisc.edu .desc("Number of Packets Transmitted") 18810119Snilay@cs.wisc.edu .prereq(txBytes) 18910119Snilay@cs.wisc.edu ; 19010119Snilay@cs.wisc.edu 19110119Snilay@cs.wisc.edu rxPackets 1923304Sstever@eecs.umich.edu .name(name() + ".rxPackets") 19310119Snilay@cs.wisc.edu .desc("Number of Packets Received") 19410119Snilay@cs.wisc.edu .prereq(rxBytes) 19510119Snilay@cs.wisc.edu ; 19610119Snilay@cs.wisc.edu 19710119Snilay@cs.wisc.edu txIPChecksums 19810119Snilay@cs.wisc.edu .name(name() + ".txIPChecksums") 1996135Sgblack@eecs.umich.edu .desc("Number of tx IP Checksums done by device") 20010608Sdam.sunwoo@arm.com .precision(0) 20110608Sdam.sunwoo@arm.com .prereq(txBytes) 20210608Sdam.sunwoo@arm.com ; 20310608Sdam.sunwoo@arm.com 20410608Sdam.sunwoo@arm.com rxIPChecksums 20510608Sdam.sunwoo@arm.com .name(name() + ".rxIPChecksums") 20610608Sdam.sunwoo@arm.com .desc("Number of rx IP Checksums done by device") 20710119Snilay@cs.wisc.edu .precision(0) 20810119Snilay@cs.wisc.edu .prereq(rxBytes) 20910119Snilay@cs.wisc.edu ; 21010608Sdam.sunwoo@arm.com 21110608Sdam.sunwoo@arm.com txTCPChecksums 21210119Snilay@cs.wisc.edu .name(name() + ".txTCPChecksums") 21310119Snilay@cs.wisc.edu .desc("Number of tx TCP Checksums done by device") 21410119Snilay@cs.wisc.edu .precision(0) 2153819Shsul@eecs.umich.edu .prereq(txBytes) 21610119Snilay@cs.wisc.edu ; 21710119Snilay@cs.wisc.edu 21810118Snilay@cs.wisc.edu rxTCPChecksums 21910119Snilay@cs.wisc.edu .name(name() + ".rxTCPChecksums") 2209827Sakash.bagdia@arm.com .desc("Number of rx TCP Checksums done by device") 22110119Snilay@cs.wisc.edu .precision(0) 22210119Snilay@cs.wisc.edu .prereq(rxBytes) 22310119Snilay@cs.wisc.edu ; 22410119Snilay@cs.wisc.edu 22510119Snilay@cs.wisc.edu descDmaReads 22610119Snilay@cs.wisc.edu .name(name() + ".descDMAReads") 2279827Sakash.bagdia@arm.com .desc("Number of descriptors the device read w/ DMA") 22810594Sgabeblack@google.com .precision(0) 2296654Snate@binkert.org ; 23010594Sgabeblack@google.com 2316654Snate@binkert.org descDmaWrites 23210594Sgabeblack@google.com .name(name() + ".descDMAWrites") 2336654Snate@binkert.org .desc("Number of descriptors the device wrote w/ DMA") 23410594Sgabeblack@google.com .precision(0) 2356654Snate@binkert.org ; 23610594Sgabeblack@google.com 23710594Sgabeblack@google.com descDmaRdBytes 2387586SAli.Saidi@arm.com .name(name() + ".descDmaReadBytes") 23910594Sgabeblack@google.com .desc("number of descriptor bytes read w/ DMA") 24010594Sgabeblack@google.com .precision(0) 2418661SAli.Saidi@ARM.com ; 2429827Sakash.bagdia@arm.com 2439827Sakash.bagdia@arm.com descDmaWrBytes 2449827Sakash.bagdia@arm.com .name(name() + ".descDmaWriteBytes") 2459793Sakash.bagdia@arm.com .desc("number of descriptor bytes write w/ DMA") 24610119Snilay@cs.wisc.edu .precision(0) 24710119Snilay@cs.wisc.edu ; 2489790Sakash.bagdia@arm.com 2499827Sakash.bagdia@arm.com 2509827Sakash.bagdia@arm.com txBandwidth 2519827Sakash.bagdia@arm.com .name(name() + ".txBandwidth") 2529793Sakash.bagdia@arm.com .desc("Transmit Bandwidth (bits/s)") 2539827Sakash.bagdia@arm.com .precision(0) 2549827Sakash.bagdia@arm.com .prereq(txBytes) 2559827Sakash.bagdia@arm.com ; 2569793Sakash.bagdia@arm.com 2579793Sakash.bagdia@arm.com rxBandwidth 2589793Sakash.bagdia@arm.com .name(name() + ".rxBandwidth") 2599384SAndreas.Sandberg@arm.com .desc("Receive Bandwidth (bits/s)") 2608863Snilay@cs.wisc.edu .precision(0) 2617876Sgblack@eecs.umich.edu .prereq(rxBytes) 2624968Sacolyte@umich.edu ; 2638926Sandreas.hansson@arm.com 2644837Ssaidi@eecs.umich.edu txPacketRate 2654837Ssaidi@eecs.umich.edu .name(name() + ".txPPS") 2669408Sandreas.hansson@arm.com .desc("Packet Tranmission Rate (packets/s)") 2679653SAndreas.Sandberg@ARM.com .precision(0) 2689653SAndreas.Sandberg@ARM.com .prereq(txBytes) 2699653SAndreas.Sandberg@ARM.com ; 2709164Sandreas.hansson@arm.com 2719408Sandreas.hansson@arm.com rxPacketRate 2728845Sandreas.hansson@arm.com .name(name() + ".rxPPS") 2738845Sandreas.hansson@arm.com .desc("Packet Reception Rate (packets/s)") 2744837Ssaidi@eecs.umich.edu .precision(0) 2759826Sandreas.hansson@arm.com .prereq(rxBytes) 2769826Sandreas.hansson@arm.com ; 2779835Sandreas.hansson@arm.com 2789826Sandreas.hansson@arm.com txBandwidth = txBytes * Stats::constant(8) / simSeconds; 2799826Sandreas.hansson@arm.com rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 2809826Sandreas.hansson@arm.com txPacketRate = txPackets / simSeconds; 2819826Sandreas.hansson@arm.com rxPacketRate = rxPackets / simSeconds; 2828659SAli.Saidi@ARM.com} 28310119Snilay@cs.wisc.edu 28410119Snilay@cs.wisc.edu/** 28510119Snilay@cs.wisc.edu * This is to read the PCI general configuration registers 28610119Snilay@cs.wisc.edu */ 28710119Snilay@cs.wisc.eduvoid 28810119Snilay@cs.wisc.eduNSGigE::ReadConfig(int offset, int size, uint8_t *data) 28910119Snilay@cs.wisc.edu{ 29010119Snilay@cs.wisc.edu if (offset < PCI_DEVICE_SPECIFIC) 29110119Snilay@cs.wisc.edu PciDev::ReadConfig(offset, size, data); 29210119Snilay@cs.wisc.edu else 29310119Snilay@cs.wisc.edu panic("Device specific PCI config space not implemented!\n"); 29410119Snilay@cs.wisc.edu} 29510119Snilay@cs.wisc.edu 29610119Snilay@cs.wisc.edu/** 29710119Snilay@cs.wisc.edu * This is to write to the PCI general configuration registers 29810119Snilay@cs.wisc.edu */ 29910119Snilay@cs.wisc.eduvoid 30010119Snilay@cs.wisc.eduNSGigE::WriteConfig(int offset, int size, uint32_t data) 30110119Snilay@cs.wisc.edu{ 30210119Snilay@cs.wisc.edu if (offset < PCI_DEVICE_SPECIFIC) 30310119Snilay@cs.wisc.edu PciDev::WriteConfig(offset, size, data); 30410119Snilay@cs.wisc.edu else 30510119Snilay@cs.wisc.edu panic("Device specific PCI config space not implemented!\n"); 30610119Snilay@cs.wisc.edu 30710119Snilay@cs.wisc.edu // Need to catch writes to BARs to update the PIO interface 30810119Snilay@cs.wisc.edu switch (offset) { 30910119Snilay@cs.wisc.edu // seems to work fine without all these PCI settings, but i 31010119Snilay@cs.wisc.edu // put in the IO to double check, an assertion will fail if we 31110119Snilay@cs.wisc.edu // need to properly implement it 31210119Snilay@cs.wisc.edu case PCI_COMMAND: 31310119Snilay@cs.wisc.edu if (config.data[offset] & PCI_CMD_IOSE) 31410119Snilay@cs.wisc.edu ioEnable = true; 31510119Snilay@cs.wisc.edu else 31610119Snilay@cs.wisc.edu ioEnable = false; 31710119Snilay@cs.wisc.edu 31810119Snilay@cs.wisc.edu#if 0 31910119Snilay@cs.wisc.edu if (config.data[offset] & PCI_CMD_BME) { 32010119Snilay@cs.wisc.edu bmEnabled = true; 32110119Snilay@cs.wisc.edu } 32210119Snilay@cs.wisc.edu else { 32310119Snilay@cs.wisc.edu bmEnabled = false; 32410119Snilay@cs.wisc.edu } 32510119Snilay@cs.wisc.edu 3268801Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_MSE) { 3273005Sstever@eecs.umich.edu memEnable = true; 3288801Sgblack@eecs.umich.edu } 3293005Sstever@eecs.umich.edu else { 3303005Sstever@eecs.umich.edu memEnable = false; 3313005Sstever@eecs.umich.edu } 3322566SN/A#endif 3337861Sgblack@eecs.umich.edu break; 3347861Sgblack@eecs.umich.edu 3357861Sgblack@eecs.umich.edu case PCI0_BASE_ADDR0: 3368635Schris.emmons@arm.com if (BARAddrs[0] != 0) { 3378635Schris.emmons@arm.com if (pioInterface) 3388635Schris.emmons@arm.com pioInterface->addAddrRange(BARAddrs[0], 3399061Snilay@cs.wisc.edu BARAddrs[0] + BARSize[0] - 1); 3403481Shsul@eecs.umich.edu 341 BARAddrs[0] &= PA_UNCACHED_MASK; 342 } 343 break; 344 case PCI0_BASE_ADDR1: 345 if (BARAddrs[1] != 0) { 346 if (pioInterface) 347 pioInterface->addAddrRange(BARAddrs[1], 348 BARAddrs[1] + BARSize[1] - 1); 349 350 BARAddrs[1] &= PA_UNCACHED_MASK; 351 } 352 break; 353 } 354} 355 356/** 357 * This reads the device registers, which are detailed in the NS83820 358 * spec sheet 359 */ 360Fault 361NSGigE::read(MemReqPtr &req, uint8_t *data) 362{ 363 assert(ioEnable); 364 365 //The mask is to give you only the offset into the device register file 366 Addr daddr = req->paddr & 0xfff; 367 DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 368 daddr, req->paddr, req->vaddr, req->size); 369 370 371 // there are some reserved registers, you can see ns_gige_reg.h and 372 // the spec sheet for details 373 if (daddr > LAST && daddr <= RESERVED) { 374 panic("Accessing reserved register"); 375 } else if (daddr > RESERVED && daddr <= 0x3FC) { 376 ReadConfig(daddr & 0xff, req->size, data); 377 return No_Fault; 378 } else if (daddr >= MIB_START && daddr <= MIB_END) { 379 // don't implement all the MIB's. hopefully the kernel 380 // doesn't actually DEPEND upon their values 381 // MIB are just hardware stats keepers 382 uint32_t ® = *(uint32_t *) data; 383 reg = 0; 384 return No_Fault; 385 } else if (daddr > 0x3FC) 386 panic("Something is messed up!\n"); 387 388 switch (req->size) { 389 case sizeof(uint32_t): 390 { 391 uint32_t ® = *(uint32_t *)data; 392 393 switch (daddr) { 394 case CR: 395 reg = regs.command; 396 //these are supposed to be cleared on a read 397 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 398 break; 399 400 case CFG: 401 reg = regs.config; 402 break; 403 404 case MEAR: 405 reg = regs.mear; 406 break; 407 408 case PTSCR: 409 reg = regs.ptscr; 410 break; 411 412 case ISR: 413 reg = regs.isr; 414 devIntrClear(ISR_ALL); 415 break; 416 417 case IMR: 418 reg = regs.imr; 419 break; 420 421 case IER: 422 reg = regs.ier; 423 break; 424 425 case IHR: 426 reg = regs.ihr; 427 break; 428 429 case TXDP: 430 reg = regs.txdp; 431 break; 432 433 case TXDP_HI: 434 reg = regs.txdp_hi; 435 break; 436 437 case TXCFG: 438 reg = regs.txcfg; 439 break; 440 441 case GPIOR: 442 reg = regs.gpior; 443 break; 444 445 case RXDP: 446 reg = regs.rxdp; 447 break; 448 449 case RXDP_HI: 450 reg = regs.rxdp_hi; 451 break; 452 453 case RXCFG: 454 reg = regs.rxcfg; 455 break; 456 457 case PQCR: 458 reg = regs.pqcr; 459 break; 460 461 case WCSR: 462 reg = regs.wcsr; 463 break; 464 465 case PCR: 466 reg = regs.pcr; 467 break; 468 469 // see the spec sheet for how RFCR and RFDR work 470 // basically, you write to RFCR to tell the machine 471 // what you want to do next, then you act upon RFDR, 472 // and the device will be prepared b/c of what you 473 // wrote to RFCR 474 case RFCR: 475 reg = regs.rfcr; 476 break; 477 478 case RFDR: 479 switch (regs.rfcr & RFCR_RFADDR) { 480 case 0x000: 481 reg = rom.perfectMatch[1]; 482 reg = reg << 8; 483 reg += rom.perfectMatch[0]; 484 break; 485 case 0x002: 486 reg = rom.perfectMatch[3] << 8; 487 reg += rom.perfectMatch[2]; 488 break; 489 case 0x004: 490 reg = rom.perfectMatch[5] << 8; 491 reg += rom.perfectMatch[4]; 492 break; 493 default: 494 panic("reading RFDR for something other than PMATCH!\n"); 495 // didn't implement other RFDR functionality b/c 496 // driver didn't use it 497 } 498 break; 499 500 case SRR: 501 reg = regs.srr; 502 break; 503 504 case MIBC: 505 reg = regs.mibc; 506 reg &= ~(MIBC_MIBS | MIBC_ACLR); 507 break; 508 509 case VRCR: 510 reg = regs.vrcr; 511 break; 512 513 case VTCR: 514 reg = regs.vtcr; 515 break; 516 517 case VDR: 518 reg = regs.vdr; 519 break; 520 521 case CCSR: 522 reg = regs.ccsr; 523 break; 524 525 case TBICR: 526 reg = regs.tbicr; 527 break; 528 529 case TBISR: 530 reg = regs.tbisr; 531 break; 532 533 case TANAR: 534 reg = regs.tanar; 535 break; 536 537 case TANLPAR: 538 reg = regs.tanlpar; 539 break; 540 541 case TANER: 542 reg = regs.taner; 543 break; 544 545 case TESR: 546 reg = regs.tesr; 547 break; 548 549 default: 550 panic("reading unimplemented register: addr=%#x", daddr); 551 } 552 553 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 554 daddr, reg, reg); 555 } 556 break; 557 558 default: 559 panic("accessing register with invalid size: addr=%#x, size=%d", 560 daddr, req->size); 561 } 562 563 return No_Fault; 564} 565 566Fault 567NSGigE::write(MemReqPtr &req, const uint8_t *data) 568{ 569 assert(ioEnable); 570 571 Addr daddr = req->paddr & 0xfff; 572 DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 573 daddr, req->paddr, req->vaddr, req->size); 574 575 if (daddr > LAST && daddr <= RESERVED) { 576 panic("Accessing reserved register"); 577 } else if (daddr > RESERVED && daddr <= 0x3FC) { 578 WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 579 return No_Fault; 580 } else if (daddr > 0x3FC) 581 panic("Something is messed up!\n"); 582 583 if (req->size == sizeof(uint32_t)) { 584 uint32_t reg = *(uint32_t *)data; 585 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 586 587 switch (daddr) { 588 case CR: 589 regs.command = reg; 590 if (reg & CR_TXD) { 591 txEnable = false; 592 } else if (reg & CR_TXE) { 593 txEnable = true; 594 595 // the kernel is enabling the transmit machine 596 if (txState == txIdle) 597 txKick(); 598 } 599 600 if (reg & CR_RXD) { 601 rxEnable = false; 602 } else if (reg & CR_RXE) { 603 rxEnable = true; 604 605 if (rxState == rxIdle) 606 rxKick(); 607 } 608 609 if (reg & CR_TXR) 610 txReset(); 611 612 if (reg & CR_RXR) 613 rxReset(); 614 615 if (reg & CR_SWI) 616 devIntrPost(ISR_SWI); 617 618 if (reg & CR_RST) { 619 txReset(); 620 rxReset(); 621 622 regsReset(); 623 } 624 break; 625 626 case CFG: 627 if (reg & CFG_LNKSTS || 628 reg & CFG_SPDSTS || 629 reg & CFG_DUPSTS || 630 reg & CFG_RESERVED || 631 reg & CFG_T64ADDR || 632 reg & CFG_PCI64_DET) 633 panic("writing to read-only or reserved CFG bits!\n"); 634 635 regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | 636 CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET); 637 638// all these #if 0's are because i don't THINK the kernel needs to 639// have these implemented. if there is a problem relating to one of 640// these, you may need to add functionality in. 641#if 0 642 if (reg & CFG_TBI_EN) ; 643 if (reg & CFG_MODE_1000) ; 644#endif 645 646 if (reg & CFG_AUTO_1000) 647 panic("CFG_AUTO_1000 not implemented!\n"); 648 649#if 0 650 if (reg & CFG_PINT_DUPSTS || 651 reg & CFG_PINT_LNKSTS || 652 reg & CFG_PINT_SPDSTS) 653 ; 654 655 if (reg & CFG_TMRTEST) ; 656 if (reg & CFG_MRM_DIS) ; 657 if (reg & CFG_MWI_DIS) ; 658 659 if (reg & CFG_T64ADDR) 660 panic("CFG_T64ADDR is read only register!\n"); 661 662 if (reg & CFG_PCI64_DET) 663 panic("CFG_PCI64_DET is read only register!\n"); 664 665 if (reg & CFG_DATA64_EN) ; 666 if (reg & CFG_M64ADDR) ; 667 if (reg & CFG_PHY_RST) ; 668 if (reg & CFG_PHY_DIS) ; 669#endif 670 671 if (reg & CFG_EXTSTS_EN) 672 extstsEnable = true; 673 else 674 extstsEnable = false; 675 676#if 0 677 if (reg & CFG_REQALG) ; 678 if (reg & CFG_SB) ; 679 if (reg & CFG_POW) ; 680 if (reg & CFG_EXD) ; 681 if (reg & CFG_PESEL) ; 682 if (reg & CFG_BROM_DIS) ; 683 if (reg & CFG_EXT_125) ; 684 if (reg & CFG_BEM) ; 685#endif 686 break; 687 688 case MEAR: 689 regs.mear = reg; 690 // since phy is completely faked, MEAR_MD* don't matter 691 // and since the driver never uses MEAR_EE*, they don't 692 // matter 693#if 0 694 if (reg & MEAR_EEDI) ; 695 if (reg & MEAR_EEDO) ; // this one is read only 696 if (reg & MEAR_EECLK) ; 697 if (reg & MEAR_EESEL) ; 698 if (reg & MEAR_MDIO) ; 699 if (reg & MEAR_MDDIR) ; 700 if (reg & MEAR_MDC) ; 701#endif 702 break; 703 704 case PTSCR: 705 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 706 // these control BISTs for various parts of chip - we 707 // don't care or do just fake that the BIST is done 708 if (reg & PTSCR_RBIST_EN) 709 regs.ptscr |= PTSCR_RBIST_DONE; 710 if (reg & PTSCR_EEBIST_EN) 711 regs.ptscr &= ~PTSCR_EEBIST_EN; 712 if (reg & PTSCR_EELOAD_EN) 713 regs.ptscr &= ~PTSCR_EELOAD_EN; 714 break; 715 716 case ISR: /* writing to the ISR has no effect */ 717 panic("ISR is a read only register!\n"); 718 719 case IMR: 720 regs.imr = reg; 721 devIntrChangeMask(); 722 break; 723 724 case IER: 725 regs.ier = reg; 726 break; 727 728 case IHR: 729 regs.ihr = reg; 730 /* not going to implement real interrupt holdoff */ 731 break; 732 733 case TXDP: 734 regs.txdp = (reg & 0xFFFFFFFC); 735 assert(txState == txIdle); 736 CTDD = false; 737 break; 738 739 case TXDP_HI: 740 regs.txdp_hi = reg; 741 break; 742 743 case TXCFG: 744 regs.txcfg = reg; 745#if 0 746 if (reg & TXCFG_CSI) ; 747 if (reg & TXCFG_HBI) ; 748 if (reg & TXCFG_MLB) ; 749 if (reg & TXCFG_ATP) ; 750 if (reg & TXCFG_ECRETRY) { 751 /* 752 * this could easily be implemented, but considering 753 * the network is just a fake pipe, wouldn't make 754 * sense to do this 755 */ 756 } 757 758 if (reg & TXCFG_BRST_DIS) ; 759#endif 760 761#if 0 762 /* we handle our own DMA, ignore the kernel's exhortations */ 763 if (reg & TXCFG_MXDMA) ; 764#endif 765 766 // also, we currently don't care about fill/drain 767 // thresholds though this may change in the future with 768 // more realistic networks or a driver which changes it 769 // according to feedback 770 771 break; 772 773 case GPIOR: 774 regs.gpior = reg; 775 /* these just control general purpose i/o pins, don't matter */ 776 break; 777 778 case RXDP: 779 regs.rxdp = reg; 780 CRDD = false; 781 break; 782 783 case RXDP_HI: 784 regs.rxdp_hi = reg; 785 break; 786 787 case RXCFG: 788 regs.rxcfg = reg; 789#if 0 790 if (reg & RXCFG_AEP) ; 791 if (reg & RXCFG_ARP) ; 792 if (reg & RXCFG_STRIPCRC) ; 793 if (reg & RXCFG_RX_RD) ; 794 if (reg & RXCFG_ALP) ; 795 if (reg & RXCFG_AIRL) ; 796 797 /* we handle our own DMA, ignore what kernel says about it */ 798 if (reg & RXCFG_MXDMA) ; 799 800 //also, we currently don't care about fill/drain thresholds 801 //though this may change in the future with more realistic 802 //networks or a driver which changes it according to feedback 803 if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 804#endif 805 break; 806 807 case PQCR: 808 /* there is no priority queueing used in the linux 2.6 driver */ 809 regs.pqcr = reg; 810 break; 811 812 case WCSR: 813 /* not going to implement wake on LAN */ 814 regs.wcsr = reg; 815 break; 816 817 case PCR: 818 /* not going to implement pause control */ 819 regs.pcr = reg; 820 break; 821 822 case RFCR: 823 regs.rfcr = reg; 824 825 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 826 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 827 acceptMulticast = (reg & RFCR_AAM) ? true : false; 828 acceptUnicast = (reg & RFCR_AAU) ? true : false; 829 acceptPerfect = (reg & RFCR_APM) ? true : false; 830 acceptArp = (reg & RFCR_AARP) ? true : false; 831 832#if 0 833 if (reg & RFCR_APAT) 834 panic("RFCR_APAT not implemented!\n"); 835#endif 836 837 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 838 panic("hash filtering not implemented!\n"); 839 840 if (reg & RFCR_ULM) 841 panic("RFCR_ULM not implemented!\n"); 842 843 break; 844 845 case RFDR: 846 panic("the driver never writes to RFDR, something is wrong!\n"); 847 848 case BRAR: 849 panic("the driver never uses BRAR, something is wrong!\n"); 850 851 case BRDR: 852 panic("the driver never uses BRDR, something is wrong!\n"); 853 854 case SRR: 855 panic("SRR is read only register!\n"); 856 857 case MIBC: 858 panic("the driver never uses MIBC, something is wrong!\n"); 859 860 case VRCR: 861 regs.vrcr = reg; 862 break; 863 864 case VTCR: 865 regs.vtcr = reg; 866 break; 867 868 case VDR: 869 panic("the driver never uses VDR, something is wrong!\n"); 870 break; 871 872 case CCSR: 873 /* not going to implement clockrun stuff */ 874 regs.ccsr = reg; 875 break; 876 877 case TBICR: 878 regs.tbicr = reg; 879 if (reg & TBICR_MR_LOOPBACK) 880 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 881 882 if (reg & TBICR_MR_AN_ENABLE) { 883 regs.tanlpar = regs.tanar; 884 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 885 } 886 887#if 0 888 if (reg & TBICR_MR_RESTART_AN) ; 889#endif 890 891 break; 892 893 case TBISR: 894 panic("TBISR is read only register!\n"); 895 896 case TANAR: 897 regs.tanar = reg; 898 if (reg & TANAR_PS2) 899 panic("this isn't used in driver, something wrong!\n"); 900 901 if (reg & TANAR_PS1) 902 panic("this isn't used in driver, something wrong!\n"); 903 break; 904 905 case TANLPAR: 906 panic("this should only be written to by the fake phy!\n"); 907 908 case TANER: 909 panic("TANER is read only register!\n"); 910 911 case TESR: 912 regs.tesr = reg; 913 break; 914 915 default: 916 panic("invalid register access daddr=%#x", daddr); 917 } 918 } else { 919 panic("Invalid Request Size"); 920 } 921 922 return No_Fault; 923} 924 925void 926NSGigE::devIntrPost(uint32_t interrupts) 927{ 928 if (interrupts & ISR_RESERVE) 929 panic("Cannot set a reserved interrupt"); 930 931 if (interrupts & ISR_NOIMPL) 932 warn("interrupt not implemented %#x\n", interrupts); 933 934 interrupts &= ~ISR_NOIMPL; 935 regs.isr |= interrupts; 936 937 DPRINTF(EthernetIntr, 938 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 939 interrupts, regs.isr, regs.imr); 940 941 if ((regs.isr & regs.imr)) { 942 Tick when = curTick; 943 if (!(regs.isr & regs.imr & ISR_NODELAY)) 944 when += intrDelay; 945 cpuIntrPost(when); 946 } 947} 948 949void 950NSGigE::devIntrClear(uint32_t interrupts) 951{ 952 if (interrupts & ISR_RESERVE) 953 panic("Cannot clear a reserved interrupt"); 954 955 interrupts &= ~ISR_NOIMPL; 956 regs.isr &= ~interrupts; 957 958 DPRINTF(EthernetIntr, 959 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 960 interrupts, regs.isr, regs.imr); 961 962 if (!(regs.isr & regs.imr)) 963 cpuIntrClear(); 964} 965 966void 967NSGigE::devIntrChangeMask() 968{ 969 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 970 regs.isr, regs.imr, regs.isr & regs.imr); 971 972 if (regs.isr & regs.imr) 973 cpuIntrPost(curTick); 974 else 975 cpuIntrClear(); 976} 977 978void 979NSGigE::cpuIntrPost(Tick when) 980{ 981 // If the interrupt you want to post is later than an interrupt 982 // already scheduled, just let it post in the coming one and don't 983 // schedule another. 984 // HOWEVER, must be sure that the scheduled intrTick is in the 985 // future (this was formerly the source of a bug) 986 /** 987 * @todo this warning should be removed and the intrTick code should 988 * be fixed. 989 */ 990 assert(when >= curTick); 991 assert(intrTick >= curTick || intrTick == 0); 992 if (when > intrTick && intrTick != 0) { 993 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 994 intrTick); 995 return; 996 } 997 998 intrTick = when; 999 if (intrTick < curTick) { 1000 debug_break(); 1001 intrTick = curTick; 1002 } 1003 1004 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 1005 intrTick); 1006 1007 if (intrEvent) 1008 intrEvent->squash(); 1009 intrEvent = new IntrEvent(this, true); 1010 intrEvent->schedule(intrTick); 1011} 1012 1013void 1014NSGigE::cpuInterrupt() 1015{ 1016 assert(intrTick == curTick); 1017 1018 // Whether or not there's a pending interrupt, we don't care about 1019 // it anymore 1020 intrEvent = 0; 1021 intrTick = 0; 1022 1023 // Don't send an interrupt if there's already one 1024 if (cpuPendingIntr) { 1025 DPRINTF(EthernetIntr, 1026 "would send an interrupt now, but there's already pending\n"); 1027 } else { 1028 // Send interrupt 1029 cpuPendingIntr = true; 1030 1031 DPRINTF(EthernetIntr, "posting cchip interrupt\n"); 1032 tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine); 1033 } 1034} 1035 1036void 1037NSGigE::cpuIntrClear() 1038{ 1039 if (!cpuPendingIntr) 1040 return; 1041 1042 if (intrEvent) { 1043 intrEvent->squash(); 1044 intrEvent = 0; 1045 } 1046 1047 intrTick = 0; 1048 1049 cpuPendingIntr = false; 1050 1051 DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); 1052 tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); 1053} 1054 1055bool 1056NSGigE::cpuIntrPending() const 1057{ return cpuPendingIntr; } 1058 1059void 1060NSGigE::txReset() 1061{ 1062 1063 DPRINTF(Ethernet, "transmit reset\n"); 1064 1065 CTDD = false; 1066 txFifoAvail = maxTxFifoSize; 1067 txEnable = false;; 1068 txFragPtr = 0; 1069 assert(txDescCnt == 0); 1070 txFifo.clear(); 1071 txState = txIdle; 1072 assert(txDmaState == dmaIdle); 1073} 1074 1075void 1076NSGigE::rxReset() 1077{ 1078 DPRINTF(Ethernet, "receive reset\n"); 1079 1080 CRDD = false; 1081 assert(rxPktBytes == 0); 1082 rxFifoCnt = 0; 1083 rxEnable = false; 1084 rxFragPtr = 0; 1085 assert(rxDescCnt == 0); 1086 assert(rxDmaState == dmaIdle); 1087 rxFifo.clear(); 1088 rxState = rxIdle; 1089} 1090 1091void 1092NSGigE::regsReset() 1093{ 1094 memset(®s, 0, sizeof(regs)); 1095 regs.config = CFG_LNKSTS; 1096 regs.mear = MEAR_MDDIR | MEAR_EEDO; 1097 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1098 // fill threshold to 32 bytes 1099 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1100 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1101 regs.mibc = MIBC_FRZ; 1102 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1103 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1104 1105 extstsEnable = false; 1106 acceptBroadcast = false; 1107 acceptMulticast = false; 1108 acceptUnicast = false; 1109 acceptPerfect = false; 1110 acceptArp = false; 1111} 1112 1113void 1114NSGigE::rxDmaReadCopy() 1115{ 1116 assert(rxDmaState == dmaReading); 1117 1118 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1119 rxDmaState = dmaIdle; 1120 1121 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1122 rxDmaAddr, rxDmaLen); 1123 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1124} 1125 1126bool 1127NSGigE::doRxDmaRead() 1128{ 1129 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1130 rxDmaState = dmaReading; 1131 1132 if (dmaInterface && !rxDmaFree) { 1133 if (dmaInterface->busy()) 1134 rxDmaState = dmaReadWaiting; 1135 else 1136 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1137 &rxDmaReadEvent, true); 1138 return true; 1139 } 1140 1141 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1142 rxDmaReadCopy(); 1143 return false; 1144 } 1145 1146 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1147 Tick start = curTick + dmaReadDelay + factor; 1148 rxDmaReadEvent.schedule(start); 1149 return true; 1150} 1151 1152void 1153NSGigE::rxDmaReadDone() 1154{ 1155 assert(rxDmaState == dmaReading); 1156 rxDmaReadCopy(); 1157 1158 // If the transmit state machine has a pending DMA, let it go first 1159 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1160 txKick(); 1161 1162 rxKick(); 1163} 1164 1165void 1166NSGigE::rxDmaWriteCopy() 1167{ 1168 assert(rxDmaState == dmaWriting); 1169 1170 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1171 rxDmaState = dmaIdle; 1172 1173 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1174 rxDmaAddr, rxDmaLen); 1175 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1176} 1177 1178bool 1179NSGigE::doRxDmaWrite() 1180{ 1181 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1182 rxDmaState = dmaWriting; 1183 1184 if (dmaInterface && !rxDmaFree) { 1185 if (dmaInterface->busy()) 1186 rxDmaState = dmaWriteWaiting; 1187 else 1188 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1189 &rxDmaWriteEvent, true); 1190 return true; 1191 } 1192 1193 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1194 rxDmaWriteCopy(); 1195 return false; 1196 } 1197 1198 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1199 Tick start = curTick + dmaWriteDelay + factor; 1200 rxDmaWriteEvent.schedule(start); 1201 return true; 1202} 1203 1204void 1205NSGigE::rxDmaWriteDone() 1206{ 1207 assert(rxDmaState == dmaWriting); 1208 rxDmaWriteCopy(); 1209 1210 // If the transmit state machine has a pending DMA, let it go first 1211 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1212 txKick(); 1213 1214 rxKick(); 1215} 1216 1217void 1218NSGigE::rxKick() 1219{ 1220 DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", 1221 NsRxStateStrings[rxState], rxFifo.size()); 1222 1223 if (rxKickTick > curTick) { 1224 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1225 rxKickTick); 1226 return; 1227 } 1228 1229 next: 1230 switch(rxDmaState) { 1231 case dmaReadWaiting: 1232 if (doRxDmaRead()) 1233 goto exit; 1234 break; 1235 case dmaWriteWaiting: 1236 if (doRxDmaWrite()) 1237 goto exit; 1238 break; 1239 default: 1240 break; 1241 } 1242 1243 // see state machine from spec for details 1244 // the way this works is, if you finish work on one state and can 1245 // go directly to another, you do that through jumping to the 1246 // label "next". however, if you have intermediate work, like DMA 1247 // so that you can't go to the next state yet, you go to exit and 1248 // exit the loop. however, when the DMA is done it will trigger 1249 // an event and come back to this loop. 1250 switch (rxState) { 1251 case rxIdle: 1252 if (!rxEnable) { 1253 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1254 goto exit; 1255 } 1256 1257 if (CRDD) { 1258 rxState = rxDescRefr; 1259 1260 rxDmaAddr = regs.rxdp & 0x3fffffff; 1261 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1262 rxDmaLen = sizeof(rxDescCache.link); 1263 rxDmaFree = dmaDescFree; 1264 1265 descDmaReads++; 1266 descDmaRdBytes += rxDmaLen; 1267 1268 if (doRxDmaRead()) 1269 goto exit; 1270 } else { 1271 rxState = rxDescRead; 1272 1273 rxDmaAddr = regs.rxdp & 0x3fffffff; 1274 rxDmaData = &rxDescCache; 1275 rxDmaLen = sizeof(ns_desc); 1276 rxDmaFree = dmaDescFree; 1277 1278 descDmaReads++; 1279 descDmaRdBytes += rxDmaLen; 1280 1281 if (doRxDmaRead()) 1282 goto exit; 1283 } 1284 break; 1285 1286 case rxDescRefr: 1287 if (rxDmaState != dmaIdle) 1288 goto exit; 1289 1290 rxState = rxAdvance; 1291 break; 1292 1293 case rxDescRead: 1294 if (rxDmaState != dmaIdle) 1295 goto exit; 1296 1297 DPRINTF(EthernetDesc, 1298 "rxDescCache: addr=%08x read descriptor\n", 1299 regs.rxdp & 0x3fffffff); 1300 DPRINTF(EthernetDesc, 1301 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1302 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1303 rxDescCache.extsts); 1304 1305 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1306 devIntrPost(ISR_RXIDLE); 1307 rxState = rxIdle; 1308 goto exit; 1309 } else { 1310 rxState = rxFifoBlock; 1311 rxFragPtr = rxDescCache.bufptr; 1312 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1313 } 1314 break; 1315 1316 case rxFifoBlock: 1317 if (!rxPacket) { 1318 /** 1319 * @todo in reality, we should be able to start processing 1320 * the packet as it arrives, and not have to wait for the 1321 * full packet ot be in the receive fifo. 1322 */ 1323 if (rxFifo.empty()) 1324 goto exit; 1325 1326 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1327 1328 // If we don't have a packet, grab a new one from the fifo. 1329 rxPacket = rxFifo.front(); 1330 rxPktBytes = rxPacket->length; 1331 rxPacketBufPtr = rxPacket->data; 1332 1333#if TRACING_ON 1334 if (DTRACE(Ethernet)) { 1335 if (rxPacket->isIpPkt()) { 1336 ip_header *ip = rxPacket->getIpHdr(); 1337 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1338 if (rxPacket->isTcpPkt()) { 1339 tcp_header *tcp = rxPacket->getTcpHdr(ip); 1340 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 1341 reverseEnd16(tcp->src_port_num), 1342 reverseEnd16(tcp->dest_port_num)); 1343 } 1344 } 1345 } 1346#endif 1347 1348 // sanity check - i think the driver behaves like this 1349 assert(rxDescCnt >= rxPktBytes); 1350 1351 // Must clear the value before popping to decrement the 1352 // reference count 1353 rxFifo.front() = NULL; 1354 rxFifo.pop_front(); 1355 rxFifoCnt -= rxPacket->length; 1356 } 1357 1358 1359 // dont' need the && rxDescCnt > 0 if driver sanity check 1360 // above holds 1361 if (rxPktBytes > 0) { 1362 rxState = rxFragWrite; 1363 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1364 // check holds 1365 rxXferLen = rxPktBytes; 1366 1367 rxDmaAddr = rxFragPtr & 0x3fffffff; 1368 rxDmaData = rxPacketBufPtr; 1369 rxDmaLen = rxXferLen; 1370 rxDmaFree = dmaDataFree; 1371 1372 if (doRxDmaWrite()) 1373 goto exit; 1374 1375 } else { 1376 rxState = rxDescWrite; 1377 1378 //if (rxPktBytes == 0) { /* packet is done */ 1379 assert(rxPktBytes == 0); 1380 DPRINTF(EthernetSM, "done with receiving packet\n"); 1381 1382 rxDescCache.cmdsts |= CMDSTS_OWN; 1383 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1384 rxDescCache.cmdsts |= CMDSTS_OK; 1385 rxDescCache.cmdsts &= 0xffff0000; 1386 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1387 1388#if 0 1389 /* 1390 * all the driver uses these are for its own stats keeping 1391 * which we don't care about, aren't necessary for 1392 * functionality and doing this would just slow us down. 1393 * if they end up using this in a later version for 1394 * functional purposes, just undef 1395 */ 1396 if (rxFilterEnable) { 1397 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1398 if (rxFifo.front()->IsUnicast()) 1399 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1400 if (rxFifo.front()->IsMulticast()) 1401 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1402 if (rxFifo.front()->IsBroadcast()) 1403 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1404 } 1405#endif 1406 1407 if (rxPacket->isIpPkt() && extstsEnable) { 1408 rxDescCache.extsts |= EXTSTS_IPPKT; 1409 rxIPChecksums++; 1410 if (!ipChecksum(rxPacket, false)) { 1411 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1412 rxDescCache.extsts |= EXTSTS_IPERR; 1413 } 1414 if (rxPacket->isTcpPkt()) { 1415 rxDescCache.extsts |= EXTSTS_TCPPKT; 1416 rxTCPChecksums++; 1417 if (!tcpChecksum(rxPacket, false)) { 1418 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1419 rxDescCache.extsts |= EXTSTS_TCPERR; 1420 1421 } 1422 } else if (rxPacket->isUdpPkt()) { 1423 rxDescCache.extsts |= EXTSTS_UDPPKT; 1424 if (!udpChecksum(rxPacket, false)) { 1425 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1426 rxDescCache.extsts |= EXTSTS_UDPERR; 1427 } 1428 } 1429 } 1430 rxPacket = 0; 1431 1432 /* 1433 * the driver seems to always receive into desc buffers 1434 * of size 1514, so you never have a pkt that is split 1435 * into multiple descriptors on the receive side, so 1436 * i don't implement that case, hence the assert above. 1437 */ 1438 1439 DPRINTF(EthernetDesc, 1440 "rxDescCache: addr=%08x writeback cmdsts extsts\n", 1441 regs.rxdp & 0x3fffffff); 1442 DPRINTF(EthernetDesc, 1443 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1444 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1445 rxDescCache.extsts); 1446 1447 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1448 rxDmaData = &(rxDescCache.cmdsts); 1449 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1450 rxDmaFree = dmaDescFree; 1451 1452 descDmaWrites++; 1453 descDmaWrBytes += rxDmaLen; 1454 1455 if (doRxDmaWrite()) 1456 goto exit; 1457 } 1458 break; 1459 1460 case rxFragWrite: 1461 if (rxDmaState != dmaIdle) 1462 goto exit; 1463 1464 rxPacketBufPtr += rxXferLen; 1465 rxFragPtr += rxXferLen; 1466 rxPktBytes -= rxXferLen; 1467 1468 rxState = rxFifoBlock; 1469 break; 1470 1471 case rxDescWrite: 1472 if (rxDmaState != dmaIdle) 1473 goto exit; 1474 1475 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1476 1477 assert(rxPacket == 0); 1478 devIntrPost(ISR_RXOK); 1479 1480 if (rxDescCache.cmdsts & CMDSTS_INTR) 1481 devIntrPost(ISR_RXDESC); 1482 1483 if (!rxEnable) { 1484 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1485 rxState = rxIdle; 1486 goto exit; 1487 } else 1488 rxState = rxAdvance; 1489 break; 1490 1491 case rxAdvance: 1492 if (rxDescCache.link == 0) { 1493 devIntrPost(ISR_RXIDLE); 1494 rxState = rxIdle; 1495 CRDD = true; 1496 goto exit; 1497 } else { 1498 rxState = rxDescRead; 1499 regs.rxdp = rxDescCache.link; 1500 CRDD = false; 1501 1502 rxDmaAddr = regs.rxdp & 0x3fffffff; 1503 rxDmaData = &rxDescCache; 1504 rxDmaLen = sizeof(ns_desc); 1505 rxDmaFree = dmaDescFree; 1506 1507 if (doRxDmaRead()) 1508 goto exit; 1509 } 1510 break; 1511 1512 default: 1513 panic("Invalid rxState!"); 1514 } 1515 1516 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1517 NsRxStateStrings[rxState]); 1518 1519 goto next; 1520 1521 exit: 1522 /** 1523 * @todo do we want to schedule a future kick? 1524 */ 1525 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1526 NsRxStateStrings[rxState]); 1527} 1528 1529void 1530NSGigE::transmit() 1531{ 1532 if (txFifo.empty()) { 1533 DPRINTF(Ethernet, "nothing to transmit\n"); 1534 return; 1535 } 1536 1537 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1538 maxTxFifoSize - txFifoAvail); 1539 if (interface->sendPacket(txFifo.front())) { 1540#if TRACING_ON 1541 if (DTRACE(Ethernet)) { 1542 if (txFifo.front()->isIpPkt()) { 1543 ip_header *ip = txFifo.front()->getIpHdr(); 1544 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1545 if (txFifo.front()->isTcpPkt()) { 1546 tcp_header *tcp = txFifo.front()->getTcpHdr(ip); 1547 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 1548 reverseEnd16(tcp->src_port_num), 1549 reverseEnd16(tcp->dest_port_num)); 1550 } 1551 } 1552 } 1553#endif 1554 1555 DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length); 1556 txBytes += txFifo.front()->length; 1557 txPackets++; 1558 1559 txFifoAvail += txFifo.front()->length; 1560 1561 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1562 txFifoAvail); 1563 txFifo.front() = NULL; 1564 txFifo.pop_front(); 1565 1566 /* 1567 * normally do a writeback of the descriptor here, and ONLY 1568 * after that is done, send this interrupt. but since our 1569 * stuff never actually fails, just do this interrupt here, 1570 * otherwise the code has to stray from this nice format. 1571 * besides, it's functionally the same. 1572 */ 1573 devIntrPost(ISR_TXOK); 1574 } else { 1575 DPRINTF(Ethernet, 1576 "May need to rethink always sending the descriptors back?\n"); 1577 } 1578 1579 if (!txFifo.empty() && !txEvent.scheduled()) { 1580 DPRINTF(Ethernet, "reschedule transmit\n"); 1581 txEvent.schedule(curTick + 1000); 1582 } 1583} 1584 1585void 1586NSGigE::txDmaReadCopy() 1587{ 1588 assert(txDmaState == dmaReading); 1589 1590 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1591 txDmaState = dmaIdle; 1592 1593 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1594 txDmaAddr, txDmaLen); 1595 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1596} 1597 1598bool 1599NSGigE::doTxDmaRead() 1600{ 1601 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1602 txDmaState = dmaReading; 1603 1604 if (dmaInterface && !txDmaFree) { 1605 if (dmaInterface->busy()) 1606 txDmaState = dmaReadWaiting; 1607 else 1608 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1609 &txDmaReadEvent, true); 1610 return true; 1611 } 1612 1613 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1614 txDmaReadCopy(); 1615 return false; 1616 } 1617 1618 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1619 Tick start = curTick + dmaReadDelay + factor; 1620 txDmaReadEvent.schedule(start); 1621 return true; 1622} 1623 1624void 1625NSGigE::txDmaReadDone() 1626{ 1627 assert(txDmaState == dmaReading); 1628 txDmaReadCopy(); 1629 1630 // If the receive state machine has a pending DMA, let it go first 1631 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1632 rxKick(); 1633 1634 txKick(); 1635} 1636 1637void 1638NSGigE::txDmaWriteCopy() 1639{ 1640 assert(txDmaState == dmaWriting); 1641 1642 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1643 txDmaState = dmaIdle; 1644 1645 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1646 txDmaAddr, txDmaLen); 1647 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1648} 1649 1650bool 1651NSGigE::doTxDmaWrite() 1652{ 1653 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1654 txDmaState = dmaWriting; 1655 1656 if (dmaInterface && !txDmaFree) { 1657 if (dmaInterface->busy()) 1658 txDmaState = dmaWriteWaiting; 1659 else 1660 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1661 &txDmaWriteEvent, true); 1662 return true; 1663 } 1664 1665 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1666 txDmaWriteCopy(); 1667 return false; 1668 } 1669 1670 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1671 Tick start = curTick + dmaWriteDelay + factor; 1672 txDmaWriteEvent.schedule(start); 1673 return true; 1674} 1675 1676void 1677NSGigE::txDmaWriteDone() 1678{ 1679 assert(txDmaState == dmaWriting); 1680 txDmaWriteCopy(); 1681 1682 // If the receive state machine has a pending DMA, let it go first 1683 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1684 rxKick(); 1685 1686 txKick(); 1687} 1688 1689void 1690NSGigE::txKick() 1691{ 1692 DPRINTF(EthernetSM, "transmit kick txState=%s\n", 1693 NsTxStateStrings[txState]); 1694 1695 if (txKickTick > curTick) { 1696 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1697 txKickTick); 1698 1699 return; 1700 } 1701 1702 next: 1703 switch(txDmaState) { 1704 case dmaReadWaiting: 1705 if (doTxDmaRead()) 1706 goto exit; 1707 break; 1708 case dmaWriteWaiting: 1709 if (doTxDmaWrite()) 1710 goto exit; 1711 break; 1712 default: 1713 break; 1714 } 1715 1716 switch (txState) { 1717 case txIdle: 1718 if (!txEnable) { 1719 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1720 goto exit; 1721 } 1722 1723 if (CTDD) { 1724 txState = txDescRefr; 1725 1726 txDmaAddr = regs.txdp & 0x3fffffff; 1727 txDmaData = &txDescCache + offsetof(ns_desc, link); 1728 txDmaLen = sizeof(txDescCache.link); 1729 txDmaFree = dmaDescFree; 1730 1731 descDmaReads++; 1732 descDmaRdBytes += txDmaLen; 1733 1734 if (doTxDmaRead()) 1735 goto exit; 1736 1737 } else { 1738 txState = txDescRead; 1739 1740 txDmaAddr = regs.txdp & 0x3fffffff; 1741 txDmaData = &txDescCache; 1742 txDmaLen = sizeof(ns_desc); 1743 txDmaFree = dmaDescFree; 1744 1745 descDmaReads++; 1746 descDmaRdBytes += txDmaLen; 1747 1748 if (doTxDmaRead()) 1749 goto exit; 1750 } 1751 break; 1752 1753 case txDescRefr: 1754 if (txDmaState != dmaIdle) 1755 goto exit; 1756 1757 txState = txAdvance; 1758 break; 1759 1760 case txDescRead: 1761 if (txDmaState != dmaIdle) 1762 goto exit; 1763 1764 DPRINTF(EthernetDesc, 1765 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1766 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 1767 txDescCache.extsts); 1768 1769 if (txDescCache.cmdsts & CMDSTS_OWN) { 1770 txState = txFifoBlock; 1771 txFragPtr = txDescCache.bufptr; 1772 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1773 } else { 1774 devIntrPost(ISR_TXIDLE); 1775 txState = txIdle; 1776 goto exit; 1777 } 1778 break; 1779 1780 case txFifoBlock: 1781 if (!txPacket) { 1782 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 1783 txPacket = new EtherPacket; 1784 txPacket->data = new uint8_t[16384]; 1785 txPacketBufPtr = txPacket->data; 1786 } 1787 1788 if (txDescCnt == 0) { 1789 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 1790 if (txDescCache.cmdsts & CMDSTS_MORE) { 1791 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1792 txState = txDescWrite; 1793 1794 txDescCache.cmdsts &= ~CMDSTS_OWN; 1795 1796 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1797 txDmaAddr &= 0x3fffffff; 1798 txDmaData = &(txDescCache.cmdsts); 1799 txDmaLen = sizeof(txDescCache.cmdsts); 1800 txDmaFree = dmaDescFree; 1801 1802 if (doTxDmaWrite()) 1803 goto exit; 1804 1805 } else { /* this packet is totally done */ 1806 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1807 /* deal with the the packet that just finished */ 1808 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 1809 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1810 udpChecksum(txPacket, true); 1811 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1812 tcpChecksum(txPacket, true); 1813 txTCPChecksums++; 1814 } 1815 if (txDescCache.extsts & EXTSTS_IPPKT) { 1816 ipChecksum(txPacket, true); 1817 txIPChecksums++; 1818 } 1819 } 1820 1821 txPacket->length = txPacketBufPtr - txPacket->data; 1822 // this is just because the receive can't handle a 1823 // packet bigger want to make sure 1824 assert(txPacket->length <= 1514); 1825 txFifo.push_back(txPacket); 1826 1827 /* 1828 * this following section is not tqo spec, but 1829 * functionally shouldn't be any different. normally, 1830 * the chip will wait til the transmit has occurred 1831 * before writing back the descriptor because it has 1832 * to wait to see that it was successfully transmitted 1833 * to decide whether to set CMDSTS_OK or not. 1834 * however, in the simulator since it is always 1835 * successfully transmitted, and writing it exactly to 1836 * spec would complicate the code, we just do it here 1837 */ 1838 1839 txDescCache.cmdsts &= ~CMDSTS_OWN; 1840 txDescCache.cmdsts |= CMDSTS_OK; 1841 1842 DPRINTF(EthernetDesc, 1843 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 1844 txDescCache.cmdsts, txDescCache.extsts); 1845 1846 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1847 txDmaAddr &= 0x3fffffff; 1848 txDmaData = &(txDescCache.cmdsts); 1849 txDmaLen = sizeof(txDescCache.cmdsts) + 1850 sizeof(txDescCache.extsts); 1851 txDmaFree = dmaDescFree; 1852 1853 descDmaWrites++; 1854 descDmaWrBytes += txDmaLen; 1855 1856 transmit(); 1857 txPacket = 0; 1858 1859 if (!txEnable) { 1860 DPRINTF(EthernetSM, "halting TX state machine\n"); 1861 txState = txIdle; 1862 goto exit; 1863 } else 1864 txState = txAdvance; 1865 1866 if (doTxDmaWrite()) 1867 goto exit; 1868 } 1869 } else { 1870 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 1871 if (txFifoAvail) { 1872 txState = txFragRead; 1873 1874 /* 1875 * The number of bytes transferred is either whatever 1876 * is left in the descriptor (txDescCnt), or if there 1877 * is not enough room in the fifo, just whatever room 1878 * is left in the fifo 1879 */ 1880 txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); 1881 1882 txDmaAddr = txFragPtr & 0x3fffffff; 1883 txDmaData = txPacketBufPtr; 1884 txDmaLen = txXferLen; 1885 txDmaFree = dmaDataFree; 1886 1887 if (doTxDmaRead()) 1888 goto exit; 1889 } else { 1890 txState = txFifoBlock; 1891 transmit(); 1892 1893 goto exit; 1894 } 1895 1896 } 1897 break; 1898 1899 case txFragRead: 1900 if (txDmaState != dmaIdle) 1901 goto exit; 1902 1903 txPacketBufPtr += txXferLen; 1904 txFragPtr += txXferLen; 1905 txDescCnt -= txXferLen; 1906 txFifoAvail -= txXferLen; 1907 1908 txState = txFifoBlock; 1909 break; 1910 1911 case txDescWrite: 1912 if (txDmaState != dmaIdle) 1913 goto exit; 1914 1915 if (txDescCache.cmdsts & CMDSTS_INTR) 1916 devIntrPost(ISR_TXDESC); 1917 1918 txState = txAdvance; 1919 break; 1920 1921 case txAdvance: 1922 if (txDescCache.link == 0) { 1923 devIntrPost(ISR_TXIDLE); 1924 txState = txIdle; 1925 goto exit; 1926 } else { 1927 txState = txDescRead; 1928 regs.txdp = txDescCache.link; 1929 CTDD = false; 1930 1931 txDmaAddr = txDescCache.link & 0x3fffffff; 1932 txDmaData = &txDescCache; 1933 txDmaLen = sizeof(ns_desc); 1934 txDmaFree = dmaDescFree; 1935 1936 if (doTxDmaRead()) 1937 goto exit; 1938 } 1939 break; 1940 1941 default: 1942 panic("invalid state"); 1943 } 1944 1945 DPRINTF(EthernetSM, "entering next txState=%s\n", 1946 NsTxStateStrings[txState]); 1947 1948 goto next; 1949 1950 exit: 1951 /** 1952 * @todo do we want to schedule a future kick? 1953 */ 1954 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1955 NsTxStateStrings[txState]); 1956} 1957 1958void 1959NSGigE::transferDone() 1960{ 1961 if (txFifo.empty()) { 1962 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1963 return; 1964 } 1965 1966 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1967 1968 if (txEvent.scheduled()) 1969 txEvent.reschedule(curTick + 1); 1970 else 1971 txEvent.schedule(curTick + 1); 1972} 1973 1974bool 1975NSGigE::rxFilter(PacketPtr packet) 1976{ 1977 bool drop = true; 1978 string type; 1979 1980 if (packet->IsUnicast()) { 1981 type = "unicast"; 1982 1983 // If we're accepting all unicast addresses 1984 if (acceptUnicast) 1985 drop = false; 1986 1987 // If we make a perfect match 1988 if (acceptPerfect && 1989 memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) 1990 drop = false; 1991 1992 eth_header *eth = (eth_header *) packet->data; 1993 if ((acceptArp) && (eth->type == 0x608)) 1994 drop = false; 1995 1996 } else if (packet->IsBroadcast()) { 1997 type = "broadcast"; 1998 1999 // if we're accepting broadcasts 2000 if (acceptBroadcast) 2001 drop = false; 2002 2003 } else if (packet->IsMulticast()) { 2004 type = "multicast"; 2005 2006 // if we're accepting all multicasts 2007 if (acceptMulticast) 2008 drop = false; 2009 2010 } else { 2011 type = "unknown"; 2012 2013 // oh well, punt on this one 2014 } 2015 2016 if (drop) { 2017 DPRINTF(Ethernet, "rxFilter drop\n"); 2018 DDUMP(EthernetData, packet->data, packet->length); 2019 } 2020 2021 return drop; 2022} 2023 2024bool 2025NSGigE::recvPacket(PacketPtr packet) 2026{ 2027 rxBytes += packet->length; 2028 rxPackets++; 2029 2030 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2031 maxRxFifoSize - rxFifoCnt); 2032 2033 if (!rxEnable) { 2034 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2035 debug_break(); 2036 interface->recvDone(); 2037 return true; 2038 } 2039 2040 if (rxFilterEnable && rxFilter(packet)) { 2041 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2042 interface->recvDone(); 2043 return true; 2044 } 2045 2046 if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { 2047 DPRINTF(Ethernet, 2048 "packet will not fit in receive buffer...packet dropped\n"); 2049 devIntrPost(ISR_RXORN); 2050 return false; 2051 } 2052 2053 rxFifo.push_back(packet); 2054 rxFifoCnt += packet->length; 2055 interface->recvDone(); 2056 2057 rxKick(); 2058 return true; 2059} 2060 2061/** 2062 * does a udp checksum. if gen is true, then it generates it and puts 2063 * it in the right place else, it just checks what it calculates 2064 * against the value in the header in packet 2065 */ 2066bool 2067NSGigE::udpChecksum(PacketPtr packet, bool gen) 2068{ 2069 ip_header *ip = packet->getIpHdr(); 2070 udp_header *hdr = packet->getUdpHdr(ip); 2071 2072 pseudo_header *pseudo = new pseudo_header; 2073 2074 pseudo->src_ip_addr = ip->src_ip_addr; 2075 pseudo->dest_ip_addr = ip->dest_ip_addr; 2076 pseudo->protocol = ip->protocol; 2077 pseudo->len = hdr->len; 2078 2079 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2080 (uint32_t) hdr->len); 2081 2082 delete pseudo; 2083 if (gen) 2084 hdr->chksum = cksum; 2085 else 2086 if (cksum != 0) 2087 return false; 2088 2089 return true; 2090} 2091 2092bool 2093NSGigE::tcpChecksum(PacketPtr packet, bool gen) 2094{ 2095 ip_header *ip = packet->getIpHdr(); 2096 tcp_header *hdr = packet->getTcpHdr(ip); 2097 2098 uint16_t cksum; 2099 pseudo_header *pseudo = new pseudo_header; 2100 if (!gen) { 2101 pseudo->src_ip_addr = ip->src_ip_addr; 2102 pseudo->dest_ip_addr = ip->dest_ip_addr; 2103 pseudo->protocol = reverseEnd16(ip->protocol); 2104 pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - 2105 (ip->vers_len & 0xf)*4); 2106 2107 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2108 (uint32_t) reverseEnd16(pseudo->len)); 2109 } else { 2110 pseudo->src_ip_addr = 0; 2111 pseudo->dest_ip_addr = 0; 2112 pseudo->protocol = hdr->chksum; 2113 pseudo->len = 0; 2114 hdr->chksum = 0; 2115 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2116 (uint32_t) (reverseEnd16(ip->dgram_len) - 2117 (ip->vers_len & 0xf)*4)); 2118 } 2119 2120 delete pseudo; 2121 if (gen) 2122 hdr->chksum = cksum; 2123 else 2124 if (cksum != 0) 2125 return false; 2126 2127 return true; 2128} 2129 2130bool 2131NSGigE::ipChecksum(PacketPtr packet, bool gen) 2132{ 2133 ip_header *hdr = packet->getIpHdr(); 2134 2135 uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, 2136 (hdr->vers_len & 0xf)*4); 2137 2138 if (gen) { 2139 DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum); 2140 hdr->hdr_chksum = cksum; 2141 } 2142 else 2143 if (cksum != 0) 2144 return false; 2145 2146 return true; 2147} 2148 2149uint16_t 2150NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) 2151{ 2152 uint32_t sum = 0; 2153 2154 uint16_t last_pad = 0; 2155 if (len & 1) { 2156 last_pad = buf[len/2] & 0xff; 2157 len--; 2158 sum += last_pad; 2159 } 2160 2161 if (pseudo) { 2162 sum = pseudo[0] + pseudo[1] + pseudo[2] + 2163 pseudo[3] + pseudo[4] + pseudo[5]; 2164 } 2165 2166 for (int i=0; i < (len/2); ++i) { 2167 sum += buf[i]; 2168 } 2169 2170 while (sum >> 16) 2171 sum = (sum >> 16) + (sum & 0xffff); 2172 2173 return ~sum; 2174} 2175 2176//===================================================================== 2177// 2178// 2179void 2180NSGigE::serialize(ostream &os) 2181{ 2182 // Serialize the PciDev base class 2183 PciDev::serialize(os); 2184 2185 /* 2186 * Finalize any DMA events now. 2187 */ 2188 if (rxDmaReadEvent.scheduled()) 2189 rxDmaReadCopy(); 2190 if (rxDmaWriteEvent.scheduled()) 2191 rxDmaWriteCopy(); 2192 if (txDmaReadEvent.scheduled()) 2193 txDmaReadCopy(); 2194 if (txDmaWriteEvent.scheduled()) 2195 txDmaWriteCopy(); 2196 2197 /* 2198 * Serialize the device registers 2199 */ 2200 SERIALIZE_SCALAR(regs.command); 2201 SERIALIZE_SCALAR(regs.config); 2202 SERIALIZE_SCALAR(regs.mear); 2203 SERIALIZE_SCALAR(regs.ptscr); 2204 SERIALIZE_SCALAR(regs.isr); 2205 SERIALIZE_SCALAR(regs.imr); 2206 SERIALIZE_SCALAR(regs.ier); 2207 SERIALIZE_SCALAR(regs.ihr); 2208 SERIALIZE_SCALAR(regs.txdp); 2209 SERIALIZE_SCALAR(regs.txdp_hi); 2210 SERIALIZE_SCALAR(regs.txcfg); 2211 SERIALIZE_SCALAR(regs.gpior); 2212 SERIALIZE_SCALAR(regs.rxdp); 2213 SERIALIZE_SCALAR(regs.rxdp_hi); 2214 SERIALIZE_SCALAR(regs.rxcfg); 2215 SERIALIZE_SCALAR(regs.pqcr); 2216 SERIALIZE_SCALAR(regs.wcsr); 2217 SERIALIZE_SCALAR(regs.pcr); 2218 SERIALIZE_SCALAR(regs.rfcr); 2219 SERIALIZE_SCALAR(regs.rfdr); 2220 SERIALIZE_SCALAR(regs.srr); 2221 SERIALIZE_SCALAR(regs.mibc); 2222 SERIALIZE_SCALAR(regs.vrcr); 2223 SERIALIZE_SCALAR(regs.vtcr); 2224 SERIALIZE_SCALAR(regs.vdr); 2225 SERIALIZE_SCALAR(regs.ccsr); 2226 SERIALIZE_SCALAR(regs.tbicr); 2227 SERIALIZE_SCALAR(regs.tbisr); 2228 SERIALIZE_SCALAR(regs.tanar); 2229 SERIALIZE_SCALAR(regs.tanlpar); 2230 SERIALIZE_SCALAR(regs.taner); 2231 SERIALIZE_SCALAR(regs.tesr); 2232 2233 SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2234 2235 SERIALIZE_SCALAR(ioEnable); 2236 2237 /* 2238 * Serialize the data Fifos 2239 */ 2240 int txNumPkts = txFifo.size(); 2241 SERIALIZE_SCALAR(txNumPkts); 2242 int i = 0; 2243 pktiter_t end = txFifo.end(); 2244 for (pktiter_t p = txFifo.begin(); p != end; ++p) { 2245 nameOut(os, csprintf("%s.txFifo%d", name(), i++)); 2246 (*p)->serialize(os); 2247 } 2248 2249 int rxNumPkts = rxFifo.size(); 2250 SERIALIZE_SCALAR(rxNumPkts); 2251 i = 0; 2252 end = rxFifo.end(); 2253 for (pktiter_t p = rxFifo.begin(); p != end; ++p) { 2254 nameOut(os, csprintf("%s.rxFifo%d", name(), i++)); 2255 (*p)->serialize(os); 2256 } 2257 2258 /* 2259 * Serialize the various helper variables 2260 */ 2261 bool txPacketExists = txPacket; 2262 SERIALIZE_SCALAR(txPacketExists); 2263 if (txPacketExists) { 2264 nameOut(os, csprintf("%s.txPacket", name())); 2265 txPacket->serialize(os); 2266 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2267 SERIALIZE_SCALAR(txPktBufPtr); 2268 } 2269 2270 bool rxPacketExists = rxPacket; 2271 SERIALIZE_SCALAR(rxPacketExists); 2272 if (rxPacketExists) { 2273 nameOut(os, csprintf("%s.rxPacket", name())); 2274 rxPacket->serialize(os); 2275 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2276 SERIALIZE_SCALAR(rxPktBufPtr); 2277 } 2278 2279 SERIALIZE_SCALAR(txXferLen); 2280 SERIALIZE_SCALAR(rxXferLen); 2281 2282 /* 2283 * Serialize DescCaches 2284 */ 2285 SERIALIZE_SCALAR(txDescCache.link); 2286 SERIALIZE_SCALAR(txDescCache.bufptr); 2287 SERIALIZE_SCALAR(txDescCache.cmdsts); 2288 SERIALIZE_SCALAR(txDescCache.extsts); 2289 SERIALIZE_SCALAR(rxDescCache.link); 2290 SERIALIZE_SCALAR(rxDescCache.bufptr); 2291 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2292 SERIALIZE_SCALAR(rxDescCache.extsts); 2293 2294 /* 2295 * Serialize tx state machine 2296 */ 2297 int txState = this->txState; 2298 SERIALIZE_SCALAR(txState); 2299 SERIALIZE_SCALAR(txEnable); 2300 SERIALIZE_SCALAR(CTDD); 2301 SERIALIZE_SCALAR(txFifoAvail); 2302 SERIALIZE_SCALAR(txFragPtr); 2303 SERIALIZE_SCALAR(txDescCnt); 2304 int txDmaState = this->txDmaState; 2305 SERIALIZE_SCALAR(txDmaState); 2306 2307 /* 2308 * Serialize rx state machine 2309 */ 2310 int rxState = this->rxState; 2311 SERIALIZE_SCALAR(rxState); 2312 SERIALIZE_SCALAR(rxEnable); 2313 SERIALIZE_SCALAR(CRDD); 2314 SERIALIZE_SCALAR(rxPktBytes); 2315 SERIALIZE_SCALAR(rxFifoCnt); 2316 SERIALIZE_SCALAR(rxDescCnt); 2317 int rxDmaState = this->rxDmaState; 2318 SERIALIZE_SCALAR(rxDmaState); 2319 2320 SERIALIZE_SCALAR(extstsEnable); 2321 2322 /* 2323 * If there's a pending transmit, store the time so we can 2324 * reschedule it later 2325 */ 2326 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2327 SERIALIZE_SCALAR(transmitTick); 2328 2329 /* 2330 * receive address filter settings 2331 */ 2332 SERIALIZE_SCALAR(rxFilterEnable); 2333 SERIALIZE_SCALAR(acceptBroadcast); 2334 SERIALIZE_SCALAR(acceptMulticast); 2335 SERIALIZE_SCALAR(acceptUnicast); 2336 SERIALIZE_SCALAR(acceptPerfect); 2337 SERIALIZE_SCALAR(acceptArp); 2338 2339 /* 2340 * Keep track of pending interrupt status. 2341 */ 2342 SERIALIZE_SCALAR(intrTick); 2343 SERIALIZE_SCALAR(cpuPendingIntr); 2344 Tick intrEventTick = 0; 2345 if (intrEvent) 2346 intrEventTick = intrEvent->when(); 2347 SERIALIZE_SCALAR(intrEventTick); 2348 2349} 2350 2351void 2352NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2353{ 2354 // Unserialize the PciDev base class 2355 PciDev::unserialize(cp, section); 2356 2357 UNSERIALIZE_SCALAR(regs.command); 2358 UNSERIALIZE_SCALAR(regs.config); 2359 UNSERIALIZE_SCALAR(regs.mear); 2360 UNSERIALIZE_SCALAR(regs.ptscr); 2361 UNSERIALIZE_SCALAR(regs.isr); 2362 UNSERIALIZE_SCALAR(regs.imr); 2363 UNSERIALIZE_SCALAR(regs.ier); 2364 UNSERIALIZE_SCALAR(regs.ihr); 2365 UNSERIALIZE_SCALAR(regs.txdp); 2366 UNSERIALIZE_SCALAR(regs.txdp_hi); 2367 UNSERIALIZE_SCALAR(regs.txcfg); 2368 UNSERIALIZE_SCALAR(regs.gpior); 2369 UNSERIALIZE_SCALAR(regs.rxdp); 2370 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2371 UNSERIALIZE_SCALAR(regs.rxcfg); 2372 UNSERIALIZE_SCALAR(regs.pqcr); 2373 UNSERIALIZE_SCALAR(regs.wcsr); 2374 UNSERIALIZE_SCALAR(regs.pcr); 2375 UNSERIALIZE_SCALAR(regs.rfcr); 2376 UNSERIALIZE_SCALAR(regs.rfdr); 2377 UNSERIALIZE_SCALAR(regs.srr); 2378 UNSERIALIZE_SCALAR(regs.mibc); 2379 UNSERIALIZE_SCALAR(regs.vrcr); 2380 UNSERIALIZE_SCALAR(regs.vtcr); 2381 UNSERIALIZE_SCALAR(regs.vdr); 2382 UNSERIALIZE_SCALAR(regs.ccsr); 2383 UNSERIALIZE_SCALAR(regs.tbicr); 2384 UNSERIALIZE_SCALAR(regs.tbisr); 2385 UNSERIALIZE_SCALAR(regs.tanar); 2386 UNSERIALIZE_SCALAR(regs.tanlpar); 2387 UNSERIALIZE_SCALAR(regs.taner); 2388 UNSERIALIZE_SCALAR(regs.tesr); 2389 2390 UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2391 2392 UNSERIALIZE_SCALAR(ioEnable); 2393 2394 /* 2395 * unserialize the data fifos 2396 */ 2397 int txNumPkts; 2398 UNSERIALIZE_SCALAR(txNumPkts); 2399 int i; 2400 for (i = 0; i < txNumPkts; ++i) { 2401 PacketPtr p = new EtherPacket; 2402 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2403 txFifo.push_back(p); 2404 } 2405 2406 int rxNumPkts; 2407 UNSERIALIZE_SCALAR(rxNumPkts); 2408 for (i = 0; i < rxNumPkts; ++i) { 2409 PacketPtr p = new EtherPacket; 2410 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2411 rxFifo.push_back(p); 2412 } 2413 2414 /* 2415 * unserialize the various helper variables 2416 */ 2417 bool txPacketExists; 2418 UNSERIALIZE_SCALAR(txPacketExists); 2419 if (txPacketExists) { 2420 txPacket = new EtherPacket; 2421 txPacket->unserialize(cp, csprintf("%s.txPacket", section)); 2422 uint32_t txPktBufPtr; 2423 UNSERIALIZE_SCALAR(txPktBufPtr); 2424 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2425 } else 2426 txPacket = 0; 2427 2428 bool rxPacketExists; 2429 UNSERIALIZE_SCALAR(rxPacketExists); 2430 rxPacket = 0; 2431 if (rxPacketExists) { 2432 rxPacket = new EtherPacket; 2433 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 2434 uint32_t rxPktBufPtr; 2435 UNSERIALIZE_SCALAR(rxPktBufPtr); 2436 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2437 } else 2438 rxPacket = 0; 2439 2440 UNSERIALIZE_SCALAR(txXferLen); 2441 UNSERIALIZE_SCALAR(rxXferLen); 2442 2443 /* 2444 * Unserialize DescCaches 2445 */ 2446 UNSERIALIZE_SCALAR(txDescCache.link); 2447 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2448 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2449 UNSERIALIZE_SCALAR(txDescCache.extsts); 2450 UNSERIALIZE_SCALAR(rxDescCache.link); 2451 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2452 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2453 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2454 2455 /* 2456 * unserialize tx state machine 2457 */ 2458 int txState; 2459 UNSERIALIZE_SCALAR(txState); 2460 this->txState = (TxState) txState; 2461 UNSERIALIZE_SCALAR(txEnable); 2462 UNSERIALIZE_SCALAR(CTDD); 2463 UNSERIALIZE_SCALAR(txFifoAvail); 2464 UNSERIALIZE_SCALAR(txFragPtr); 2465 UNSERIALIZE_SCALAR(txDescCnt); 2466 int txDmaState; 2467 UNSERIALIZE_SCALAR(txDmaState); 2468 this->txDmaState = (DmaState) txDmaState; 2469 2470 /* 2471 * unserialize rx state machine 2472 */ 2473 int rxState; 2474 UNSERIALIZE_SCALAR(rxState); 2475 this->rxState = (RxState) rxState; 2476 UNSERIALIZE_SCALAR(rxEnable); 2477 UNSERIALIZE_SCALAR(CRDD); 2478 UNSERIALIZE_SCALAR(rxPktBytes); 2479 UNSERIALIZE_SCALAR(rxFifoCnt); 2480 UNSERIALIZE_SCALAR(rxDescCnt); 2481 int rxDmaState; 2482 UNSERIALIZE_SCALAR(rxDmaState); 2483 this->rxDmaState = (DmaState) rxDmaState; 2484 2485 UNSERIALIZE_SCALAR(extstsEnable); 2486 2487 /* 2488 * If there's a pending transmit, reschedule it now 2489 */ 2490 Tick transmitTick; 2491 UNSERIALIZE_SCALAR(transmitTick); 2492 if (transmitTick) 2493 txEvent.schedule(curTick + transmitTick); 2494 2495 /* 2496 * unserialize receive address filter settings 2497 */ 2498 UNSERIALIZE_SCALAR(rxFilterEnable); 2499 UNSERIALIZE_SCALAR(acceptBroadcast); 2500 UNSERIALIZE_SCALAR(acceptMulticast); 2501 UNSERIALIZE_SCALAR(acceptUnicast); 2502 UNSERIALIZE_SCALAR(acceptPerfect); 2503 UNSERIALIZE_SCALAR(acceptArp); 2504 2505 /* 2506 * Keep track of pending interrupt status. 2507 */ 2508 UNSERIALIZE_SCALAR(intrTick); 2509 UNSERIALIZE_SCALAR(cpuPendingIntr); 2510 Tick intrEventTick; 2511 UNSERIALIZE_SCALAR(intrEventTick); 2512 if (intrEventTick) { 2513 intrEvent = new IntrEvent(this, true); 2514 intrEvent->schedule(intrEventTick); 2515 } 2516 2517 /* 2518 * re-add addrRanges to bus bridges 2519 */ 2520 if (pioInterface) { 2521 pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1); 2522 pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1); 2523 } 2524} 2525 2526Tick 2527NSGigE::cacheAccess(MemReqPtr &req) 2528{ 2529 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2530 req->paddr, req->paddr - addr); 2531 return curTick + pioLatency; 2532} 2533//===================================================================== 2534 2535 2536//********** helper functions****************************************** 2537 2538uint16_t reverseEnd16(uint16_t num) 2539{ 2540 uint16_t reverse = (num & 0xff)<<8; 2541 reverse += ((num & 0xff00) >> 8); 2542 return reverse; 2543} 2544 2545uint32_t reverseEnd32(uint32_t num) 2546{ 2547 uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16; 2548 reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8)); 2549 return reverse; 2550} 2551 2552 2553 2554//===================================================================== 2555 2556BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2557 2558 SimObjectParam<EtherInt *> peer; 2559 SimObjectParam<NSGigE *> device; 2560 2561END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2562 2563BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2564 2565 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2566 INIT_PARAM(device, "Ethernet device of this interface") 2567 2568END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2569 2570CREATE_SIM_OBJECT(NSGigEInt) 2571{ 2572 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2573 2574 EtherInt *p = (EtherInt *)peer; 2575 if (p) { 2576 dev_int->setPeer(p); 2577 p->setPeer(dev_int); 2578 } 2579 2580 return dev_int; 2581} 2582 2583REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2584 2585 2586BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2587 2588 Param<Tick> tx_delay; 2589 Param<Tick> rx_delay; 2590 SimObjectParam<IntrControl *> intr_ctrl; 2591 Param<Tick> intr_delay; 2592 SimObjectParam<MemoryController *> mmu; 2593 SimObjectParam<PhysicalMemory *> physmem; 2594 Param<bool> rx_filter; 2595 Param<string> hardware_address; 2596 SimObjectParam<Bus*> header_bus; 2597 SimObjectParam<Bus*> payload_bus; 2598 SimObjectParam<HierParams *> hier; 2599 Param<Tick> pio_latency; 2600 Param<bool> dma_desc_free; 2601 Param<bool> dma_data_free; 2602 Param<Tick> dma_read_delay; 2603 Param<Tick> dma_write_delay; 2604 Param<Tick> dma_read_factor; 2605 Param<Tick> dma_write_factor; 2606 SimObjectParam<PciConfigAll *> configspace; 2607 SimObjectParam<PciConfigData *> configdata; 2608 SimObjectParam<Tsunami *> tsunami; 2609 Param<uint32_t> pci_bus; 2610 Param<uint32_t> pci_dev; 2611 Param<uint32_t> pci_func; 2612 Param<uint32_t> tx_fifo_size; 2613 Param<uint32_t> rx_fifo_size; 2614 2615END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2616 2617BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2618 2619 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 2620 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 2621 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 2622 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), 2623 INIT_PARAM(mmu, "Memory Controller"), 2624 INIT_PARAM(physmem, "Physical Memory"), 2625 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2626 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2627 "00:99:00:00:00:01"), 2628 INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), 2629 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2630 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2631 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2632 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2633 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2634 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2635 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2636 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2637 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2638 INIT_PARAM(configspace, "PCI Configspace"), 2639 INIT_PARAM(configdata, "PCI Config data"), 2640 INIT_PARAM(tsunami, "Tsunami"), 2641 INIT_PARAM(pci_bus, "PCI bus"), 2642 INIT_PARAM(pci_dev, "PCI device number"), 2643 INIT_PARAM(pci_func, "PCI function code"), 2644 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2645 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072) 2646 2647END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2648 2649 2650CREATE_SIM_OBJECT(NSGigE) 2651{ 2652 int eaddr[6]; 2653 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 2654 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 2655 2656 return new NSGigE(getInstanceName(), intr_ctrl, intr_delay, 2657 physmem, tx_delay, rx_delay, mmu, hier, header_bus, 2658 payload_bus, pio_latency, dma_desc_free, dma_data_free, 2659 dma_read_delay, dma_write_delay, dma_read_factor, 2660 dma_write_factor, configspace, configdata, 2661 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 2662 tx_fifo_size, rx_fifo_size); 2663} 2664 2665REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2666