ns_gige.cc revision 1035
12810SN/A/* 29614Srene.dejong@arm.com * Copyright (c) 2004 The Regents of The University of Michigan 38856Sandreas.hansson@arm.com * All rights reserved. 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68856Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78856Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98856Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118856Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128856Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138856Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A */ 282810SN/A 292810SN/A/* @file 302810SN/A * Device module for modelling the National Semiconductor 312810SN/A * DP83820 ethernet controller. Does not support priority queueing 322810SN/A */ 332810SN/A#include <cstdio> 342810SN/A#include <deque> 352810SN/A#include <string> 362810SN/A 372810SN/A#include "base/inet.hh" 382810SN/A#include "cpu/exec_context.hh" 392810SN/A#include "cpu/intr_control.hh" 402810SN/A#include "dev/dma.hh" 412810SN/A#include "dev/etherlink.hh" 422810SN/A#include "dev/ns_gige.hh" 432810SN/A#include "dev/pciconfigall.hh" 442810SN/A#include "dev/tsunami_cchip.hh" 452810SN/A#include "mem/bus/bus.hh" 462810SN/A#include "mem/bus/dma_interface.hh" 472810SN/A#include "mem/bus/pio_interface.hh" 4811486Snikos.nikoleris@arm.com#include "mem/bus/pio_interface_impl.hh" 4911486Snikos.nikoleris@arm.com#include "mem/functional_mem/memory_control.hh" 508232Snate@binkert.org#include "mem/functional_mem/physical_memory.hh" 519152Satgutier@umich.edu#include "sim/builder.hh" 5211486Snikos.nikoleris@arm.com#include "sim/host.hh" 5311486Snikos.nikoleris@arm.com#include "sim/sim_stats.hh" 549795Sandreas.hansson@arm.com#include "targetarch/vtophys.hh" 559795Sandreas.hansson@arm.com 5610263Satgutier@umich.educonst char *NsRxStateStrings[] = 578786Sgblack@eecs.umich.edu{ 582810SN/A "rxIdle", 592810SN/A "rxDescRefr", 602810SN/A "rxDescRead", 618856Sandreas.hansson@arm.com "rxFifoBlock", 628856Sandreas.hansson@arm.com "rxFragWrite", 638856Sandreas.hansson@arm.com "rxDescWrite", 648922Swilliam.wang@arm.com "rxAdvance" 658914Sandreas.hansson@arm.com}; 668856Sandreas.hansson@arm.com 678856Sandreas.hansson@arm.comconst char *NsTxStateStrings[] = 684475SN/A{ 6911053Sandreas.hansson@arm.com "txIdle", 705034SN/A "txDescRefr", 7110360Sandreas.hansson@arm.com "txDescRead", 7211377Sandreas.hansson@arm.com "txFifoBlock", 7311377Sandreas.hansson@arm.com "txFragRead", 7411053Sandreas.hansson@arm.com "txDescWrite", 7510693SMarco.Balboni@ARM.com "txAdvance" 7610693SMarco.Balboni@ARM.com}; 7710693SMarco.Balboni@ARM.com 789263Smrinmoy.ghosh@arm.comconst char *NsDmaState[] = 795034SN/A{ 8011331Sandreas.hansson@arm.com "dmaIdle", 8110884Sandreas.hansson@arm.com "dmaReading", 824626SN/A "dmaWriting", 8310360Sandreas.hansson@arm.com "dmaReadWaiting", 8411484Snikos.nikoleris@arm.com "dmaWriteWaiting" 855034SN/A}; 868883SAli.Saidi@ARM.com 878833Sdam.sunwoo@arm.comusing namespace std; 884458SN/A 8911377Sandreas.hansson@arm.com// helper function declarations 9011377Sandreas.hansson@arm.com// These functions reverse Endianness so we can evaluate network data 9111377Sandreas.hansson@arm.com// correctly 9211377Sandreas.hansson@arm.comuint16_t reverseEnd16(uint16_t); 9311377Sandreas.hansson@arm.comuint32_t reverseEnd32(uint32_t); 9411377Sandreas.hansson@arm.com 9511331Sandreas.hansson@arm.com/////////////////////////////////////////////////////////////////////// 9611331Sandreas.hansson@arm.com// 972810SN/A// NSGigE PCI Device 982810SN/A// 993013SN/ANSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, 1008856Sandreas.hansson@arm.com PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, 1012810SN/A MemoryController *mmu, HierParams *hier, Bus *header_bus, 1023013SN/A Bus *payload_bus, Tick pio_latency, bool dma_desc_free, 10310714Sandreas.hansson@arm.com bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, 1042810SN/A Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, 1059614Srene.dejong@arm.com PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, 1069614Srene.dejong@arm.com uint32_t func, bool rx_filter, const int eaddr[6], 1079614Srene.dejong@arm.com uint32_t tx_fifo_size, uint32_t rx_fifo_size) 10810345SCurtis.Dunham@arm.com : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), 10910714Sandreas.hansson@arm.com maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), 11010345SCurtis.Dunham@arm.com txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 1119614Srene.dejong@arm.com txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), 1122810SN/A CTDD(false), txFifoAvail(tx_fifo_size), 1132810SN/A txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 1142810SN/A rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), 1158856Sandreas.hansson@arm.com rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1162810SN/A rxDmaReadEvent(this), rxDmaWriteEvent(this), 1173013SN/A txDmaReadEvent(this), txDmaWriteEvent(this), 11810714Sandreas.hansson@arm.com dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free), 1193013SN/A txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0), 1208856Sandreas.hansson@arm.com txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false), 12110714Sandreas.hansson@arm.com acceptMulticast(false), acceptUnicast(false), 1228922Swilliam.wang@arm.com acceptPerfect(false), acceptArp(false), 1232897SN/A physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), 1242810SN/A intrEvent(0), interface(0) 1252810SN/A{ 12610344Sandreas.hansson@arm.com tsunami->ethernet = this; 12710344Sandreas.hansson@arm.com 12810344Sandreas.hansson@arm.com if (header_bus) { 12910714Sandreas.hansson@arm.com pioInterface = newPioInterface(name, hier, header_bus, this, 13010344Sandreas.hansson@arm.com &NSGigE::cacheAccess); 13110344Sandreas.hansson@arm.com 13210344Sandreas.hansson@arm.com pioLatency = pio_latency * header_bus->clockRatio; 13310713Sandreas.hansson@arm.com 13410344Sandreas.hansson@arm.com if (payload_bus) 1352844SN/A dmaInterface = new DMAInterface<Bus>(name + ".dma", 1362810SN/A header_bus, payload_bus, 1); 1372858SN/A else 1382858SN/A dmaInterface = new DMAInterface<Bus>(name + ".dma", 1398856Sandreas.hansson@arm.com header_bus, header_bus, 1); 1408922Swilliam.wang@arm.com } else if (payload_bus) { 1418711Sandreas.hansson@arm.com pioInterface = newPioInterface(name, hier, payload_bus, this, 14211331Sandreas.hansson@arm.com &NSGigE::cacheAccess); 1432858SN/A 1442858SN/A pioLatency = pio_latency * payload_bus->clockRatio; 1459294Sandreas.hansson@arm.com 1469294Sandreas.hansson@arm.com dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, 1478922Swilliam.wang@arm.com payload_bus, 1); 1488922Swilliam.wang@arm.com } 1498922Swilliam.wang@arm.com 1508922Swilliam.wang@arm.com 1518922Swilliam.wang@arm.com intrDelay = US2Ticks(intr_delay); 1528922Swilliam.wang@arm.com dmaReadDelay = dma_read_delay; 1538922Swilliam.wang@arm.com dmaWriteDelay = dma_write_delay; 1548922Swilliam.wang@arm.com dmaReadFactor = dma_read_factor; 1559294Sandreas.hansson@arm.com dmaWriteFactor = dma_write_factor; 1569294Sandreas.hansson@arm.com 1578922Swilliam.wang@arm.com regsReset(); 1588922Swilliam.wang@arm.com rom.perfectMatch[0] = eaddr[0]; 1598922Swilliam.wang@arm.com rom.perfectMatch[1] = eaddr[1]; 1608922Swilliam.wang@arm.com rom.perfectMatch[2] = eaddr[2]; 1618922Swilliam.wang@arm.com rom.perfectMatch[3] = eaddr[3]; 1628922Swilliam.wang@arm.com rom.perfectMatch[4] = eaddr[4]; 1638922Swilliam.wang@arm.com rom.perfectMatch[5] = eaddr[5]; 1644628SN/A} 16510821Sandreas.hansson@arm.com 16610821Sandreas.hansson@arm.comNSGigE::~NSGigE() 16710821Sandreas.hansson@arm.com{} 16810821Sandreas.hansson@arm.com 16910821Sandreas.hansson@arm.comvoid 17010821Sandreas.hansson@arm.comNSGigE::regStats() 17110821Sandreas.hansson@arm.com{ 17210821Sandreas.hansson@arm.com txBytes 17310821Sandreas.hansson@arm.com .name(name() + ".txBytes") 17410821Sandreas.hansson@arm.com .desc("Bytes Transmitted") 17510821Sandreas.hansson@arm.com .prereq(txBytes) 1762858SN/A ; 1772810SN/A 1782810SN/A rxBytes 1792810SN/A .name(name() + ".rxBytes") 1802810SN/A .desc("Bytes Received") 1812810SN/A .prereq(rxBytes) 1824022SN/A ; 1834022SN/A 1844022SN/A txPackets 1852810SN/A .name(name() + ".txPackets") 1862810SN/A .desc("Number of Packets Transmitted") 1878833Sdam.sunwoo@arm.com .prereq(txBytes) 1882810SN/A ; 1892810SN/A 1902810SN/A rxPackets 1912810SN/A .name(name() + ".rxPackets") 1928833Sdam.sunwoo@arm.com .desc("Number of Packets Received") 1938833Sdam.sunwoo@arm.com .prereq(rxBytes) 1948833Sdam.sunwoo@arm.com ; 1952810SN/A 1962810SN/A txIPChecksums 1974871SN/A .name(name() + ".txIPChecksums") 1984871SN/A .desc("Number of tx IP Checksums done by device") 1994871SN/A .precision(0) 2004871SN/A .prereq(txBytes) 20111455Sandreas.hansson@arm.com ; 20210885Sandreas.hansson@arm.com 2034871SN/A rxIPChecksums 2044871SN/A .name(name() + ".rxIPChecksums") 2054871SN/A .desc("Number of rx IP Checksums done by device") 2064871SN/A .precision(0) 2074871SN/A .prereq(rxBytes) 2082810SN/A ; 2092810SN/A 2102810SN/A txTCPChecksums 2118833Sdam.sunwoo@arm.com .name(name() + ".txTCPChecksums") 2122810SN/A .desc("Number of tx TCP Checksums done by device") 2134871SN/A .precision(0) 2148833Sdam.sunwoo@arm.com .prereq(txBytes) 2158833Sdam.sunwoo@arm.com ; 2168833Sdam.sunwoo@arm.com 2172810SN/A rxTCPChecksums 2182810SN/A .name(name() + ".rxTCPChecksums") 2192810SN/A .desc("Number of rx TCP Checksums done by device") 2202810SN/A .precision(0) 2218833Sdam.sunwoo@arm.com .prereq(rxBytes) 2222810SN/A ; 2234871SN/A 2248833Sdam.sunwoo@arm.com descDmaReads 2258833Sdam.sunwoo@arm.com .name(name() + ".descDMAReads") 2268833Sdam.sunwoo@arm.com .desc("Number of descriptors the device read w/ DMA") 2272810SN/A .precision(0) 2282810SN/A ; 2294022SN/A 2304022SN/A descDmaWrites 2314022SN/A .name(name() + ".descDMAWrites") 2322810SN/A .desc("Number of descriptors the device wrote w/ DMA") 2332810SN/A .precision(0) 2348833Sdam.sunwoo@arm.com ; 2352810SN/A 2362810SN/A descDmaRdBytes 2372810SN/A .name(name() + ".descDmaReadBytes") 2382810SN/A .desc("number of descriptor bytes read w/ DMA") 2398833Sdam.sunwoo@arm.com .precision(0) 2408833Sdam.sunwoo@arm.com ; 2418833Sdam.sunwoo@arm.com 2422810SN/A descDmaWrBytes 2432810SN/A .name(name() + ".descDmaWriteBytes") 2442810SN/A .desc("number of descriptor bytes write w/ DMA") 2452810SN/A .precision(0) 2462810SN/A ; 2478833Sdam.sunwoo@arm.com 2482810SN/A 2494871SN/A txBandwidth 2508833Sdam.sunwoo@arm.com .name(name() + ".txBandwidth") 2518833Sdam.sunwoo@arm.com .desc("Transmit Bandwidth (bits/s)") 2528833Sdam.sunwoo@arm.com .precision(0) 2532810SN/A .prereq(txBytes) 2542810SN/A ; 2552810SN/A 2562810SN/A rxBandwidth 2578833Sdam.sunwoo@arm.com .name(name() + ".rxBandwidth") 2582810SN/A .desc("Receive Bandwidth (bits/s)") 2594871SN/A .precision(0) 2608833Sdam.sunwoo@arm.com .prereq(rxBytes) 2618833Sdam.sunwoo@arm.com ; 2628833Sdam.sunwoo@arm.com 2632810SN/A txPacketRate 2642810SN/A .name(name() + ".txPPS") 2654022SN/A .desc("Packet Tranmission Rate (packets/s)") 2664022SN/A .precision(0) 2674022SN/A .prereq(txBytes) 2682810SN/A ; 2692810SN/A 2708833Sdam.sunwoo@arm.com rxPacketRate 2712810SN/A .name(name() + ".rxPPS") 2722810SN/A .desc("Packet Reception Rate (packets/s)") 2732810SN/A .precision(0) 2742810SN/A .prereq(rxBytes) 2758833Sdam.sunwoo@arm.com ; 2768833Sdam.sunwoo@arm.com 2778833Sdam.sunwoo@arm.com txBandwidth = txBytes * Stats::constant(8) / simSeconds; 2782810SN/A rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 2792810SN/A txPacketRate = txPackets / simSeconds; 2802810SN/A rxPacketRate = rxPackets / simSeconds; 2812810SN/A} 2822810SN/A 2838833Sdam.sunwoo@arm.com/** 2842810SN/A * This is to read the PCI general configuration registers 2854871SN/A */ 2868833Sdam.sunwoo@arm.comvoid 2878833Sdam.sunwoo@arm.comNSGigE::ReadConfig(int offset, int size, uint8_t *data) 2888833Sdam.sunwoo@arm.com{ 2892810SN/A if (offset < PCI_DEVICE_SPECIFIC) 2902810SN/A PciDev::ReadConfig(offset, size, data); 2912810SN/A else 2922810SN/A panic("Device specific PCI config space not implemented!\n"); 2938833Sdam.sunwoo@arm.com} 2942810SN/A 2954871SN/A/** 2968833Sdam.sunwoo@arm.com * This is to write to the PCI general configuration registers 2978833Sdam.sunwoo@arm.com */ 2988833Sdam.sunwoo@arm.comvoid 2992810SN/ANSGigE::WriteConfig(int offset, int size, uint32_t data) 3002810SN/A{ 3014022SN/A if (offset < PCI_DEVICE_SPECIFIC) 3024022SN/A PciDev::WriteConfig(offset, size, data); 3034022SN/A else 3042810SN/A panic("Device specific PCI config space not implemented!\n"); 3052810SN/A 3062810SN/A // Need to catch writes to BARs to update the PIO interface 3072810SN/A switch (offset) { 3082810SN/A // seems to work fine without all these PCI settings, but i 3092810SN/A // put in the IO to double check, an assertion will fail if we 3108833Sdam.sunwoo@arm.com // need to properly implement it 3112810SN/A case PCI_COMMAND: 3128833Sdam.sunwoo@arm.com if (config.data[offset] & PCI_CMD_IOSE) 3138833Sdam.sunwoo@arm.com ioEnable = true; 3148833Sdam.sunwoo@arm.com else 3152810SN/A ioEnable = false; 3162810SN/A 3172810SN/A#if 0 3182810SN/A if (config.data[offset] & PCI_CMD_BME) { 3192810SN/A bmEnabled = true; 3208833Sdam.sunwoo@arm.com } 3212810SN/A else { 3222810SN/A bmEnabled = false; 3238833Sdam.sunwoo@arm.com } 3248833Sdam.sunwoo@arm.com 3258833Sdam.sunwoo@arm.com if (config.data[offset] & PCI_CMD_MSE) { 3262810SN/A memEnable = true; 3272810SN/A } 3282810SN/A else { 3292810SN/A memEnable = false; 3308833Sdam.sunwoo@arm.com } 3312810SN/A#endif 3322810SN/A break; 3338833Sdam.sunwoo@arm.com 3348833Sdam.sunwoo@arm.com case PCI0_BASE_ADDR0: 3358833Sdam.sunwoo@arm.com if (BARAddrs[0] != 0) { 3362810SN/A if (pioInterface) 3372810SN/A pioInterface->addAddrRange(BARAddrs[0], 3384022SN/A BARAddrs[0] + BARSize[0] - 1); 3394022SN/A 3404022SN/A BARAddrs[0] &= PA_UNCACHED_MASK; 3412810SN/A } 3422810SN/A break; 3432810SN/A case PCI0_BASE_ADDR1: 3442810SN/A if (BARAddrs[1] != 0) { 3452810SN/A if (pioInterface) 3462810SN/A pioInterface->addAddrRange(BARAddrs[1], 3478833Sdam.sunwoo@arm.com BARAddrs[1] + BARSize[1] - 1); 3482810SN/A 3498833Sdam.sunwoo@arm.com BARAddrs[1] &= PA_UNCACHED_MASK; 3508833Sdam.sunwoo@arm.com } 3518833Sdam.sunwoo@arm.com break; 3522810SN/A } 3532810SN/A} 3542810SN/A 3552810SN/A/** 3562810SN/A * This reads the device registers, which are detailed in the NS83820 3578833Sdam.sunwoo@arm.com * spec sheet 3582810SN/A */ 3592810SN/AFault 3608833Sdam.sunwoo@arm.comNSGigE::read(MemReqPtr &req, uint8_t *data) 3618833Sdam.sunwoo@arm.com{ 3628833Sdam.sunwoo@arm.com assert(ioEnable); 3632810SN/A 3642810SN/A //The mask is to give you only the offset into the device register file 3652810SN/A Addr daddr = req->paddr & 0xfff; 3662810SN/A DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 3678833Sdam.sunwoo@arm.com daddr, req->paddr, req->vaddr, req->size); 3682810SN/A 3692810SN/A 3708833Sdam.sunwoo@arm.com // there are some reserved registers, you can see ns_gige_reg.h and 3718833Sdam.sunwoo@arm.com // the spec sheet for details 3728833Sdam.sunwoo@arm.com if (daddr > LAST && daddr <= RESERVED) { 3732810SN/A panic("Accessing reserved register"); 3742810SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 3754022SN/A ReadConfig(daddr & 0xff, req->size, data); 3764022SN/A return No_Fault; 3774022SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 3782810SN/A // don't implement all the MIB's. hopefully the kernel 3792810SN/A // doesn't actually DEPEND upon their values 3802810SN/A // MIB are just hardware stats keepers 3812810SN/A uint32_t ® = *(uint32_t *) data; 3822810SN/A reg = 0; 3832810SN/A return No_Fault; 3842810SN/A } else if (daddr > 0x3FC) 3852810SN/A panic("Something is messed up!\n"); 3868833Sdam.sunwoo@arm.com 3878833Sdam.sunwoo@arm.com switch (req->size) { 3888833Sdam.sunwoo@arm.com case sizeof(uint32_t): 3898833Sdam.sunwoo@arm.com { 3902810SN/A uint32_t ® = *(uint32_t *)data; 3912810SN/A 3922810SN/A switch (daddr) { 3932810SN/A case CR: 3942810SN/A reg = regs.command; 3958833Sdam.sunwoo@arm.com //these are supposed to be cleared on a read 3962810SN/A reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 3972810SN/A break; 3988833Sdam.sunwoo@arm.com 3998833Sdam.sunwoo@arm.com case CFG: 4008833Sdam.sunwoo@arm.com reg = regs.config; 4012810SN/A break; 4022810SN/A 4032810SN/A case MEAR: 4042810SN/A reg = regs.mear; 4058833Sdam.sunwoo@arm.com break; 4062810SN/A 4072810SN/A case PTSCR: 4088833Sdam.sunwoo@arm.com reg = regs.ptscr; 4098833Sdam.sunwoo@arm.com break; 4108833Sdam.sunwoo@arm.com 4112810SN/A case ISR: 4122810SN/A reg = regs.isr; 4132810SN/A devIntrClear(ISR_ALL); 4142810SN/A break; 4152810SN/A 4162810SN/A case IMR: 4172810SN/A reg = regs.imr; 4182810SN/A break; 4192810SN/A 4202810SN/A case IER: 4212810SN/A reg = regs.ier; 4222810SN/A break; 4232810SN/A 4242810SN/A case IHR: 4252810SN/A reg = regs.ihr; 4262810SN/A break; 4272810SN/A 4282810SN/A case TXDP: 4292810SN/A reg = regs.txdp; 4302810SN/A break; 4312810SN/A 4322810SN/A case TXDP_HI: 4332810SN/A reg = regs.txdp_hi; 4342810SN/A break; 4352810SN/A 4362810SN/A case TXCFG: 4372810SN/A reg = regs.txcfg; 43811436SRekai.GonzalezAlberquilla@arm.com break; 43911436SRekai.GonzalezAlberquilla@arm.com 44011436SRekai.GonzalezAlberquilla@arm.com case GPIOR: 44111436SRekai.GonzalezAlberquilla@arm.com reg = regs.gpior; 44211436SRekai.GonzalezAlberquilla@arm.com break; 44311436SRekai.GonzalezAlberquilla@arm.com 4444626SN/A case RXDP: 4458833Sdam.sunwoo@arm.com reg = regs.rxdp; 4464626SN/A break; 4474626SN/A 4488833Sdam.sunwoo@arm.com case RXDP_HI: 4494626SN/A reg = regs.rxdp_hi; 4508833Sdam.sunwoo@arm.com break; 4518833Sdam.sunwoo@arm.com 4528833Sdam.sunwoo@arm.com case RXCFG: 4534626SN/A reg = regs.rxcfg; 4544626SN/A break; 4554626SN/A 4564626SN/A case PQCR: 4574626SN/A reg = regs.pqcr; 4584626SN/A break; 4594626SN/A 4604626SN/A case WCSR: 4618833Sdam.sunwoo@arm.com reg = regs.wcsr; 4624626SN/A break; 4634626SN/A 4644626SN/A case PCR: 4654626SN/A reg = regs.pcr; 4668833Sdam.sunwoo@arm.com break; 4678833Sdam.sunwoo@arm.com 4688833Sdam.sunwoo@arm.com // see the spec sheet for how RFCR and RFDR work 4694626SN/A // basically, you write to RFCR to tell the machine 4704626SN/A // what you want to do next, then you act upon RFDR, 4714626SN/A // and the device will be prepared b/c of what you 4724626SN/A // wrote to RFCR 4734626SN/A case RFCR: 4748833Sdam.sunwoo@arm.com reg = regs.rfcr; 4754626SN/A break; 4764871SN/A 4778833Sdam.sunwoo@arm.com case RFDR: 4788833Sdam.sunwoo@arm.com switch (regs.rfcr & RFCR_RFADDR) { 4798833Sdam.sunwoo@arm.com case 0x000: 4804626SN/A reg = rom.perfectMatch[1]; 4814626SN/A reg = reg << 8; 4824626SN/A reg += rom.perfectMatch[0]; 4834626SN/A break; 4848833Sdam.sunwoo@arm.com case 0x002: 4854626SN/A reg = rom.perfectMatch[3] << 8; 4864871SN/A reg += rom.perfectMatch[2]; 4878833Sdam.sunwoo@arm.com break; 4888833Sdam.sunwoo@arm.com case 0x004: 4898833Sdam.sunwoo@arm.com reg = rom.perfectMatch[5] << 8; 4904626SN/A reg += rom.perfectMatch[4]; 4914626SN/A break; 4924626SN/A default: 4934626SN/A panic("reading RFDR for something other than PMATCH!\n"); 4944626SN/A // didn't implement other RFDR functionality b/c 4954626SN/A // driver didn't use it 4964626SN/A } 4978833Sdam.sunwoo@arm.com break; 4984626SN/A 4994626SN/A case SRR: 5004626SN/A reg = regs.srr; 5014626SN/A break; 5028833Sdam.sunwoo@arm.com 5038833Sdam.sunwoo@arm.com case MIBC: 5048833Sdam.sunwoo@arm.com reg = regs.mibc; 5054626SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 5064626SN/A break; 5074626SN/A 5084626SN/A case VRCR: 5094626SN/A reg = regs.vrcr; 5108833Sdam.sunwoo@arm.com break; 5114626SN/A 5124871SN/A case VTCR: 5138833Sdam.sunwoo@arm.com reg = regs.vtcr; 5148833Sdam.sunwoo@arm.com break; 5158833Sdam.sunwoo@arm.com 5164626SN/A case VDR: 5174626SN/A reg = regs.vdr; 5184626SN/A break; 5194626SN/A 5208833Sdam.sunwoo@arm.com case CCSR: 5214626SN/A reg = regs.ccsr; 5224871SN/A break; 5238833Sdam.sunwoo@arm.com 5248833Sdam.sunwoo@arm.com case TBICR: 5258833Sdam.sunwoo@arm.com reg = regs.tbicr; 5264626SN/A break; 5274626SN/A 5284626SN/A case TBISR: 5294626SN/A reg = regs.tbisr; 5304626SN/A break; 5314626SN/A 5324626SN/A case TANAR: 5338833Sdam.sunwoo@arm.com reg = regs.tanar; 5344626SN/A break; 5354626SN/A 5364626SN/A case TANLPAR: 5374626SN/A reg = regs.tanlpar; 5388833Sdam.sunwoo@arm.com break; 5398833Sdam.sunwoo@arm.com 5408833Sdam.sunwoo@arm.com case TANER: 5414626SN/A reg = regs.taner; 5424626SN/A break; 5434626SN/A 5444626SN/A case TESR: 5454626SN/A reg = regs.tesr; 5468833Sdam.sunwoo@arm.com break; 5474626SN/A 5484871SN/A default: 5498833Sdam.sunwoo@arm.com panic("reading unimplemented register: addr = %#x", daddr); 5508833Sdam.sunwoo@arm.com } 5518833Sdam.sunwoo@arm.com 5524626SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 5534626SN/A daddr, reg, reg); 5544626SN/A } 5554626SN/A break; 5568833Sdam.sunwoo@arm.com 5574626SN/A default: 5584871SN/A panic("accessing register with invalid size: addr=%#x, size=%d", 5594871SN/A daddr, req->size); 5608833Sdam.sunwoo@arm.com } 5618833Sdam.sunwoo@arm.com 5628833Sdam.sunwoo@arm.com return No_Fault; 5634626SN/A} 5644626SN/A 5654626SN/AFault 5664626SN/ANSGigE::write(MemReqPtr &req, const uint8_t *data) 5674626SN/A{ 5684626SN/A assert(ioEnable); 5694626SN/A 5708833Sdam.sunwoo@arm.com Addr daddr = req->paddr & 0xfff; 5714626SN/A DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 5724626SN/A daddr, req->paddr, req->vaddr, req->size); 5734626SN/A 5744626SN/A if (daddr > LAST && daddr <= RESERVED) { 5758833Sdam.sunwoo@arm.com panic("Accessing reserved register"); 5768833Sdam.sunwoo@arm.com } else if (daddr > RESERVED && daddr <= 0x3FC) { 5778833Sdam.sunwoo@arm.com WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 5784626SN/A return No_Fault; 5794626SN/A } else if (daddr > 0x3FC) 5804626SN/A panic("Something is messed up!\n"); 5814626SN/A 5824626SN/A if (req->size == sizeof(uint32_t)) { 5838833Sdam.sunwoo@arm.com uint32_t reg = *(uint32_t *)data; 5844626SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 5854871SN/A 5864871SN/A switch (daddr) { 5878833Sdam.sunwoo@arm.com case CR: 5888833Sdam.sunwoo@arm.com regs.command = reg; 5898833Sdam.sunwoo@arm.com if (reg & CR_TXD) { 5904626SN/A txEnable = false; 5914626SN/A } else if (reg & CR_TXE) { 5924626SN/A txEnable = true; 5934626SN/A 5944626SN/A // the kernel is enabling the transmit machine 5954626SN/A if (txState == txIdle) 5964626SN/A txKick(); 5978833Sdam.sunwoo@arm.com } 5984626SN/A 5994626SN/A if (reg & CR_RXD) { 6004626SN/A rxEnable = false; 6014626SN/A } else if (reg & CR_RXE) { 6028833Sdam.sunwoo@arm.com rxEnable = true; 60311483Snikos.nikoleris@arm.com 60411483Snikos.nikoleris@arm.com if (rxState == rxIdle) 6058833Sdam.sunwoo@arm.com rxKick(); 6064626SN/A } 6074626SN/A 6084626SN/A if (reg & CR_TXR) 6094626SN/A txReset(); 6104626SN/A 6118833Sdam.sunwoo@arm.com if (reg & CR_RXR) 6124626SN/A rxReset(); 6134871SN/A 6144871SN/A if (reg & CR_SWI) 6154871SN/A devIntrPost(ISR_SWI); 6168833Sdam.sunwoo@arm.com 6178833Sdam.sunwoo@arm.com if (reg & CR_RST) { 6188833Sdam.sunwoo@arm.com txReset(); 6194626SN/A rxReset(); 6204626SN/A 6214626SN/A regsReset(); 6224626SN/A } 6234626SN/A break; 6244626SN/A 6254626SN/A case CFG: 6264626SN/A if (reg & CFG_LNKSTS || 6274626SN/A reg & CFG_SPDSTS || 6284626SN/A reg & CFG_DUPSTS || 6294626SN/A reg & CFG_RESERVED || 6304626SN/A reg & CFG_T64ADDR || 6314626SN/A reg & CFG_PCI64_DET) 6324626SN/A panic("writing to read-only or reserved CFG bits!\n"); 6334626SN/A 6344626SN/A regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | 6354626SN/A CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET); 6364626SN/A 6374626SN/A// all these #if 0's are because i don't THINK the kernel needs to 6384626SN/A// have these implemented. if there is a problem relating to one of 6394626SN/A// these, you may need to add functionality in. 6404626SN/A#if 0 6414626SN/A if (reg & CFG_TBI_EN) ; 6424626SN/A if (reg & CFG_MODE_1000) ; 6434626SN/A#endif 6444626SN/A 6454626SN/A if (reg & CFG_AUTO_1000) 6464626SN/A panic("CFG_AUTO_1000 not implemented!\n"); 6474626SN/A 6484626SN/A#if 0 6494626SN/A if (reg & CFG_PINT_DUPSTS || 6504626SN/A reg & CFG_PINT_LNKSTS || 6514626SN/A reg & CFG_PINT_SPDSTS) 6524626SN/A ; 6534626SN/A 6544626SN/A if (reg & CFG_TMRTEST) ; 6554626SN/A if (reg & CFG_MRM_DIS) ; 6564626SN/A if (reg & CFG_MWI_DIS) ; 6574626SN/A 6584626SN/A if (reg & CFG_T64ADDR) 6594626SN/A panic("CFG_T64ADDR is read only register!\n"); 6604626SN/A 6614626SN/A if (reg & CFG_PCI64_DET) 6624626SN/A panic("CFG_PCI64_DET is read only register!\n"); 6634626SN/A 6648833Sdam.sunwoo@arm.com if (reg & CFG_DATA64_EN) ; 6658833Sdam.sunwoo@arm.com if (reg & CFG_M64ADDR) ; 6668833Sdam.sunwoo@arm.com if (reg & CFG_PHY_RST) ; 6678833Sdam.sunwoo@arm.com if (reg & CFG_PHY_DIS) ; 6684626SN/A#endif 6694626SN/A 6704626SN/A if (reg & CFG_EXTSTS_EN) 6714626SN/A extstsEnable = true; 6724626SN/A else 6738833Sdam.sunwoo@arm.com extstsEnable = false; 6744626SN/A 6754626SN/A#if 0 6768833Sdam.sunwoo@arm.com if (reg & CFG_REQALG) ; 6778833Sdam.sunwoo@arm.com if (reg & CFG_SB) ; 6788833Sdam.sunwoo@arm.com if (reg & CFG_POW) ; 6794626SN/A if (reg & CFG_EXD) ; 6804626SN/A if (reg & CFG_PESEL) ; 6814626SN/A if (reg & CFG_BROM_DIS) ; 6824626SN/A if (reg & CFG_EXT_125) ; 6838833Sdam.sunwoo@arm.com if (reg & CFG_BEM) ; 6844626SN/A#endif 6854626SN/A break; 6868833Sdam.sunwoo@arm.com 6878833Sdam.sunwoo@arm.com case MEAR: 6888833Sdam.sunwoo@arm.com regs.mear = reg; 6894626SN/A // since phy is completely faked, MEAR_MD* don't matter 6904626SN/A // and since the driver never uses MEAR_EE*, they don't 6914626SN/A // matter 6924626SN/A#if 0 6934626SN/A if (reg & MEAR_EEDI) ; 6944626SN/A if (reg & MEAR_EEDO) ; // this one is read only 6954626SN/A if (reg & MEAR_EECLK) ; 6964626SN/A if (reg & MEAR_EESEL) ; 6974626SN/A if (reg & MEAR_MDIO) ; 6984626SN/A if (reg & MEAR_MDDIR) ; 6994626SN/A if (reg & MEAR_MDC) ; 7004626SN/A#endif 7014626SN/A break; 7028833Sdam.sunwoo@arm.com 7038833Sdam.sunwoo@arm.com case PTSCR: 70411483Snikos.nikoleris@arm.com regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 70511483Snikos.nikoleris@arm.com // these control BISTs for various parts of chip - we 7068833Sdam.sunwoo@arm.com // don't care or do just fake that the BIST is done 7074626SN/A if (reg & PTSCR_RBIST_EN) 7084626SN/A regs.ptscr |= PTSCR_RBIST_DONE; 7094626SN/A if (reg & PTSCR_EEBIST_EN) 7104626SN/A regs.ptscr &= ~PTSCR_EEBIST_EN; 7114626SN/A if (reg & PTSCR_EELOAD_EN) 7128833Sdam.sunwoo@arm.com regs.ptscr &= ~PTSCR_EELOAD_EN; 7134626SN/A break; 7144626SN/A 7158833Sdam.sunwoo@arm.com case ISR: /* writing to the ISR has no effect */ 7168833Sdam.sunwoo@arm.com panic("ISR is a read only register!\n"); 7178833Sdam.sunwoo@arm.com 7184626SN/A case IMR: 7194626SN/A regs.imr = reg; 7204626SN/A devIntrChangeMask(); 7214626SN/A break; 7228833Sdam.sunwoo@arm.com 7234626SN/A case IER: 7244626SN/A regs.ier = reg; 7258833Sdam.sunwoo@arm.com break; 7268833Sdam.sunwoo@arm.com 7278833Sdam.sunwoo@arm.com case IHR: 7284626SN/A regs.ihr = reg; 7294626SN/A /* not going to implement real interrupt holdoff */ 7304626SN/A break; 7314626SN/A 7324626SN/A case TXDP: 7334626SN/A regs.txdp = (reg & 0xFFFFFFFC); 7344626SN/A assert(txState == txIdle); 7354626SN/A CTDD = false; 7364626SN/A break; 7374626SN/A 7384626SN/A case TXDP_HI: 7394626SN/A regs.txdp_hi = reg; 7404626SN/A break; 7418833Sdam.sunwoo@arm.com 7428833Sdam.sunwoo@arm.com case TXCFG: 74311483Snikos.nikoleris@arm.com regs.txcfg = reg; 74411483Snikos.nikoleris@arm.com#if 0 7458833Sdam.sunwoo@arm.com if (reg & TXCFG_CSI) ; 7464626SN/A if (reg & TXCFG_HBI) ; 7474626SN/A if (reg & TXCFG_MLB) ; 7484626SN/A if (reg & TXCFG_ATP) ; 7494626SN/A if (reg & TXCFG_ECRETRY) { 7504626SN/A /* 7518833Sdam.sunwoo@arm.com * this could easily be implemented, but considering 7524626SN/A * the network is just a fake pipe, wouldn't make 75311483Snikos.nikoleris@arm.com * sense to do this 75411483Snikos.nikoleris@arm.com */ 7558833Sdam.sunwoo@arm.com } 7568833Sdam.sunwoo@arm.com 7578833Sdam.sunwoo@arm.com if (reg & TXCFG_BRST_DIS) ; 7584626SN/A#endif 7592810SN/A 760#if 0 761 /* we handle our own DMA, ignore the kernel's exhortations */ 762 if (reg & TXCFG_MXDMA) ; 763#endif 764 765 // also, we currently don't care about fill/drain 766 // thresholds though this may change in the future with 767 // more realistic networks or a driver which changes it 768 // according to feedback 769 770 break; 771 772 case GPIOR: 773 regs.gpior = reg; 774 /* these just control general purpose i/o pins, don't matter */ 775 break; 776 777 case RXDP: 778 regs.rxdp = reg; 779 CRDD = false; 780 break; 781 782 case RXDP_HI: 783 regs.rxdp_hi = reg; 784 break; 785 786 case RXCFG: 787 regs.rxcfg = reg; 788#if 0 789 if (reg & RXCFG_AEP) ; 790 if (reg & RXCFG_ARP) ; 791 if (reg & RXCFG_STRIPCRC) ; 792 if (reg & RXCFG_RX_RD) ; 793 if (reg & RXCFG_ALP) ; 794 if (reg & RXCFG_AIRL) ; 795 796 /* we handle our own DMA, ignore what kernel says about it */ 797 if (reg & RXCFG_MXDMA) ; 798 799 //also, we currently don't care about fill/drain thresholds 800 //though this may change in the future with more realistic 801 //networks or a driver which changes it according to feedback 802 if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 803#endif 804 break; 805 806 case PQCR: 807 /* there is no priority queueing used in the linux 2.6 driver */ 808 regs.pqcr = reg; 809 break; 810 811 case WCSR: 812 /* not going to implement wake on LAN */ 813 regs.wcsr = reg; 814 break; 815 816 case PCR: 817 /* not going to implement pause control */ 818 regs.pcr = reg; 819 break; 820 821 case RFCR: 822 regs.rfcr = reg; 823 824 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 825 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 826 acceptMulticast = (reg & RFCR_AAM) ? true : false; 827 acceptUnicast = (reg & RFCR_AAU) ? true : false; 828 acceptPerfect = (reg & RFCR_APM) ? true : false; 829 acceptArp = (reg & RFCR_AARP) ? true : false; 830 831#if 0 832 if (reg & RFCR_APAT) 833 panic("RFCR_APAT not implemented!\n"); 834#endif 835 836 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 837 panic("hash filtering not implemented!\n"); 838 839 if (reg & RFCR_ULM) 840 panic("RFCR_ULM not implemented!\n"); 841 842 break; 843 844 case RFDR: 845 panic("the driver never writes to RFDR, something is wrong!\n"); 846 847 case BRAR: 848 panic("the driver never uses BRAR, something is wrong!\n"); 849 850 case BRDR: 851 panic("the driver never uses BRDR, something is wrong!\n"); 852 853 case SRR: 854 panic("SRR is read only register!\n"); 855 856 case MIBC: 857 panic("the driver never uses MIBC, something is wrong!\n"); 858 859 case VRCR: 860 regs.vrcr = reg; 861 break; 862 863 case VTCR: 864 regs.vtcr = reg; 865 break; 866 867 case VDR: 868 panic("the driver never uses VDR, something is wrong!\n"); 869 break; 870 871 case CCSR: 872 /* not going to implement clockrun stuff */ 873 regs.ccsr = reg; 874 break; 875 876 case TBICR: 877 regs.tbicr = reg; 878 if (reg & TBICR_MR_LOOPBACK) 879 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 880 881 if (reg & TBICR_MR_AN_ENABLE) { 882 regs.tanlpar = regs.tanar; 883 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 884 } 885 886#if 0 887 if (reg & TBICR_MR_RESTART_AN) ; 888#endif 889 890 break; 891 892 case TBISR: 893 panic("TBISR is read only register!\n"); 894 895 case TANAR: 896 regs.tanar = reg; 897 if (reg & TANAR_PS2) 898 panic("this isn't used in driver, something wrong!\n"); 899 900 if (reg & TANAR_PS1) 901 panic("this isn't used in driver, something wrong!\n"); 902 break; 903 904 case TANLPAR: 905 panic("this should only be written to by the fake phy!\n"); 906 907 case TANER: 908 panic("TANER is read only register!\n"); 909 910 case TESR: 911 regs.tesr = reg; 912 break; 913 914 default: 915 panic("invalid register access daddr=%#x", daddr); 916 } 917 } else { 918 panic("Invalid Request Size"); 919 } 920 921 return No_Fault; 922} 923 924void 925NSGigE::devIntrPost(uint32_t interrupts) 926{ 927 bool delay = false; 928 929 if (interrupts & ISR_RESERVE) 930 panic("Cannot set a reserved interrupt"); 931 932 if (interrupts & ISR_TXRCMP) 933 regs.isr |= ISR_TXRCMP; 934 935 if (interrupts & ISR_RXRCMP) 936 regs.isr |= ISR_RXRCMP; 937 938//ISR_DPERR not implemented 939//ISR_SSERR not implemented 940//ISR_RMABT not implemented 941//ISR_RXSOVR not implemented 942//ISR_HIBINT not implemented 943//ISR_PHY not implemented 944//ISR_PME not implemented 945 946 if (interrupts & ISR_SWI) 947 regs.isr |= ISR_SWI; 948 949//ISR_MIB not implemented 950//ISR_TXURN not implemented 951 952 if (interrupts & ISR_TXIDLE) 953 regs.isr |= ISR_TXIDLE; 954 955 if (interrupts & ISR_TXERR) 956 regs.isr |= ISR_TXERR; 957 958 if (interrupts & ISR_TXDESC) 959 regs.isr |= ISR_TXDESC; 960 961 if (interrupts & ISR_TXOK) { 962 regs.isr |= ISR_TXOK; 963 delay = true; 964 } 965 966 if (interrupts & ISR_RXORN) 967 regs.isr |= ISR_RXORN; 968 969 if (interrupts & ISR_RXIDLE) 970 regs.isr |= ISR_RXIDLE; 971 972//ISR_RXEARLY not implemented 973 974 if (interrupts & ISR_RXERR) 975 regs.isr |= ISR_RXERR; 976 977 if (interrupts & ISR_RXDESC) 978 regs.isr |= ISR_RXDESC; 979 980 if (interrupts & ISR_RXOK) { 981 delay = true; 982 regs.isr |= ISR_RXOK; 983 } 984 985 if ((regs.isr & regs.imr)) { 986 Tick when = curTick; 987 if (delay) 988 when += intrDelay; 989 cpuIntrPost(when); 990 } 991 992 DPRINTF(EthernetIntr, 993 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 994 interrupts, regs.isr, regs.imr); 995} 996 997void 998NSGigE::devIntrClear(uint32_t interrupts) 999{ 1000 if (interrupts & ISR_RESERVE) 1001 panic("Cannot clear a reserved interrupt"); 1002 1003 if (interrupts & ISR_TXRCMP) 1004 regs.isr &= ~ISR_TXRCMP; 1005 1006 if (interrupts & ISR_RXRCMP) 1007 regs.isr &= ~ISR_RXRCMP; 1008 1009//ISR_DPERR not implemented 1010//ISR_SSERR not implemented 1011//ISR_RMABT not implemented 1012//ISR_RXSOVR not implemented 1013//ISR_HIBINT not implemented 1014//ISR_PHY not implemented 1015//ISR_PME not implemented 1016 1017 if (interrupts & ISR_SWI) 1018 regs.isr &= ~ISR_SWI; 1019 1020//ISR_MIB not implemented 1021//ISR_TXURN not implemented 1022 1023 if (interrupts & ISR_TXIDLE) 1024 regs.isr &= ~ISR_TXIDLE; 1025 1026 if (interrupts & ISR_TXERR) 1027 regs.isr &= ~ISR_TXERR; 1028 1029 if (interrupts & ISR_TXDESC) 1030 regs.isr &= ~ISR_TXDESC; 1031 1032 if (interrupts & ISR_TXOK) 1033 regs.isr &= ~ISR_TXOK; 1034 1035 if (interrupts & ISR_RXORN) 1036 regs.isr &= ~ISR_RXORN; 1037 1038 if (interrupts & ISR_RXIDLE) 1039 regs.isr &= ~ISR_RXIDLE; 1040 1041//ISR_RXEARLY not implemented 1042 1043 if (interrupts & ISR_RXERR) 1044 regs.isr &= ~ISR_RXERR; 1045 1046 if (interrupts & ISR_RXDESC) 1047 regs.isr &= ~ISR_RXDESC; 1048 1049 if (interrupts & ISR_RXOK) 1050 regs.isr &= ~ISR_RXOK; 1051 1052 if (!(regs.isr & regs.imr)) 1053 cpuIntrClear(); 1054 1055 DPRINTF(EthernetIntr, 1056 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 1057 interrupts, regs.isr, regs.imr); 1058} 1059 1060void 1061NSGigE::devIntrChangeMask() 1062{ 1063 DPRINTF(EthernetIntr, "interrupt mask changed\n"); 1064 1065 if (regs.isr & regs.imr) 1066 cpuIntrPost(curTick); 1067 else 1068 cpuIntrClear(); 1069} 1070 1071void 1072NSGigE::cpuIntrPost(Tick when) 1073{ 1074 // If the interrupt you want to post is later than an interrupt 1075 // already scheduled, just let it post in the coming one and don't 1076 // schedule another. 1077 // HOWEVER, must be sure that the scheduled intrTick is in the 1078 // future (this was formerly the source of a bug) 1079 /** 1080 * @todo this warning should be removed and the intrTick code should 1081 * be fixed. 1082 */ 1083 if (intrTick < curTick && intrTick != 0) { 1084 warn("intrTick < curTick !!! intrTick=%d curTick=%d\n", 1085 intrTick, curTick); 1086 intrTick = 0; 1087 } 1088 assert((intrTick >= curTick) || (intrTick == 0)); 1089 if (when > intrTick && intrTick != 0) 1090 return; 1091 1092 intrTick = when; 1093 1094 if (intrEvent) { 1095 intrEvent->squash(); 1096 intrEvent = 0; 1097 } 1098 1099 if (when < curTick) { 1100 cpuInterrupt(); 1101 } else { 1102 DPRINTF(EthernetIntr, 1103 "going to schedule an interrupt for intrTick=%d\n", 1104 intrTick); 1105 intrEvent = new IntrEvent(this, true); 1106 intrEvent->schedule(intrTick); 1107 } 1108} 1109 1110void 1111NSGigE::cpuInterrupt() 1112{ 1113 // Don't send an interrupt if there's already one 1114 if (cpuPendingIntr) { 1115 DPRINTF(EthernetIntr, 1116 "would send an interrupt now, but there's already pending\n"); 1117 intrTick = 0; 1118 return; 1119 } 1120 // Don't send an interrupt if it's supposed to be delayed 1121 if (intrTick > curTick) { 1122 DPRINTF(EthernetIntr, 1123 "an interrupt is scheduled for %d, wait til then\n", 1124 intrTick); 1125 return; 1126 } 1127 1128 // Whether or not there's a pending interrupt, we don't care about 1129 // it anymore 1130 intrEvent = 0; 1131 intrTick = 0; 1132 1133 // Send interrupt 1134 cpuPendingIntr = true; 1135 /** @todo rework the intctrl to be tsunami ok */ 1136 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 1137 DPRINTF(EthernetIntr, "Posting interrupts to cchip!\n"); 1138 tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine); 1139} 1140 1141void 1142NSGigE::cpuIntrClear() 1143{ 1144 if (!cpuPendingIntr) 1145 return; 1146 1147 cpuPendingIntr = false; 1148 /** @todo rework the intctrl to be tsunami ok */ 1149 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 1150 DPRINTF(EthernetIntr, "clearing all interrupts from cchip\n"); 1151 tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); 1152} 1153 1154bool 1155NSGigE::cpuIntrPending() const 1156{ return cpuPendingIntr; } 1157 1158void 1159NSGigE::txReset() 1160{ 1161 1162 DPRINTF(Ethernet, "transmit reset\n"); 1163 1164 CTDD = false; 1165 txFifoAvail = maxTxFifoSize; 1166 txEnable = false;; 1167 txFragPtr = 0; 1168 assert(txDescCnt == 0); 1169 txFifo.clear(); 1170 txState = txIdle; 1171 assert(txDmaState == dmaIdle); 1172} 1173 1174void 1175NSGigE::rxReset() 1176{ 1177 DPRINTF(Ethernet, "receive reset\n"); 1178 1179 CRDD = false; 1180 assert(rxPktBytes == 0); 1181 rxFifoCnt = 0; 1182 rxEnable = false; 1183 rxFragPtr = 0; 1184 assert(rxDescCnt == 0); 1185 assert(rxDmaState == dmaIdle); 1186 rxFifo.clear(); 1187 rxState = rxIdle; 1188} 1189 1190void NSGigE::regsReset() 1191{ 1192 memset(®s, 0, sizeof(regs)); 1193 regs.config = 0x80000000; 1194 regs.mear = 0x12; 1195 regs.isr = 0x00608000; 1196 regs.txcfg = 0x120; 1197 regs.rxcfg = 0x4; 1198 regs.srr = 0x0103; 1199 regs.mibc = 0x2; 1200 regs.vdr = 0x81; 1201 regs.tesr = 0xc000; 1202 1203 extstsEnable = false; 1204 acceptBroadcast = false; 1205 acceptMulticast = false; 1206 acceptUnicast = false; 1207 acceptPerfect = false; 1208 acceptArp = false; 1209} 1210 1211void 1212NSGigE::rxDmaReadCopy() 1213{ 1214 assert(rxDmaState == dmaReading); 1215 1216 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1217 rxDmaState = dmaIdle; 1218 1219 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1220 rxDmaAddr, rxDmaLen); 1221 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1222} 1223 1224bool 1225NSGigE::doRxDmaRead() 1226{ 1227 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1228 rxDmaState = dmaReading; 1229 1230 if (dmaInterface && !rxDmaFree) { 1231 if (dmaInterface->busy()) 1232 rxDmaState = dmaReadWaiting; 1233 else 1234 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1235 &rxDmaReadEvent, true); 1236 return true; 1237 } 1238 1239 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1240 rxDmaReadCopy(); 1241 return false; 1242 } 1243 1244 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1245 Tick start = curTick + dmaReadDelay + factor; 1246 rxDmaReadEvent.schedule(start); 1247 return true; 1248} 1249 1250void 1251NSGigE::rxDmaReadDone() 1252{ 1253 assert(rxDmaState == dmaReading); 1254 rxDmaReadCopy(); 1255 1256 // If the transmit state machine has a pending DMA, let it go first 1257 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1258 txKick(); 1259 1260 rxKick(); 1261} 1262 1263void 1264NSGigE::rxDmaWriteCopy() 1265{ 1266 assert(rxDmaState == dmaWriting); 1267 1268 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1269 rxDmaState = dmaIdle; 1270 1271 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1272 rxDmaAddr, rxDmaLen); 1273 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1274} 1275 1276bool 1277NSGigE::doRxDmaWrite() 1278{ 1279 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1280 rxDmaState = dmaWriting; 1281 1282 if (dmaInterface && !rxDmaFree) { 1283 if (dmaInterface->busy()) 1284 rxDmaState = dmaWriteWaiting; 1285 else 1286 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1287 &rxDmaWriteEvent, true); 1288 return true; 1289 } 1290 1291 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1292 rxDmaWriteCopy(); 1293 return false; 1294 } 1295 1296 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1297 Tick start = curTick + dmaWriteDelay + factor; 1298 rxDmaWriteEvent.schedule(start); 1299 return true; 1300} 1301 1302void 1303NSGigE::rxDmaWriteDone() 1304{ 1305 assert(rxDmaState == dmaWriting); 1306 rxDmaWriteCopy(); 1307 1308 // If the transmit state machine has a pending DMA, let it go first 1309 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1310 txKick(); 1311 1312 rxKick(); 1313} 1314 1315void 1316NSGigE::rxKick() 1317{ 1318 DPRINTF(EthernetSM, "receive kick state=%s (rxBuf.size=%d)\n", 1319 NsRxStateStrings[rxState], rxFifo.size()); 1320 1321 if (rxKickTick > curTick) { 1322 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1323 rxKickTick); 1324 return; 1325 } 1326 1327 next: 1328 switch(rxDmaState) { 1329 case dmaReadWaiting: 1330 if (doRxDmaRead()) 1331 goto exit; 1332 break; 1333 case dmaWriteWaiting: 1334 if (doRxDmaWrite()) 1335 goto exit; 1336 break; 1337 default: 1338 break; 1339 } 1340 1341 // see state machine from spec for details 1342 // the way this works is, if you finish work on one state and can 1343 // go directly to another, you do that through jumping to the 1344 // label "next". however, if you have intermediate work, like DMA 1345 // so that you can't go to the next state yet, you go to exit and 1346 // exit the loop. however, when the DMA is done it will trigger 1347 // an event and come back to this loop. 1348 switch (rxState) { 1349 case rxIdle: 1350 if (!rxEnable) { 1351 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1352 goto exit; 1353 } 1354 1355 if (CRDD) { 1356 rxState = rxDescRefr; 1357 1358 rxDmaAddr = regs.rxdp & 0x3fffffff; 1359 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1360 rxDmaLen = sizeof(rxDescCache.link); 1361 rxDmaFree = dmaDescFree; 1362 1363 descDmaReads++; 1364 descDmaRdBytes += rxDmaLen; 1365 1366 if (doRxDmaRead()) 1367 goto exit; 1368 } else { 1369 rxState = rxDescRead; 1370 1371 rxDmaAddr = regs.rxdp & 0x3fffffff; 1372 rxDmaData = &rxDescCache; 1373 rxDmaLen = sizeof(ns_desc); 1374 rxDmaFree = dmaDescFree; 1375 1376 descDmaReads++; 1377 descDmaRdBytes += rxDmaLen; 1378 1379 if (doRxDmaRead()) 1380 goto exit; 1381 } 1382 break; 1383 1384 case rxDescRefr: 1385 if (rxDmaState != dmaIdle) 1386 goto exit; 1387 1388 rxState = rxAdvance; 1389 break; 1390 1391 case rxDescRead: 1392 if (rxDmaState != dmaIdle) 1393 goto exit; 1394 1395 DPRINTF(EthernetDesc, 1396 "rxDescCache:\n" 1397 "\tlink=%08x\n" 1398 "\tbufptr=%08x\n" 1399 "\tcmdsts=%08x\n" 1400 "\textsts=%08x\n", 1401 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1402 rxDescCache.extsts); 1403 1404 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1405 devIntrPost(ISR_RXIDLE); 1406 rxState = rxIdle; 1407 goto exit; 1408 } else { 1409 rxState = rxFifoBlock; 1410 rxFragPtr = rxDescCache.bufptr; 1411 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1412 } 1413 break; 1414 1415 case rxFifoBlock: 1416 if (!rxPacket) { 1417 /** 1418 * @todo in reality, we should be able to start processing 1419 * the packet as it arrives, and not have to wait for the 1420 * full packet ot be in the receive fifo. 1421 */ 1422 if (rxFifo.empty()) 1423 goto exit; 1424 1425 DPRINTF(EthernetSM, "\n\n*****processing receive of new packet\n"); 1426 1427 // If we don't have a packet, grab a new one from the fifo. 1428 rxPacket = rxFifo.front(); 1429 rxPktBytes = rxPacket->length; 1430 rxPacketBufPtr = rxPacket->data; 1431 1432#if TRACING_ON 1433 if (DTRACE(Ethernet)) { 1434 if (rxPacket->isIpPkt()) { 1435 ip_header *ip = rxPacket->getIpHdr(); 1436 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1437 if (rxPacket->isTcpPkt()) { 1438 tcp_header *tcp = rxPacket->getTcpHdr(ip); 1439 DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", 1440 reverseEnd16(tcp->src_port_num), 1441 reverseEnd16(tcp->dest_port_num)); 1442 } 1443 } 1444 } 1445#endif 1446 1447 // sanity check - i think the driver behaves like this 1448 assert(rxDescCnt >= rxPktBytes); 1449 1450 // Must clear the value before popping to decrement the 1451 // reference count 1452 rxFifo.front() = NULL; 1453 rxFifo.pop_front(); 1454 rxFifoCnt -= rxPacket->length; 1455 } 1456 1457 1458 // dont' need the && rxDescCnt > 0 if driver sanity check 1459 // above holds 1460 if (rxPktBytes > 0) { 1461 rxState = rxFragWrite; 1462 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1463 // check holds 1464 rxXferLen = rxPktBytes; 1465 1466 rxDmaAddr = rxFragPtr & 0x3fffffff; 1467 rxDmaData = rxPacketBufPtr; 1468 rxDmaLen = rxXferLen; 1469 rxDmaFree = dmaDataFree; 1470 1471 if (doRxDmaWrite()) 1472 goto exit; 1473 1474 } else { 1475 rxState = rxDescWrite; 1476 1477 //if (rxPktBytes == 0) { /* packet is done */ 1478 assert(rxPktBytes == 0); 1479 DPRINTF(EthernetSM, "done with receiving packet\n"); 1480 1481 rxDescCache.cmdsts |= CMDSTS_OWN; 1482 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1483 rxDescCache.cmdsts |= CMDSTS_OK; 1484 rxDescCache.cmdsts &= 0xffff0000; 1485 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1486 1487#if 0 1488 /* 1489 * all the driver uses these are for its own stats keeping 1490 * which we don't care about, aren't necessary for 1491 * functionality and doing this would just slow us down. 1492 * if they end up using this in a later version for 1493 * functional purposes, just undef 1494 */ 1495 if (rxFilterEnable) { 1496 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1497 if (rxFifo.front()->IsUnicast()) 1498 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1499 if (rxFifo.front()->IsMulticast()) 1500 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1501 if (rxFifo.front()->IsBroadcast()) 1502 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1503 } 1504#endif 1505 1506 if (rxPacket->isIpPkt() && extstsEnable) { 1507 rxDescCache.extsts |= EXTSTS_IPPKT; 1508 rxIPChecksums++; 1509 if (!ipChecksum(rxPacket, false)) { 1510 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1511 rxDescCache.extsts |= EXTSTS_IPERR; 1512 } 1513 if (rxPacket->isTcpPkt()) { 1514 rxDescCache.extsts |= EXTSTS_TCPPKT; 1515 rxTCPChecksums++; 1516 if (!tcpChecksum(rxPacket, false)) { 1517 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1518 rxDescCache.extsts |= EXTSTS_TCPERR; 1519 1520 } 1521 } else if (rxPacket->isUdpPkt()) { 1522 rxDescCache.extsts |= EXTSTS_UDPPKT; 1523 if (!udpChecksum(rxPacket, false)) { 1524 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1525 rxDescCache.extsts |= EXTSTS_UDPERR; 1526 } 1527 } 1528 } 1529 rxPacket = 0; 1530 1531 /* 1532 * the driver seems to always receive into desc buffers 1533 * of size 1514, so you never have a pkt that is split 1534 * into multiple descriptors on the receive side, so 1535 * i don't implement that case, hence the assert above. 1536 */ 1537 1538 DPRINTF(EthernetDesc, 1539 "rxDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", 1540 rxDescCache.cmdsts, rxDescCache.extsts); 1541 1542 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1543 rxDmaData = &(rxDescCache.cmdsts); 1544 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1545 rxDmaFree = dmaDescFree; 1546 1547 descDmaWrites++; 1548 descDmaWrBytes += rxDmaLen; 1549 1550 if (doRxDmaWrite()) 1551 goto exit; 1552 } 1553 break; 1554 1555 case rxFragWrite: 1556 if (rxDmaState != dmaIdle) 1557 goto exit; 1558 1559 rxPacketBufPtr += rxXferLen; 1560 rxFragPtr += rxXferLen; 1561 rxPktBytes -= rxXferLen; 1562 1563 rxState = rxFifoBlock; 1564 break; 1565 1566 case rxDescWrite: 1567 if (rxDmaState != dmaIdle) 1568 goto exit; 1569 1570 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1571 1572 assert(rxPacket == 0); 1573 devIntrPost(ISR_RXOK); 1574 1575 if (rxDescCache.cmdsts & CMDSTS_INTR) 1576 devIntrPost(ISR_RXDESC); 1577 1578 if (!rxEnable) { 1579 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1580 rxState = rxIdle; 1581 goto exit; 1582 } else 1583 rxState = rxAdvance; 1584 break; 1585 1586 case rxAdvance: 1587 if (rxDescCache.link == 0) { 1588 devIntrPost(ISR_RXIDLE); 1589 rxState = rxIdle; 1590 CRDD = true; 1591 goto exit; 1592 } else { 1593 rxState = rxDescRead; 1594 regs.rxdp = rxDescCache.link; 1595 CRDD = false; 1596 1597 rxDmaAddr = regs.rxdp & 0x3fffffff; 1598 rxDmaData = &rxDescCache; 1599 rxDmaLen = sizeof(ns_desc); 1600 rxDmaFree = dmaDescFree; 1601 1602 if (doRxDmaRead()) 1603 goto exit; 1604 } 1605 break; 1606 1607 default: 1608 panic("Invalid rxState!"); 1609 } 1610 1611 1612 DPRINTF(EthernetSM, "entering next rx state = %s\n", 1613 NsRxStateStrings[rxState]); 1614 1615 goto next; 1616 1617 exit: 1618 /** 1619 * @todo do we want to schedule a future kick? 1620 */ 1621 DPRINTF(EthernetSM, "rx state machine exited state=%s\n", 1622 NsRxStateStrings[rxState]); 1623} 1624 1625void 1626NSGigE::transmit() 1627{ 1628 if (txFifo.empty()) { 1629 DPRINTF(Ethernet, "nothing to transmit\n"); 1630 return; 1631 } 1632 1633 DPRINTF(Ethernet, "\n\nAttempt Pkt Transmit: txFifo length = %d\n", 1634 maxTxFifoSize - txFifoAvail); 1635 if (interface->sendPacket(txFifo.front())) { 1636#if TRACING_ON 1637 if (DTRACE(Ethernet)) { 1638 if (txFifo.front()->isIpPkt()) { 1639 ip_header *ip = txFifo.front()->getIpHdr(); 1640 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1641 if (txFifo.front()->isTcpPkt()) { 1642 tcp_header *tcp = txFifo.front()->getTcpHdr(ip); 1643 DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", 1644 reverseEnd16(tcp->src_port_num), 1645 reverseEnd16(tcp->dest_port_num)); 1646 } 1647 } 1648 } 1649#endif 1650 1651 DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length); 1652 txBytes += txFifo.front()->length; 1653 txPackets++; 1654 1655 txFifoAvail += txFifo.front()->length; 1656 1657 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1658 txFifoAvail); 1659 txFifo.front() = NULL; 1660 txFifo.pop_front(); 1661 1662 /* 1663 * normally do a writeback of the descriptor here, and ONLY 1664 * after that is done, send this interrupt. but since our 1665 * stuff never actually fails, just do this interrupt here, 1666 * otherwise the code has to stray from this nice format. 1667 * besides, it's functionally the same. 1668 */ 1669 devIntrPost(ISR_TXOK); 1670 } else { 1671 DPRINTF(Ethernet, 1672 "May need to rethink always sending the descriptors back?\n"); 1673 } 1674 1675 if (!txFifo.empty() && !txEvent.scheduled()) { 1676 DPRINTF(Ethernet, "reschedule transmit\n"); 1677 txEvent.schedule(curTick + 1000); 1678 } 1679} 1680 1681void 1682NSGigE::txDmaReadCopy() 1683{ 1684 assert(txDmaState == dmaReading); 1685 1686 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1687 txDmaState = dmaIdle; 1688 1689 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1690 txDmaAddr, txDmaLen); 1691 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1692} 1693 1694bool 1695NSGigE::doTxDmaRead() 1696{ 1697 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1698 txDmaState = dmaReading; 1699 1700 if (dmaInterface && !txDmaFree) { 1701 if (dmaInterface->busy()) 1702 txDmaState = dmaReadWaiting; 1703 else 1704 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1705 &txDmaReadEvent, true); 1706 return true; 1707 } 1708 1709 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1710 txDmaReadCopy(); 1711 return false; 1712 } 1713 1714 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1715 Tick start = curTick + dmaReadDelay + factor; 1716 txDmaReadEvent.schedule(start); 1717 return true; 1718} 1719 1720void 1721NSGigE::txDmaReadDone() 1722{ 1723 assert(txDmaState == dmaReading); 1724 txDmaReadCopy(); 1725 1726 // If the receive state machine has a pending DMA, let it go first 1727 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1728 rxKick(); 1729 1730 txKick(); 1731} 1732 1733void 1734NSGigE::txDmaWriteCopy() 1735{ 1736 assert(txDmaState == dmaWriting); 1737 1738 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1739 txDmaState = dmaIdle; 1740 1741 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1742 txDmaAddr, txDmaLen); 1743 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1744} 1745 1746bool 1747NSGigE::doTxDmaWrite() 1748{ 1749 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1750 txDmaState = dmaWriting; 1751 1752 if (dmaInterface && !txDmaFree) { 1753 if (dmaInterface->busy()) 1754 txDmaState = dmaWriteWaiting; 1755 else 1756 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1757 &txDmaWriteEvent, true); 1758 return true; 1759 } 1760 1761 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1762 txDmaWriteCopy(); 1763 return false; 1764 } 1765 1766 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1767 Tick start = curTick + dmaWriteDelay + factor; 1768 txDmaWriteEvent.schedule(start); 1769 return true; 1770} 1771 1772void 1773NSGigE::txDmaWriteDone() 1774{ 1775 assert(txDmaState == dmaWriting); 1776 txDmaWriteCopy(); 1777 1778 // If the receive state machine has a pending DMA, let it go first 1779 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1780 rxKick(); 1781 1782 txKick(); 1783} 1784 1785void 1786NSGigE::txKick() 1787{ 1788 DPRINTF(EthernetSM, "transmit kick state=%s\n", NsTxStateStrings[txState]); 1789 1790 if (txKickTick > curTick) { 1791 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1792 txKickTick); 1793 1794 return; 1795 } 1796 1797 next: 1798 switch(txDmaState) { 1799 case dmaReadWaiting: 1800 if (doTxDmaRead()) 1801 goto exit; 1802 break; 1803 case dmaWriteWaiting: 1804 if (doTxDmaWrite()) 1805 goto exit; 1806 break; 1807 default: 1808 break; 1809 } 1810 1811 switch (txState) { 1812 case txIdle: 1813 if (!txEnable) { 1814 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1815 goto exit; 1816 } 1817 1818 if (CTDD) { 1819 txState = txDescRefr; 1820 1821 txDmaAddr = regs.txdp & 0x3fffffff; 1822 txDmaData = &txDescCache + offsetof(ns_desc, link); 1823 txDmaLen = sizeof(txDescCache.link); 1824 txDmaFree = dmaDescFree; 1825 1826 descDmaReads++; 1827 descDmaRdBytes += txDmaLen; 1828 1829 if (doTxDmaRead()) 1830 goto exit; 1831 1832 } else { 1833 txState = txDescRead; 1834 1835 txDmaAddr = regs.txdp & 0x3fffffff; 1836 txDmaData = &txDescCache; 1837 txDmaLen = sizeof(ns_desc); 1838 txDmaFree = dmaDescFree; 1839 1840 descDmaReads++; 1841 descDmaRdBytes += txDmaLen; 1842 1843 if (doTxDmaRead()) 1844 goto exit; 1845 } 1846 break; 1847 1848 case txDescRefr: 1849 if (txDmaState != dmaIdle) 1850 goto exit; 1851 1852 txState = txAdvance; 1853 break; 1854 1855 case txDescRead: 1856 if (txDmaState != dmaIdle) 1857 goto exit; 1858 1859 DPRINTF(EthernetDesc, 1860 "txDescCache data:\n" 1861 "\tlink=%08x\n" 1862 "\tbufptr=%08x\n" 1863 "\tcmdsts=%08x\n" 1864 "\textsts=%08x\n", 1865 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 1866 txDescCache.extsts); 1867 1868 if (txDescCache.cmdsts & CMDSTS_OWN) { 1869 txState = txFifoBlock; 1870 txFragPtr = txDescCache.bufptr; 1871 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1872 } else { 1873 devIntrPost(ISR_TXIDLE); 1874 txState = txIdle; 1875 goto exit; 1876 } 1877 break; 1878 1879 case txFifoBlock: 1880 if (!txPacket) { 1881 DPRINTF(EthernetSM, "\n\n*****starting the tx of a new packet\n"); 1882 txPacket = new EtherPacket; 1883 txPacket->data = new uint8_t[16384]; 1884 txPacketBufPtr = txPacket->data; 1885 } 1886 1887 if (txDescCnt == 0) { 1888 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 1889 if (txDescCache.cmdsts & CMDSTS_MORE) { 1890 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1891 txState = txDescWrite; 1892 1893 txDescCache.cmdsts &= ~CMDSTS_OWN; 1894 1895 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1896 txDmaAddr &= 0x3fffffff; 1897 txDmaData = &(txDescCache.cmdsts); 1898 txDmaLen = sizeof(txDescCache.cmdsts); 1899 txDmaFree = dmaDescFree; 1900 1901 if (doTxDmaWrite()) 1902 goto exit; 1903 1904 } else { /* this packet is totally done */ 1905 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1906 /* deal with the the packet that just finished */ 1907 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 1908 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1909 udpChecksum(txPacket, true); 1910 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1911 tcpChecksum(txPacket, true); 1912 txTCPChecksums++; 1913 } 1914 if (txDescCache.extsts & EXTSTS_IPPKT) { 1915 ipChecksum(txPacket, true); 1916 txIPChecksums++; 1917 } 1918 } 1919 1920 txPacket->length = txPacketBufPtr - txPacket->data; 1921 // this is just because the receive can't handle a 1922 // packet bigger want to make sure 1923 assert(txPacket->length <= 1514); 1924 txFifo.push_back(txPacket); 1925 1926 /* 1927 * this following section is not tqo spec, but 1928 * functionally shouldn't be any different. normally, 1929 * the chip will wait til the transmit has occurred 1930 * before writing back the descriptor because it has 1931 * to wait to see that it was successfully transmitted 1932 * to decide whether to set CMDSTS_OK or not. 1933 * however, in the simulator since it is always 1934 * successfully transmitted, and writing it exactly to 1935 * spec would complicate the code, we just do it here 1936 */ 1937 1938 txDescCache.cmdsts &= ~CMDSTS_OWN; 1939 txDescCache.cmdsts |= CMDSTS_OK; 1940 1941 DPRINTF(EthernetDesc, 1942 "txDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", 1943 txDescCache.cmdsts, txDescCache.extsts); 1944 1945 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1946 txDmaAddr &= 0x3fffffff; 1947 txDmaData = &(txDescCache.cmdsts); 1948 txDmaLen = sizeof(txDescCache.cmdsts) + 1949 sizeof(txDescCache.extsts); 1950 txDmaFree = dmaDescFree; 1951 1952 descDmaWrites++; 1953 descDmaWrBytes += txDmaLen; 1954 1955 transmit(); 1956 txPacket = 0; 1957 1958 if (!txEnable) { 1959 DPRINTF(EthernetSM, "halting TX state machine\n"); 1960 txState = txIdle; 1961 goto exit; 1962 } else 1963 txState = txAdvance; 1964 1965 if (doTxDmaWrite()) 1966 goto exit; 1967 } 1968 } else { 1969 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 1970 if (txFifoAvail) { 1971 txState = txFragRead; 1972 1973 /* 1974 * The number of bytes transferred is either whatever 1975 * is left in the descriptor (txDescCnt), or if there 1976 * is not enough room in the fifo, just whatever room 1977 * is left in the fifo 1978 */ 1979 txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); 1980 1981 txDmaAddr = txFragPtr & 0x3fffffff; 1982 txDmaData = txPacketBufPtr; 1983 txDmaLen = txXferLen; 1984 txDmaFree = dmaDataFree; 1985 1986 if (doTxDmaRead()) 1987 goto exit; 1988 } else { 1989 txState = txFifoBlock; 1990 transmit(); 1991 1992 goto exit; 1993 } 1994 1995 } 1996 break; 1997 1998 case txFragRead: 1999 if (txDmaState != dmaIdle) 2000 goto exit; 2001 2002 txPacketBufPtr += txXferLen; 2003 txFragPtr += txXferLen; 2004 txDescCnt -= txXferLen; 2005 txFifoAvail -= txXferLen; 2006 2007 txState = txFifoBlock; 2008 break; 2009 2010 case txDescWrite: 2011 if (txDmaState != dmaIdle) 2012 goto exit; 2013 2014 if (txDescCache.cmdsts & CMDSTS_INTR) 2015 devIntrPost(ISR_TXDESC); 2016 2017 txState = txAdvance; 2018 break; 2019 2020 case txAdvance: 2021 if (txDescCache.link == 0) { 2022 devIntrPost(ISR_TXIDLE); 2023 txState = txIdle; 2024 goto exit; 2025 } else { 2026 txState = txDescRead; 2027 regs.txdp = txDescCache.link; 2028 CTDD = false; 2029 2030 txDmaAddr = txDescCache.link & 0x3fffffff; 2031 txDmaData = &txDescCache; 2032 txDmaLen = sizeof(ns_desc); 2033 txDmaFree = dmaDescFree; 2034 2035 if (doTxDmaRead()) 2036 goto exit; 2037 } 2038 break; 2039 2040 default: 2041 panic("invalid state"); 2042 } 2043 2044 DPRINTF(EthernetSM, "entering next tx state=%s\n", 2045 NsTxStateStrings[txState]); 2046 2047 goto next; 2048 2049 exit: 2050 /** 2051 * @todo do we want to schedule a future kick? 2052 */ 2053 DPRINTF(EthernetSM, "tx state machine exited state=%s\n", 2054 NsTxStateStrings[txState]); 2055} 2056 2057void 2058NSGigE::transferDone() 2059{ 2060 if (txFifo.empty()) 2061 return; 2062 2063 if (txEvent.scheduled()) 2064 txEvent.reschedule(curTick + 1); 2065 else 2066 txEvent.schedule(curTick + 1); 2067} 2068 2069bool 2070NSGigE::rxFilter(PacketPtr packet) 2071{ 2072 bool drop = true; 2073 string type; 2074 2075 if (packet->IsUnicast()) { 2076 type = "unicast"; 2077 2078 // If we're accepting all unicast addresses 2079 if (acceptUnicast) 2080 drop = false; 2081 2082 // If we make a perfect match 2083 if (acceptPerfect && 2084 memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) 2085 drop = false; 2086 2087 eth_header *eth = (eth_header *) packet->data; 2088 if ((acceptArp) && (eth->type == 0x608)) 2089 drop = false; 2090 2091 } else if (packet->IsBroadcast()) { 2092 type = "broadcast"; 2093 2094 // if we're accepting broadcasts 2095 if (acceptBroadcast) 2096 drop = false; 2097 2098 } else if (packet->IsMulticast()) { 2099 type = "multicast"; 2100 2101 // if we're accepting all multicasts 2102 if (acceptMulticast) 2103 drop = false; 2104 2105 } else { 2106 type = "unknown"; 2107 2108 // oh well, punt on this one 2109 } 2110 2111 if (drop) { 2112 DPRINTF(Ethernet, "rxFilter drop\n"); 2113 DDUMP(EthernetData, packet->data, packet->length); 2114 } 2115 2116 return drop; 2117} 2118 2119bool 2120NSGigE::recvPacket(PacketPtr packet) 2121{ 2122 rxBytes += packet->length; 2123 rxPackets++; 2124 2125 DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail=%d\n", 2126 maxRxFifoSize - rxFifoCnt); 2127 2128 if (!rxEnable) { 2129 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2130 interface->recvDone(); 2131 return true; 2132 } 2133 2134 if (rxFilterEnable && rxFilter(packet)) { 2135 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2136 interface->recvDone(); 2137 return true; 2138 } 2139 2140 if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { 2141 DPRINTF(Ethernet, 2142 "packet will not fit in receive buffer...packet dropped\n"); 2143 devIntrPost(ISR_RXORN); 2144 return false; 2145 } 2146 2147 rxFifo.push_back(packet); 2148 rxFifoCnt += packet->length; 2149 interface->recvDone(); 2150 2151 rxKick(); 2152 return true; 2153} 2154 2155/** 2156 * does a udp checksum. if gen is true, then it generates it and puts 2157 * it in the right place else, it just checks what it calculates 2158 * against the value in the header in packet 2159 */ 2160bool 2161NSGigE::udpChecksum(PacketPtr packet, bool gen) 2162{ 2163 ip_header *ip = packet->getIpHdr(); 2164 udp_header *hdr = packet->getUdpHdr(ip); 2165 2166 pseudo_header *pseudo = new pseudo_header; 2167 2168 pseudo->src_ip_addr = ip->src_ip_addr; 2169 pseudo->dest_ip_addr = ip->dest_ip_addr; 2170 pseudo->protocol = ip->protocol; 2171 pseudo->len = hdr->len; 2172 2173 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2174 (uint32_t) hdr->len); 2175 2176 delete pseudo; 2177 if (gen) 2178 hdr->chksum = cksum; 2179 else 2180 if (cksum != 0) 2181 return false; 2182 2183 return true; 2184} 2185 2186bool 2187NSGigE::tcpChecksum(PacketPtr packet, bool gen) 2188{ 2189 ip_header *ip = packet->getIpHdr(); 2190 tcp_header *hdr = packet->getTcpHdr(ip); 2191 2192 uint16_t cksum; 2193 pseudo_header *pseudo = new pseudo_header; 2194 if (!gen) { 2195 pseudo->src_ip_addr = ip->src_ip_addr; 2196 pseudo->dest_ip_addr = ip->dest_ip_addr; 2197 pseudo->protocol = reverseEnd16(ip->protocol); 2198 pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - 2199 (ip->vers_len & 0xf)*4); 2200 2201 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2202 (uint32_t) reverseEnd16(pseudo->len)); 2203 } else { 2204 pseudo->src_ip_addr = 0; 2205 pseudo->dest_ip_addr = 0; 2206 pseudo->protocol = hdr->chksum; 2207 pseudo->len = 0; 2208 hdr->chksum = 0; 2209 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2210 (uint32_t) (reverseEnd16(ip->dgram_len) - 2211 (ip->vers_len & 0xf)*4)); 2212 } 2213 2214 delete pseudo; 2215 if (gen) 2216 hdr->chksum = cksum; 2217 else 2218 if (cksum != 0) 2219 return false; 2220 2221 return true; 2222} 2223 2224bool 2225NSGigE::ipChecksum(PacketPtr packet, bool gen) 2226{ 2227 ip_header *hdr = packet->getIpHdr(); 2228 2229 uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, 2230 (hdr->vers_len & 0xf)*4); 2231 2232 if (gen) { 2233 DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum); 2234 hdr->hdr_chksum = cksum; 2235 } 2236 else 2237 if (cksum != 0) 2238 return false; 2239 2240 return true; 2241} 2242 2243uint16_t 2244NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) 2245{ 2246 uint32_t sum = 0; 2247 2248 uint16_t last_pad = 0; 2249 if (len & 1) { 2250 last_pad = buf[len/2] & 0xff; 2251 len--; 2252 sum += last_pad; 2253 } 2254 2255 if (pseudo) { 2256 sum = pseudo[0] + pseudo[1] + pseudo[2] + 2257 pseudo[3] + pseudo[4] + pseudo[5]; 2258 } 2259 2260 for (int i=0; i < (len/2); ++i) { 2261 sum += buf[i]; 2262 } 2263 2264 while (sum >> 16) 2265 sum = (sum >> 16) + (sum & 0xffff); 2266 2267 return ~sum; 2268} 2269 2270//===================================================================== 2271// 2272// 2273void 2274NSGigE::serialize(ostream &os) 2275{ 2276 // Serialize the PciDev base class 2277 PciDev::serialize(os); 2278 2279 /* 2280 * Finalize any DMA events now. 2281 */ 2282 if (rxDmaReadEvent.scheduled()) 2283 rxDmaReadCopy(); 2284 if (rxDmaWriteEvent.scheduled()) 2285 rxDmaWriteCopy(); 2286 if (txDmaReadEvent.scheduled()) 2287 txDmaReadCopy(); 2288 if (txDmaWriteEvent.scheduled()) 2289 txDmaWriteCopy(); 2290 2291 /* 2292 * Serialize the device registers 2293 */ 2294 SERIALIZE_SCALAR(regs.command); 2295 SERIALIZE_SCALAR(regs.config); 2296 SERIALIZE_SCALAR(regs.mear); 2297 SERIALIZE_SCALAR(regs.ptscr); 2298 SERIALIZE_SCALAR(regs.isr); 2299 SERIALIZE_SCALAR(regs.imr); 2300 SERIALIZE_SCALAR(regs.ier); 2301 SERIALIZE_SCALAR(regs.ihr); 2302 SERIALIZE_SCALAR(regs.txdp); 2303 SERIALIZE_SCALAR(regs.txdp_hi); 2304 SERIALIZE_SCALAR(regs.txcfg); 2305 SERIALIZE_SCALAR(regs.gpior); 2306 SERIALIZE_SCALAR(regs.rxdp); 2307 SERIALIZE_SCALAR(regs.rxdp_hi); 2308 SERIALIZE_SCALAR(regs.rxcfg); 2309 SERIALIZE_SCALAR(regs.pqcr); 2310 SERIALIZE_SCALAR(regs.wcsr); 2311 SERIALIZE_SCALAR(regs.pcr); 2312 SERIALIZE_SCALAR(regs.rfcr); 2313 SERIALIZE_SCALAR(regs.rfdr); 2314 SERIALIZE_SCALAR(regs.srr); 2315 SERIALIZE_SCALAR(regs.mibc); 2316 SERIALIZE_SCALAR(regs.vrcr); 2317 SERIALIZE_SCALAR(regs.vtcr); 2318 SERIALIZE_SCALAR(regs.vdr); 2319 SERIALIZE_SCALAR(regs.ccsr); 2320 SERIALIZE_SCALAR(regs.tbicr); 2321 SERIALIZE_SCALAR(regs.tbisr); 2322 SERIALIZE_SCALAR(regs.tanar); 2323 SERIALIZE_SCALAR(regs.tanlpar); 2324 SERIALIZE_SCALAR(regs.taner); 2325 SERIALIZE_SCALAR(regs.tesr); 2326 2327 SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2328 2329 SERIALIZE_SCALAR(ioEnable); 2330 2331 /* 2332 * Serialize the data Fifos 2333 */ 2334 int txNumPkts = txFifo.size(); 2335 SERIALIZE_SCALAR(txNumPkts); 2336 int i = 0; 2337 pktiter_t end = txFifo.end(); 2338 for (pktiter_t p = txFifo.begin(); p != end; ++p) { 2339 nameOut(os, csprintf("%s.txFifo%d", name(), i++)); 2340 (*p)->serialize(os); 2341 } 2342 2343 int rxNumPkts = rxFifo.size(); 2344 SERIALIZE_SCALAR(rxNumPkts); 2345 i = 0; 2346 end = rxFifo.end(); 2347 for (pktiter_t p = rxFifo.begin(); p != end; ++p) { 2348 nameOut(os, csprintf("%s.rxFifo%d", name(), i++)); 2349 (*p)->serialize(os); 2350 } 2351 2352 /* 2353 * Serialize the various helper variables 2354 */ 2355 bool txPacketExists = txPacket; 2356 SERIALIZE_SCALAR(txPacketExists); 2357 if (txPacketExists) { 2358 nameOut(os, csprintf("%s.txPacket", name())); 2359 txPacket->serialize(os); 2360 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2361 SERIALIZE_SCALAR(txPktBufPtr); 2362 } 2363 2364 bool rxPacketExists = rxPacket; 2365 SERIALIZE_SCALAR(rxPacketExists); 2366 if (rxPacketExists) { 2367 nameOut(os, csprintf("%s.rxPacket", name())); 2368 rxPacket->serialize(os); 2369 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2370 SERIALIZE_SCALAR(rxPktBufPtr); 2371 } 2372 2373 SERIALIZE_SCALAR(txXferLen); 2374 SERIALIZE_SCALAR(rxXferLen); 2375 2376 /* 2377 * Serialize DescCaches 2378 */ 2379 SERIALIZE_SCALAR(txDescCache.link); 2380 SERIALIZE_SCALAR(txDescCache.bufptr); 2381 SERIALIZE_SCALAR(txDescCache.cmdsts); 2382 SERIALIZE_SCALAR(txDescCache.extsts); 2383 SERIALIZE_SCALAR(rxDescCache.link); 2384 SERIALIZE_SCALAR(rxDescCache.bufptr); 2385 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2386 SERIALIZE_SCALAR(rxDescCache.extsts); 2387 2388 /* 2389 * Serialize tx state machine 2390 */ 2391 int txState = this->txState; 2392 SERIALIZE_SCALAR(txState); 2393 SERIALIZE_SCALAR(txEnable); 2394 SERIALIZE_SCALAR(CTDD); 2395 SERIALIZE_SCALAR(txFifoAvail); 2396 SERIALIZE_SCALAR(txFragPtr); 2397 SERIALIZE_SCALAR(txDescCnt); 2398 int txDmaState = this->txDmaState; 2399 SERIALIZE_SCALAR(txDmaState); 2400 2401 /* 2402 * Serialize rx state machine 2403 */ 2404 int rxState = this->rxState; 2405 SERIALIZE_SCALAR(rxState); 2406 SERIALIZE_SCALAR(rxEnable); 2407 SERIALIZE_SCALAR(CRDD); 2408 SERIALIZE_SCALAR(rxPktBytes); 2409 SERIALIZE_SCALAR(rxFifoCnt); 2410 SERIALIZE_SCALAR(rxDescCnt); 2411 int rxDmaState = this->rxDmaState; 2412 SERIALIZE_SCALAR(rxDmaState); 2413 2414 SERIALIZE_SCALAR(extstsEnable); 2415 2416 /* 2417 * If there's a pending transmit, store the time so we can 2418 * reschedule it later 2419 */ 2420 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2421 SERIALIZE_SCALAR(transmitTick); 2422 2423 /* 2424 * receive address filter settings 2425 */ 2426 SERIALIZE_SCALAR(rxFilterEnable); 2427 SERIALIZE_SCALAR(acceptBroadcast); 2428 SERIALIZE_SCALAR(acceptMulticast); 2429 SERIALIZE_SCALAR(acceptUnicast); 2430 SERIALIZE_SCALAR(acceptPerfect); 2431 SERIALIZE_SCALAR(acceptArp); 2432 2433 /* 2434 * Keep track of pending interrupt status. 2435 */ 2436 SERIALIZE_SCALAR(intrTick); 2437 SERIALIZE_SCALAR(cpuPendingIntr); 2438 Tick intrEventTick = 0; 2439 if (intrEvent) 2440 intrEventTick = intrEvent->when(); 2441 SERIALIZE_SCALAR(intrEventTick); 2442 2443} 2444 2445void 2446NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2447{ 2448 // Unserialize the PciDev base class 2449 PciDev::unserialize(cp, section); 2450 2451 UNSERIALIZE_SCALAR(regs.command); 2452 UNSERIALIZE_SCALAR(regs.config); 2453 UNSERIALIZE_SCALAR(regs.mear); 2454 UNSERIALIZE_SCALAR(regs.ptscr); 2455 UNSERIALIZE_SCALAR(regs.isr); 2456 UNSERIALIZE_SCALAR(regs.imr); 2457 UNSERIALIZE_SCALAR(regs.ier); 2458 UNSERIALIZE_SCALAR(regs.ihr); 2459 UNSERIALIZE_SCALAR(regs.txdp); 2460 UNSERIALIZE_SCALAR(regs.txdp_hi); 2461 UNSERIALIZE_SCALAR(regs.txcfg); 2462 UNSERIALIZE_SCALAR(regs.gpior); 2463 UNSERIALIZE_SCALAR(regs.rxdp); 2464 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2465 UNSERIALIZE_SCALAR(regs.rxcfg); 2466 UNSERIALIZE_SCALAR(regs.pqcr); 2467 UNSERIALIZE_SCALAR(regs.wcsr); 2468 UNSERIALIZE_SCALAR(regs.pcr); 2469 UNSERIALIZE_SCALAR(regs.rfcr); 2470 UNSERIALIZE_SCALAR(regs.rfdr); 2471 UNSERIALIZE_SCALAR(regs.srr); 2472 UNSERIALIZE_SCALAR(regs.mibc); 2473 UNSERIALIZE_SCALAR(regs.vrcr); 2474 UNSERIALIZE_SCALAR(regs.vtcr); 2475 UNSERIALIZE_SCALAR(regs.vdr); 2476 UNSERIALIZE_SCALAR(regs.ccsr); 2477 UNSERIALIZE_SCALAR(regs.tbicr); 2478 UNSERIALIZE_SCALAR(regs.tbisr); 2479 UNSERIALIZE_SCALAR(regs.tanar); 2480 UNSERIALIZE_SCALAR(regs.tanlpar); 2481 UNSERIALIZE_SCALAR(regs.taner); 2482 UNSERIALIZE_SCALAR(regs.tesr); 2483 2484 UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2485 2486 UNSERIALIZE_SCALAR(ioEnable); 2487 2488 /* 2489 * unserialize the data fifos 2490 */ 2491 int txNumPkts; 2492 UNSERIALIZE_SCALAR(txNumPkts); 2493 int i; 2494 for (i = 0; i < txNumPkts; ++i) { 2495 PacketPtr p = new EtherPacket; 2496 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2497 txFifo.push_back(p); 2498 } 2499 2500 int rxNumPkts; 2501 UNSERIALIZE_SCALAR(rxNumPkts); 2502 for (i = 0; i < rxNumPkts; ++i) { 2503 PacketPtr p = new EtherPacket; 2504 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2505 rxFifo.push_back(p); 2506 } 2507 2508 /* 2509 * unserialize the various helper variables 2510 */ 2511 bool txPacketExists; 2512 UNSERIALIZE_SCALAR(txPacketExists); 2513 if (txPacketExists) { 2514 txPacket = new EtherPacket; 2515 txPacket->unserialize(cp, csprintf("%s.txPacket", section)); 2516 uint32_t txPktBufPtr; 2517 UNSERIALIZE_SCALAR(txPktBufPtr); 2518 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2519 } else 2520 txPacket = 0; 2521 2522 bool rxPacketExists; 2523 UNSERIALIZE_SCALAR(rxPacketExists); 2524 rxPacket = 0; 2525 if (rxPacketExists) { 2526 rxPacket = new EtherPacket; 2527 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 2528 uint32_t rxPktBufPtr; 2529 UNSERIALIZE_SCALAR(rxPktBufPtr); 2530 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2531 } else 2532 rxPacket = 0; 2533 2534 UNSERIALIZE_SCALAR(txXferLen); 2535 UNSERIALIZE_SCALAR(rxXferLen); 2536 2537 /* 2538 * Unserialize DescCaches 2539 */ 2540 UNSERIALIZE_SCALAR(txDescCache.link); 2541 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2542 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2543 UNSERIALIZE_SCALAR(txDescCache.extsts); 2544 UNSERIALIZE_SCALAR(rxDescCache.link); 2545 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2546 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2547 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2548 2549 /* 2550 * unserialize tx state machine 2551 */ 2552 int txState; 2553 UNSERIALIZE_SCALAR(txState); 2554 this->txState = (TxState) txState; 2555 UNSERIALIZE_SCALAR(txEnable); 2556 UNSERIALIZE_SCALAR(CTDD); 2557 UNSERIALIZE_SCALAR(txFifoAvail); 2558 UNSERIALIZE_SCALAR(txFragPtr); 2559 UNSERIALIZE_SCALAR(txDescCnt); 2560 int txDmaState; 2561 UNSERIALIZE_SCALAR(txDmaState); 2562 this->txDmaState = (DmaState) txDmaState; 2563 2564 /* 2565 * unserialize rx state machine 2566 */ 2567 int rxState; 2568 UNSERIALIZE_SCALAR(rxState); 2569 this->rxState = (RxState) rxState; 2570 UNSERIALIZE_SCALAR(rxEnable); 2571 UNSERIALIZE_SCALAR(CRDD); 2572 UNSERIALIZE_SCALAR(rxPktBytes); 2573 UNSERIALIZE_SCALAR(rxFifoCnt); 2574 UNSERIALIZE_SCALAR(rxDescCnt); 2575 int rxDmaState; 2576 UNSERIALIZE_SCALAR(rxDmaState); 2577 this->rxDmaState = (DmaState) rxDmaState; 2578 2579 UNSERIALIZE_SCALAR(extstsEnable); 2580 2581 /* 2582 * If there's a pending transmit, reschedule it now 2583 */ 2584 Tick transmitTick; 2585 UNSERIALIZE_SCALAR(transmitTick); 2586 if (transmitTick) 2587 txEvent.schedule(curTick + transmitTick); 2588 2589 /* 2590 * unserialize receive address filter settings 2591 */ 2592 UNSERIALIZE_SCALAR(rxFilterEnable); 2593 UNSERIALIZE_SCALAR(acceptBroadcast); 2594 UNSERIALIZE_SCALAR(acceptMulticast); 2595 UNSERIALIZE_SCALAR(acceptUnicast); 2596 UNSERIALIZE_SCALAR(acceptPerfect); 2597 UNSERIALIZE_SCALAR(acceptArp); 2598 2599 /* 2600 * Keep track of pending interrupt status. 2601 */ 2602 UNSERIALIZE_SCALAR(intrTick); 2603 UNSERIALIZE_SCALAR(cpuPendingIntr); 2604 Tick intrEventTick; 2605 UNSERIALIZE_SCALAR(intrEventTick); 2606 if (intrEventTick) { 2607 intrEvent = new IntrEvent(this, true); 2608 intrEvent->schedule(intrEventTick); 2609 } 2610 2611 /* 2612 * re-add addrRanges to bus bridges 2613 */ 2614 if (pioInterface) { 2615 pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1); 2616 pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1); 2617 } 2618} 2619 2620Tick 2621NSGigE::cacheAccess(MemReqPtr &req) 2622{ 2623 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2624 req->paddr, req->paddr - addr); 2625 return curTick + pioLatency; 2626} 2627//===================================================================== 2628 2629 2630//********** helper functions****************************************** 2631 2632uint16_t reverseEnd16(uint16_t num) 2633{ 2634 uint16_t reverse = (num & 0xff)<<8; 2635 reverse += ((num & 0xff00) >> 8); 2636 return reverse; 2637} 2638 2639uint32_t reverseEnd32(uint32_t num) 2640{ 2641 uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16; 2642 reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8)); 2643 return reverse; 2644} 2645 2646 2647 2648//===================================================================== 2649 2650BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2651 2652 SimObjectParam<EtherInt *> peer; 2653 SimObjectParam<NSGigE *> device; 2654 2655END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2656 2657BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2658 2659 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2660 INIT_PARAM(device, "Ethernet device of this interface") 2661 2662END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2663 2664CREATE_SIM_OBJECT(NSGigEInt) 2665{ 2666 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2667 2668 EtherInt *p = (EtherInt *)peer; 2669 if (p) { 2670 dev_int->setPeer(p); 2671 p->setPeer(dev_int); 2672 } 2673 2674 return dev_int; 2675} 2676 2677REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2678 2679 2680BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2681 2682 Param<Tick> tx_delay; 2683 Param<Tick> rx_delay; 2684 SimObjectParam<IntrControl *> intr_ctrl; 2685 Param<Tick> intr_delay; 2686 SimObjectParam<MemoryController *> mmu; 2687 SimObjectParam<PhysicalMemory *> physmem; 2688 Param<bool> rx_filter; 2689 Param<string> hardware_address; 2690 SimObjectParam<Bus*> header_bus; 2691 SimObjectParam<Bus*> payload_bus; 2692 SimObjectParam<HierParams *> hier; 2693 Param<Tick> pio_latency; 2694 Param<bool> dma_desc_free; 2695 Param<bool> dma_data_free; 2696 Param<Tick> dma_read_delay; 2697 Param<Tick> dma_write_delay; 2698 Param<Tick> dma_read_factor; 2699 Param<Tick> dma_write_factor; 2700 SimObjectParam<PciConfigAll *> configspace; 2701 SimObjectParam<PciConfigData *> configdata; 2702 SimObjectParam<Tsunami *> tsunami; 2703 Param<uint32_t> pci_bus; 2704 Param<uint32_t> pci_dev; 2705 Param<uint32_t> pci_func; 2706 Param<uint32_t> tx_fifo_size; 2707 Param<uint32_t> rx_fifo_size; 2708 2709END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2710 2711BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2712 2713 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 2714 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 2715 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 2716 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), 2717 INIT_PARAM(mmu, "Memory Controller"), 2718 INIT_PARAM(physmem, "Physical Memory"), 2719 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2720 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2721 "00:99:00:00:00:01"), 2722 INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), 2723 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2724 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2725 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2726 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2727 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2728 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2729 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2730 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2731 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2732 INIT_PARAM(configspace, "PCI Configspace"), 2733 INIT_PARAM(configdata, "PCI Config data"), 2734 INIT_PARAM(tsunami, "Tsunami"), 2735 INIT_PARAM(pci_bus, "PCI bus"), 2736 INIT_PARAM(pci_dev, "PCI device number"), 2737 INIT_PARAM(pci_func, "PCI function code"), 2738 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2739 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072) 2740 2741END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2742 2743 2744CREATE_SIM_OBJECT(NSGigE) 2745{ 2746 int eaddr[6]; 2747 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 2748 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 2749 2750 return new NSGigE(getInstanceName(), intr_ctrl, intr_delay, 2751 physmem, tx_delay, rx_delay, mmu, hier, header_bus, 2752 payload_bus, pio_latency, dma_desc_free, dma_data_free, 2753 dma_read_delay, dma_write_delay, dma_read_factor, 2754 dma_write_factor, configspace, configdata, 2755 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 2756 tx_fifo_size, rx_fifo_size); 2757} 2758 2759REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2760