ns_gige.cc revision 1078
12292SN/A/* 28948Sandreas.hansson@arm.com * Copyright (c) 2004 The Regents of The University of Michigan 38707Sandreas.hansson@arm.com * All rights reserved. 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142727Sktlim@umich.edu * this software without specific prior written permission. 152292SN/A * 162292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272292SN/A */ 282292SN/A 292292SN/A/* @file 302292SN/A * Device module for modelling the National Semiconductor 312292SN/A * DP83820 ethernet controller. Does not support priority queueing 322292SN/A */ 332292SN/A#include <cstdio> 342292SN/A#include <deque> 352292SN/A#include <string> 362292SN/A 372292SN/A#include "base/inet.hh" 382292SN/A#include "cpu/exec_context.hh" 392689Sktlim@umich.edu#include "cpu/intr_control.hh" 402689Sktlim@umich.edu#include "dev/dma.hh" 412292SN/A#include "dev/etherlink.hh" 422292SN/A#include "dev/ns_gige.hh" 432329SN/A#include "dev/pciconfigall.hh" 442980Sgblack@eecs.umich.edu#include "dev/tsunami_cchip.hh" 452329SN/A#include "mem/bus/bus.hh" 462329SN/A#include "mem/bus/dma_interface.hh" 472292SN/A#include "mem/bus/pio_interface.hh" 489444SAndreas.Sandberg@ARM.com#include "mem/bus/pio_interface_impl.hh" 498232Snate@binkert.org#include "mem/functional_mem/memory_control.hh" 508232Snate@binkert.org#include "mem/functional_mem/physical_memory.hh" 518232Snate@binkert.org#include "sim/builder.hh" 526221Snate@binkert.org#include "sim/debug.hh" 532292SN/A#include "sim/host.hh" 546221Snate@binkert.org#include "sim/sim_stats.hh" 555529Snate@binkert.org#include "targetarch/vtophys.hh" 562292SN/A 575529Snate@binkert.orgconst char *NsRxStateStrings[] = 588707Sandreas.hansson@arm.com{ 594329Sktlim@umich.edu "rxIdle", 604329Sktlim@umich.edu "rxDescRefr", 615529Snate@binkert.org "rxDescRead", 622907Sktlim@umich.edu "rxFifoBlock", 632292SN/A "rxFragWrite", 642292SN/A "rxDescWrite", 652292SN/A "rxAdvance" 662292SN/A}; 672980Sgblack@eecs.umich.edu 682292SN/Aconst char *NsTxStateStrings[] = 692292SN/A{ 702292SN/A "txIdle", 712292SN/A "txDescRefr", 722292SN/A "txDescRead", 732292SN/A "txFifoBlock", 742292SN/A "txFragRead", 752292SN/A "txDescWrite", 762292SN/A "txAdvance" 772292SN/A}; 782292SN/A 794329Sktlim@umich.educonst char *NsDmaState[] = 802292SN/A{ 812292SN/A "dmaIdle", 822292SN/A "dmaReading", 832292SN/A "dmaWriting", 842292SN/A "dmaReadWaiting", 852292SN/A "dmaWriteWaiting" 862292SN/A}; 874329Sktlim@umich.edu 882292SN/Ausing namespace std; 898346Sksewell@umich.edu 902292SN/A 912292SN/A/////////////////////////////////////////////////////////////////////// 922292SN/A// 932292SN/A// NSGigE PCI Device 942292SN/A// 952292SN/ANSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, 962292SN/A PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, 972292SN/A MemoryController *mmu, HierParams *hier, Bus *header_bus, 982292SN/A Bus *payload_bus, Tick pio_latency, bool dma_desc_free, 992292SN/A bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, 1002292SN/A Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, 1012292SN/A PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, 1024329Sktlim@umich.edu uint32_t func, bool rx_filter, const int eaddr[6], 1032292SN/A uint32_t tx_fifo_size, uint32_t rx_fifo_size) 1048346Sksewell@umich.edu : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), 1052292SN/A maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), 1062292SN/A txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 1072292SN/A txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), 1082292SN/A CTDD(false), txFifoAvail(tx_fifo_size), 1092292SN/A txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 1102292SN/A rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), 1112292SN/A rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1126221Snate@binkert.org rxDmaReadEvent(this), rxDmaWriteEvent(this), 1134329Sktlim@umich.edu txDmaReadEvent(this), txDmaWriteEvent(this), 1144329Sktlim@umich.edu dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free), 1158850Sandreas.hansson@arm.com txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0), 1162292SN/A txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false), 1172292SN/A acceptMulticast(false), acceptUnicast(false), 1182292SN/A acceptPerfect(false), acceptArp(false), 1192292SN/A physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), 1202292SN/A intrEvent(0), interface(0) 1212292SN/A{ 1222292SN/A tsunami->ethernet = this; 1232292SN/A 1242292SN/A if (header_bus) { 1252292SN/A pioInterface = newPioInterface(name, hier, header_bus, this, 1262292SN/A &NSGigE::cacheAccess); 1272292SN/A 1282292SN/A pioLatency = pio_latency * header_bus->clockRatio; 1292727Sktlim@umich.edu 1302727Sktlim@umich.edu if (payload_bus) 1312727Sktlim@umich.edu dmaInterface = new DMAInterface<Bus>(name + ".dma", 1326221Snate@binkert.org header_bus, payload_bus, 1); 1332727Sktlim@umich.edu else 1342727Sktlim@umich.edu dmaInterface = new DMAInterface<Bus>(name + ".dma", 1352727Sktlim@umich.edu header_bus, header_bus, 1); 1362727Sktlim@umich.edu } else if (payload_bus) { 1372727Sktlim@umich.edu pioInterface = newPioInterface(name, hier, payload_bus, this, 1382727Sktlim@umich.edu &NSGigE::cacheAccess); 1396221Snate@binkert.org 1402292SN/A pioLatency = pio_latency * payload_bus->clockRatio; 1412292SN/A 1422292SN/A dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, 1432292SN/A payload_bus, 1); 1442292SN/A } 1452292SN/A 1462307SN/A 1479444SAndreas.Sandberg@ARM.com intrDelay = US2Ticks(intr_delay); 1482307SN/A dmaReadDelay = dma_read_delay; 1499444SAndreas.Sandberg@ARM.com dmaWriteDelay = dma_write_delay; 1509444SAndreas.Sandberg@ARM.com dmaReadFactor = dma_read_factor; 1519444SAndreas.Sandberg@ARM.com dmaWriteFactor = dma_write_factor; 1529444SAndreas.Sandberg@ARM.com 1539444SAndreas.Sandberg@ARM.com regsReset(); 1549444SAndreas.Sandberg@ARM.com rom.perfectMatch[0] = eaddr[0]; 1559444SAndreas.Sandberg@ARM.com rom.perfectMatch[1] = eaddr[1]; 1569444SAndreas.Sandberg@ARM.com rom.perfectMatch[2] = eaddr[2]; 1579444SAndreas.Sandberg@ARM.com rom.perfectMatch[3] = eaddr[3]; 1589444SAndreas.Sandberg@ARM.com rom.perfectMatch[4] = eaddr[4]; 1599444SAndreas.Sandberg@ARM.com rom.perfectMatch[5] = eaddr[5]; 1609444SAndreas.Sandberg@ARM.com} 1619444SAndreas.Sandberg@ARM.com 1629444SAndreas.Sandberg@ARM.comNSGigE::~NSGigE() 1639444SAndreas.Sandberg@ARM.com{} 1642307SN/A 1659444SAndreas.Sandberg@ARM.comvoid 1669444SAndreas.Sandberg@ARM.comNSGigE::regStats() 1679444SAndreas.Sandberg@ARM.com{ 1689444SAndreas.Sandberg@ARM.com txBytes 1699444SAndreas.Sandberg@ARM.com .name(name() + ".txBytes") 1709444SAndreas.Sandberg@ARM.com .desc("Bytes Transmitted") 1719444SAndreas.Sandberg@ARM.com .prereq(txBytes) 1729444SAndreas.Sandberg@ARM.com ; 1739444SAndreas.Sandberg@ARM.com 1749444SAndreas.Sandberg@ARM.com rxBytes 1759444SAndreas.Sandberg@ARM.com .name(name() + ".rxBytes") 1769444SAndreas.Sandberg@ARM.com .desc("Bytes Received") 1772307SN/A .prereq(rxBytes) 1782307SN/A ; 1792307SN/A 1802307SN/A txPackets 1812307SN/A .name(name() + ".txPackets") 1822307SN/A .desc("Number of Packets Transmitted") 1836221Snate@binkert.org .prereq(txBytes) 1842307SN/A ; 1852307SN/A 1862307SN/A rxPackets 1872307SN/A .name(name() + ".rxPackets") 1882307SN/A .desc("Number of Packets Received") 1892292SN/A .prereq(rxBytes) 1906221Snate@binkert.org ; 1912292SN/A 1922292SN/A txIpChecksums 1932292SN/A .name(name() + ".txIpChecksums") 1942292SN/A .desc("Number of tx IP Checksums done by device") 1952292SN/A .precision(0) 1962292SN/A .prereq(txBytes) 1972292SN/A ; 1982292SN/A 1992292SN/A rxIpChecksums 2002292SN/A .name(name() + ".rxIpChecksums") 2012292SN/A .desc("Number of rx IP Checksums done by device") 2022292SN/A .precision(0) 2032292SN/A .prereq(rxBytes) 2043867Sbinkertn@umich.edu ; 2052292SN/A 2062292SN/A txTcpChecksums 2072292SN/A .name(name() + ".txTcpChecksums") 2082292SN/A .desc("Number of tx TCP Checksums done by device") 2092292SN/A .precision(0) 2102292SN/A .prereq(txBytes) 2112292SN/A ; 2122292SN/A 2132292SN/A rxTcpChecksums 2142292SN/A .name(name() + ".rxTcpChecksums") 2152292SN/A .desc("Number of rx TCP Checksums done by device") 2166221Snate@binkert.org .precision(0) 2176221Snate@binkert.org .prereq(rxBytes) 2183867Sbinkertn@umich.edu ; 2193867Sbinkertn@umich.edu 2206221Snate@binkert.org txUdpChecksums 2213867Sbinkertn@umich.edu .name(name() + ".txUdpChecksums") 2223867Sbinkertn@umich.edu .desc("Number of tx UDP Checksums done by device") 2232292SN/A .precision(0) 2242292SN/A .prereq(txBytes) 2252292SN/A ; 2262292SN/A 2272292SN/A rxUdpChecksums 2282292SN/A .name(name() + ".rxUdpChecksums") 2296221Snate@binkert.org .desc("Number of rx UDP Checksums done by device") 2302292SN/A .precision(0) 2312292SN/A .prereq(rxBytes) 2322292SN/A ; 2332292SN/A 2342292SN/A descDmaReads 2352292SN/A .name(name() + ".descDMAReads") 2362292SN/A .desc("Number of descriptors the device read w/ DMA") 2376221Snate@binkert.org .precision(0) 2382292SN/A ; 2392292SN/A 2402292SN/A descDmaWrites 2412292SN/A .name(name() + ".descDMAWrites") 2422292SN/A .desc("Number of descriptors the device wrote w/ DMA") 2432292SN/A .precision(0) 2442292SN/A ; 2452292SN/A 2462292SN/A descDmaRdBytes 2476221Snate@binkert.org .name(name() + ".descDmaReadBytes") 2486221Snate@binkert.org .desc("number of descriptor bytes read w/ DMA") 2492292SN/A .precision(0) 2503867Sbinkertn@umich.edu ; 2516221Snate@binkert.org 2522292SN/A descDmaWrBytes 2532292SN/A .name(name() + ".descDmaWriteBytes") 2542292SN/A .desc("number of descriptor bytes write w/ DMA") 2552292SN/A .precision(0) 2562292SN/A ; 2572292SN/A 2582292SN/A 2592292SN/A txBandwidth 2602292SN/A .name(name() + ".txBandwidth") 2616221Snate@binkert.org .desc("Transmit Bandwidth (bits/s)") 2622292SN/A .precision(0) 2632292SN/A .prereq(txBytes) 2642292SN/A ; 2652292SN/A 2662292SN/A rxBandwidth 2672292SN/A .name(name() + ".rxBandwidth") 2682292SN/A .desc("Receive Bandwidth (bits/s)") 2692292SN/A .precision(0) 2706221Snate@binkert.org .prereq(rxBytes) 2712292SN/A ; 2722292SN/A 2732292SN/A txPacketRate 2742292SN/A .name(name() + ".txPPS") 2752292SN/A .desc("Packet Tranmission Rate (packets/s)") 2762292SN/A .precision(0) 2772292SN/A .prereq(txBytes) 2782292SN/A ; 2796221Snate@binkert.org 2802292SN/A rxPacketRate 2812292SN/A .name(name() + ".rxPPS") 2822292SN/A .desc("Packet Reception Rate (packets/s)") 2832292SN/A .precision(0) 2842292SN/A .prereq(rxBytes) 2852292SN/A ; 2862292SN/A 2872292SN/A txBandwidth = txBytes * Stats::constant(8) / simSeconds; 2886221Snate@binkert.org rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 2892292SN/A txPacketRate = txPackets / simSeconds; 2902292SN/A rxPacketRate = rxPackets / simSeconds; 2912292SN/A} 2922292SN/A 2932292SN/A/** 2942292SN/A * This is to read the PCI general configuration registers 2952292SN/A */ 2962292SN/Avoid 2976221Snate@binkert.orgNSGigE::ReadConfig(int offset, int size, uint8_t *data) 2986221Snate@binkert.org{ 2992292SN/A if (offset < PCI_DEVICE_SPECIFIC) 3003867Sbinkertn@umich.edu PciDev::ReadConfig(offset, size, data); 3016221Snate@binkert.org else 3022292SN/A panic("Device specific PCI config space not implemented!\n"); 3032292SN/A} 3042329SN/A 3052329SN/A/** 3062292SN/A * This is to write to the PCI general configuration registers 3072292SN/A */ 3082292SN/Avoid 3092292SN/ANSGigE::WriteConfig(int offset, int size, uint32_t data) 3102292SN/A{ 3112292SN/A if (offset < PCI_DEVICE_SPECIFIC) 3122292SN/A PciDev::WriteConfig(offset, size, data); 3132292SN/A else 3142292SN/A panic("Device specific PCI config space not implemented!\n"); 3152292SN/A 3162292SN/A // Need to catch writes to BARs to update the PIO interface 3176221Snate@binkert.org switch (offset) { 3186221Snate@binkert.org // seems to work fine without all these PCI settings, but i 3192292SN/A // put in the IO to double check, an assertion will fail if we 3203867Sbinkertn@umich.edu // need to properly implement it 3216221Snate@binkert.org case PCI_COMMAND: 3223867Sbinkertn@umich.edu if (config.data[offset] & PCI_CMD_IOSE) 3232292SN/A ioEnable = true; 3242292SN/A else 3252292SN/A ioEnable = false; 3262292SN/A 3272292SN/A#if 0 3282292SN/A if (config.data[offset] & PCI_CMD_BME) { 3292292SN/A bmEnabled = true; 3308707Sandreas.hansson@arm.com } 3318707Sandreas.hansson@arm.com else { 3328707Sandreas.hansson@arm.com bmEnabled = false; 3338707Sandreas.hansson@arm.com } 3348707Sandreas.hansson@arm.com 3358707Sandreas.hansson@arm.com if (config.data[offset] & PCI_CMD_MSE) { 3368707Sandreas.hansson@arm.com memEnable = true; 3378707Sandreas.hansson@arm.com } 3388707Sandreas.hansson@arm.com else { 3398707Sandreas.hansson@arm.com memEnable = false; 3408707Sandreas.hansson@arm.com } 3418707Sandreas.hansson@arm.com#endif 3428707Sandreas.hansson@arm.com break; 3438707Sandreas.hansson@arm.com 3448707Sandreas.hansson@arm.com case PCI0_BASE_ADDR0: 3458707Sandreas.hansson@arm.com if (BARAddrs[0] != 0) { 3468707Sandreas.hansson@arm.com if (pioInterface) 3478707Sandreas.hansson@arm.com pioInterface->addAddrRange(BARAddrs[0], 3488975Sandreas.hansson@arm.com BARAddrs[0] + BARSize[0] - 1); 3498707Sandreas.hansson@arm.com 3508707Sandreas.hansson@arm.com BARAddrs[0] &= PA_UNCACHED_MASK; 3518707Sandreas.hansson@arm.com } 3528707Sandreas.hansson@arm.com break; 3538948Sandreas.hansson@arm.com case PCI0_BASE_ADDR1: 3548948Sandreas.hansson@arm.com if (BARAddrs[1] != 0) { 3558948Sandreas.hansson@arm.com if (pioInterface) 3568707Sandreas.hansson@arm.com pioInterface->addAddrRange(BARAddrs[1], 3578948Sandreas.hansson@arm.com BARAddrs[1] + BARSize[1] - 1); 3588975Sandreas.hansson@arm.com 3598975Sandreas.hansson@arm.com BARAddrs[1] &= PA_UNCACHED_MASK; 3608948Sandreas.hansson@arm.com } 3618948Sandreas.hansson@arm.com break; 3628948Sandreas.hansson@arm.com } 3638948Sandreas.hansson@arm.com} 3648948Sandreas.hansson@arm.com 3658948Sandreas.hansson@arm.com/** 3668948Sandreas.hansson@arm.com * This reads the device registers, which are detailed in the NS83820 3678948Sandreas.hansson@arm.com * spec sheet 3688948Sandreas.hansson@arm.com */ 3698948Sandreas.hansson@arm.comFault 3708707Sandreas.hansson@arm.comNSGigE::read(MemReqPtr &req, uint8_t *data) 3718707Sandreas.hansson@arm.com{ 3728707Sandreas.hansson@arm.com assert(ioEnable); 3738707Sandreas.hansson@arm.com 3742292SN/A //The mask is to give you only the offset into the device register file 3752292SN/A Addr daddr = req->paddr & 0xfff; 3762292SN/A DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 3772292SN/A daddr, req->paddr, req->vaddr, req->size); 3782292SN/A 3792292SN/A 3806221Snate@binkert.org // there are some reserved registers, you can see ns_gige_reg.h and 3816221Snate@binkert.org // the spec sheet for details 3822292SN/A if (daddr > LAST && daddr <= RESERVED) { 3833867Sbinkertn@umich.edu panic("Accessing reserved register"); 3846221Snate@binkert.org } else if (daddr > RESERVED && daddr <= 0x3FC) { 3853867Sbinkertn@umich.edu ReadConfig(daddr & 0xff, req->size, data); 3862292SN/A return No_Fault; 3872292SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 3882292SN/A // don't implement all the MIB's. hopefully the kernel 3892292SN/A // doesn't actually DEPEND upon their values 3902292SN/A // MIB are just hardware stats keepers 3912292SN/A uint32_t ® = *(uint32_t *) data; 3922292SN/A reg = 0; 3932292SN/A return No_Fault; 3942292SN/A } else if (daddr > 0x3FC) 3952292SN/A panic("Something is messed up!\n"); 3962292SN/A 3972292SN/A switch (req->size) { 3986221Snate@binkert.org case sizeof(uint32_t): 3996221Snate@binkert.org { 4002292SN/A uint32_t ® = *(uint32_t *)data; 4013867Sbinkertn@umich.edu 4026221Snate@binkert.org switch (daddr) { 4033867Sbinkertn@umich.edu case CR: 4042292SN/A reg = regs.command; 4052292SN/A //these are supposed to be cleared on a read 4062292SN/A reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 4072292SN/A break; 4082292SN/A 4092292SN/A case CFG: 4102292SN/A reg = regs.config; 4112292SN/A break; 4122292SN/A 4132292SN/A case MEAR: 4142292SN/A reg = regs.mear; 4152292SN/A break; 4166221Snate@binkert.org 4176221Snate@binkert.org case PTSCR: 4182292SN/A reg = regs.ptscr; 4193867Sbinkertn@umich.edu break; 4206221Snate@binkert.org 4213867Sbinkertn@umich.edu case ISR: 4222292SN/A reg = regs.isr; 4232292SN/A devIntrClear(ISR_ALL); 4242292SN/A break; 4252292SN/A 4262292SN/A case IMR: 4272292SN/A reg = regs.imr; 4282292SN/A break; 4292292SN/A 4302292SN/A case IER: 4312292SN/A reg = regs.ier; 4322292SN/A break; 4332292SN/A 4346221Snate@binkert.org case IHR: 4356221Snate@binkert.org reg = regs.ihr; 4362292SN/A break; 4373867Sbinkertn@umich.edu 4386221Snate@binkert.org case TXDP: 4393867Sbinkertn@umich.edu reg = regs.txdp; 4402292SN/A break; 4412292SN/A 4422292SN/A case TXDP_HI: 4432292SN/A reg = regs.txdp_hi; 4442292SN/A break; 4452292SN/A 4462292SN/A case TXCFG: 4472292SN/A reg = regs.txcfg; 4486221Snate@binkert.org break; 4492292SN/A 4503870Sbinkertn@umich.edu case GPIOR: 4512292SN/A reg = regs.gpior; 4522292SN/A break; 4532292SN/A 4542292SN/A case RXDP: 4552292SN/A reg = regs.rxdp; 4562292SN/A break; 4572292SN/A 4582292SN/A case RXDP_HI: 4592292SN/A reg = regs.rxdp_hi; 4606221Snate@binkert.org break; 4616221Snate@binkert.org 4622292SN/A case RXCFG: 4633867Sbinkertn@umich.edu reg = regs.rxcfg; 4646221Snate@binkert.org break; 4653867Sbinkertn@umich.edu 4663867Sbinkertn@umich.edu case PQCR: 4672292SN/A reg = regs.pqcr; 4682292SN/A break; 4692292SN/A 4702292SN/A case WCSR: 4712292SN/A reg = regs.wcsr; 4722292SN/A break; 4732292SN/A 4742292SN/A case PCR: 4756221Snate@binkert.org reg = regs.pcr; 4762292SN/A break; 4772292SN/A 4782292SN/A // see the spec sheet for how RFCR and RFDR work 4793867Sbinkertn@umich.edu // basically, you write to RFCR to tell the machine 4802292SN/A // what you want to do next, then you act upon RFDR, 4812292SN/A // and the device will be prepared b/c of what you 4822292SN/A // wrote to RFCR 4832292SN/A case RFCR: 4842292SN/A reg = regs.rfcr; 4852292SN/A break; 4862292SN/A 4879444SAndreas.Sandberg@ARM.com case RFDR: 4889444SAndreas.Sandberg@ARM.com switch (regs.rfcr & RFCR_RFADDR) { 4899444SAndreas.Sandberg@ARM.com case 0x000: 4909444SAndreas.Sandberg@ARM.com reg = rom.perfectMatch[1]; 4919444SAndreas.Sandberg@ARM.com reg = reg << 8; 4929444SAndreas.Sandberg@ARM.com reg += rom.perfectMatch[0]; 4939444SAndreas.Sandberg@ARM.com break; 4949444SAndreas.Sandberg@ARM.com case 0x002: 4959444SAndreas.Sandberg@ARM.com reg = rom.perfectMatch[3] << 8; 4969444SAndreas.Sandberg@ARM.com reg += rom.perfectMatch[2]; 4979444SAndreas.Sandberg@ARM.com break; 4989444SAndreas.Sandberg@ARM.com case 0x004: 4999444SAndreas.Sandberg@ARM.com reg = rom.perfectMatch[5] << 8; 5009444SAndreas.Sandberg@ARM.com reg += rom.perfectMatch[4]; 5019444SAndreas.Sandberg@ARM.com break; 5029444SAndreas.Sandberg@ARM.com default: 5039444SAndreas.Sandberg@ARM.com panic("reading RFDR for something other than PMATCH!\n"); 5049444SAndreas.Sandberg@ARM.com // didn't implement other RFDR functionality b/c 5059444SAndreas.Sandberg@ARM.com // driver didn't use it 5069444SAndreas.Sandberg@ARM.com } 5079444SAndreas.Sandberg@ARM.com break; 5089444SAndreas.Sandberg@ARM.com 5099444SAndreas.Sandberg@ARM.com case SRR: 5109444SAndreas.Sandberg@ARM.com reg = regs.srr; 5119444SAndreas.Sandberg@ARM.com break; 5129444SAndreas.Sandberg@ARM.com 5139444SAndreas.Sandberg@ARM.com case MIBC: 5149444SAndreas.Sandberg@ARM.com reg = regs.mibc; 5159444SAndreas.Sandberg@ARM.com reg &= ~(MIBC_MIBS | MIBC_ACLR); 5169444SAndreas.Sandberg@ARM.com break; 5179444SAndreas.Sandberg@ARM.com 5189444SAndreas.Sandberg@ARM.com case VRCR: 5199444SAndreas.Sandberg@ARM.com reg = regs.vrcr; 5209444SAndreas.Sandberg@ARM.com break; 5219444SAndreas.Sandberg@ARM.com 5229444SAndreas.Sandberg@ARM.com case VTCR: 5239444SAndreas.Sandberg@ARM.com reg = regs.vtcr; 5249444SAndreas.Sandberg@ARM.com break; 5259444SAndreas.Sandberg@ARM.com 5269444SAndreas.Sandberg@ARM.com case VDR: 5279444SAndreas.Sandberg@ARM.com reg = regs.vdr; 5282292SN/A break; 5292292SN/A 5306221Snate@binkert.org case CCSR: 5316221Snate@binkert.org reg = regs.ccsr; 5322292SN/A break; 5333867Sbinkertn@umich.edu 5346221Snate@binkert.org case TBICR: 5353867Sbinkertn@umich.edu reg = regs.tbicr; 5362292SN/A break; 5372292SN/A 5382292SN/A case TBISR: 5392292SN/A reg = regs.tbisr; 5402292SN/A break; 5412292SN/A 5422292SN/A case TANAR: 5432292SN/A reg = regs.tanar; 5442292SN/A break; 5456221Snate@binkert.org 5462292SN/A case TANLPAR: 5472292SN/A reg = regs.tanlpar; 5482292SN/A break; 5493870Sbinkertn@umich.edu 5502292SN/A case TANER: 5512292SN/A reg = regs.taner; 5522292SN/A break; 5532292SN/A 5542292SN/A case TESR: 5552292SN/A reg = regs.tesr; 5562292SN/A break; 5572292SN/A 5582292SN/A default: 5596221Snate@binkert.org panic("reading unimplemented register: addr=%#x", daddr); 5606221Snate@binkert.org } 5612292SN/A 5623867Sbinkertn@umich.edu DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 5636221Snate@binkert.org daddr, reg, reg); 5643867Sbinkertn@umich.edu } 5652292SN/A break; 5662292SN/A 5672292SN/A default: 5682292SN/A panic("accessing register with invalid size: addr=%#x, size=%d", 5692292SN/A daddr, req->size); 5702292SN/A } 5712292SN/A 5722292SN/A return No_Fault; 5732292SN/A} 5746221Snate@binkert.org 5752292SN/AFault 5762292SN/ANSGigE::write(MemReqPtr &req, const uint8_t *data) 5772292SN/A{ 5783870Sbinkertn@umich.edu assert(ioEnable); 5792292SN/A 5802292SN/A Addr daddr = req->paddr & 0xfff; 5812292SN/A DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 5822292SN/A daddr, req->paddr, req->vaddr, req->size); 5832292SN/A 5842292SN/A if (daddr > LAST && daddr <= RESERVED) { 5852292SN/A panic("Accessing reserved register"); 5862292SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 5872292SN/A WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 5886221Snate@binkert.org return No_Fault; 5896221Snate@binkert.org } else if (daddr > 0x3FC) 5902292SN/A panic("Something is messed up!\n"); 5913867Sbinkertn@umich.edu 5926221Snate@binkert.org if (req->size == sizeof(uint32_t)) { 5933867Sbinkertn@umich.edu uint32_t reg = *(uint32_t *)data; 5942292SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 5952292SN/A 5962292SN/A switch (daddr) { 5972292SN/A case CR: 5982292SN/A regs.command = reg; 5992292SN/A if (reg & CR_TXD) { 6002292SN/A txEnable = false; 6012292SN/A } else if (reg & CR_TXE) { 6022292SN/A txEnable = true; 6036221Snate@binkert.org 6042292SN/A // the kernel is enabling the transmit machine 6053870Sbinkertn@umich.edu if (txState == txIdle) 6062292SN/A txKick(); 6072292SN/A } 6082292SN/A 6092292SN/A if (reg & CR_RXD) { 6102292SN/A rxEnable = false; 6112292SN/A } else if (reg & CR_RXE) { 6122292SN/A rxEnable = true; 6132292SN/A 6142292SN/A if (rxState == rxIdle) 6156221Snate@binkert.org rxKick(); 6166221Snate@binkert.org } 6172292SN/A 6183867Sbinkertn@umich.edu if (reg & CR_TXR) 6196221Snate@binkert.org txReset(); 6203867Sbinkertn@umich.edu 6215557Sktlim@umich.edu if (reg & CR_RXR) 6225557Sktlim@umich.edu rxReset(); 6232292SN/A 6242292SN/A if (reg & CR_SWI) 6255557Sktlim@umich.edu devIntrPost(ISR_SWI); 6262292SN/A 6272292SN/A if (reg & CR_RST) { 6282292SN/A txReset(); 6292292SN/A rxReset(); 6302292SN/A 6312292SN/A regsReset(); 6326221Snate@binkert.org } 6336221Snate@binkert.org break; 6342292SN/A 6353867Sbinkertn@umich.edu case CFG: 6366221Snate@binkert.org if (reg & CFG_LNKSTS || 6373867Sbinkertn@umich.edu reg & CFG_SPDSTS || 6385557Sktlim@umich.edu reg & CFG_DUPSTS || 6395557Sktlim@umich.edu reg & CFG_RESERVED || 6402292SN/A reg & CFG_T64ADDR || 6412292SN/A reg & CFG_PCI64_DET) 6425557Sktlim@umich.edu panic("writing to read-only or reserved CFG bits!\n"); 6432292SN/A 6442292SN/A regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | 6452292SN/A CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET); 6462292SN/A 6479440SAndreas.Sandberg@ARM.com// all these #if 0's are because i don't THINK the kernel needs to 6482292SN/A// have these implemented. if there is a problem relating to one of 6499440SAndreas.Sandberg@ARM.com// these, you may need to add functionality in. 6509440SAndreas.Sandberg@ARM.com#if 0 6512292SN/A if (reg & CFG_TBI_EN) ; 6523867Sbinkertn@umich.edu if (reg & CFG_MODE_1000) ; 6536221Snate@binkert.org#endif 6543867Sbinkertn@umich.edu 6552292SN/A if (reg & CFG_AUTO_1000) 6562292SN/A panic("CFG_AUTO_1000 not implemented!\n"); 6572292SN/A 658#if 0 659 if (reg & CFG_PINT_DUPSTS || 660 reg & CFG_PINT_LNKSTS || 661 reg & CFG_PINT_SPDSTS) 662 ; 663 664 if (reg & CFG_TMRTEST) ; 665 if (reg & CFG_MRM_DIS) ; 666 if (reg & CFG_MWI_DIS) ; 667 668 if (reg & CFG_T64ADDR) 669 panic("CFG_T64ADDR is read only register!\n"); 670 671 if (reg & CFG_PCI64_DET) 672 panic("CFG_PCI64_DET is read only register!\n"); 673 674 if (reg & CFG_DATA64_EN) ; 675 if (reg & CFG_M64ADDR) ; 676 if (reg & CFG_PHY_RST) ; 677 if (reg & CFG_PHY_DIS) ; 678#endif 679 680 if (reg & CFG_EXTSTS_EN) 681 extstsEnable = true; 682 else 683 extstsEnable = false; 684 685#if 0 686 if (reg & CFG_REQALG) ; 687 if (reg & CFG_SB) ; 688 if (reg & CFG_POW) ; 689 if (reg & CFG_EXD) ; 690 if (reg & CFG_PESEL) ; 691 if (reg & CFG_BROM_DIS) ; 692 if (reg & CFG_EXT_125) ; 693 if (reg & CFG_BEM) ; 694#endif 695 break; 696 697 case MEAR: 698 regs.mear = reg; 699 // since phy is completely faked, MEAR_MD* don't matter 700 // and since the driver never uses MEAR_EE*, they don't 701 // matter 702#if 0 703 if (reg & MEAR_EEDI) ; 704 if (reg & MEAR_EEDO) ; // this one is read only 705 if (reg & MEAR_EECLK) ; 706 if (reg & MEAR_EESEL) ; 707 if (reg & MEAR_MDIO) ; 708 if (reg & MEAR_MDDIR) ; 709 if (reg & MEAR_MDC) ; 710#endif 711 break; 712 713 case PTSCR: 714 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 715 // these control BISTs for various parts of chip - we 716 // don't care or do just fake that the BIST is done 717 if (reg & PTSCR_RBIST_EN) 718 regs.ptscr |= PTSCR_RBIST_DONE; 719 if (reg & PTSCR_EEBIST_EN) 720 regs.ptscr &= ~PTSCR_EEBIST_EN; 721 if (reg & PTSCR_EELOAD_EN) 722 regs.ptscr &= ~PTSCR_EELOAD_EN; 723 break; 724 725 case ISR: /* writing to the ISR has no effect */ 726 panic("ISR is a read only register!\n"); 727 728 case IMR: 729 regs.imr = reg; 730 devIntrChangeMask(); 731 break; 732 733 case IER: 734 regs.ier = reg; 735 break; 736 737 case IHR: 738 regs.ihr = reg; 739 /* not going to implement real interrupt holdoff */ 740 break; 741 742 case TXDP: 743 regs.txdp = (reg & 0xFFFFFFFC); 744 assert(txState == txIdle); 745 CTDD = false; 746 break; 747 748 case TXDP_HI: 749 regs.txdp_hi = reg; 750 break; 751 752 case TXCFG: 753 regs.txcfg = reg; 754#if 0 755 if (reg & TXCFG_CSI) ; 756 if (reg & TXCFG_HBI) ; 757 if (reg & TXCFG_MLB) ; 758 if (reg & TXCFG_ATP) ; 759 if (reg & TXCFG_ECRETRY) { 760 /* 761 * this could easily be implemented, but considering 762 * the network is just a fake pipe, wouldn't make 763 * sense to do this 764 */ 765 } 766 767 if (reg & TXCFG_BRST_DIS) ; 768#endif 769 770#if 0 771 /* we handle our own DMA, ignore the kernel's exhortations */ 772 if (reg & TXCFG_MXDMA) ; 773#endif 774 775 // also, we currently don't care about fill/drain 776 // thresholds though this may change in the future with 777 // more realistic networks or a driver which changes it 778 // according to feedback 779 780 break; 781 782 case GPIOR: 783 regs.gpior = reg; 784 /* these just control general purpose i/o pins, don't matter */ 785 break; 786 787 case RXDP: 788 regs.rxdp = reg; 789 CRDD = false; 790 break; 791 792 case RXDP_HI: 793 regs.rxdp_hi = reg; 794 break; 795 796 case RXCFG: 797 regs.rxcfg = reg; 798#if 0 799 if (reg & RXCFG_AEP) ; 800 if (reg & RXCFG_ARP) ; 801 if (reg & RXCFG_STRIPCRC) ; 802 if (reg & RXCFG_RX_RD) ; 803 if (reg & RXCFG_ALP) ; 804 if (reg & RXCFG_AIRL) ; 805 806 /* we handle our own DMA, ignore what kernel says about it */ 807 if (reg & RXCFG_MXDMA) ; 808 809 //also, we currently don't care about fill/drain thresholds 810 //though this may change in the future with more realistic 811 //networks or a driver which changes it according to feedback 812 if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 813#endif 814 break; 815 816 case PQCR: 817 /* there is no priority queueing used in the linux 2.6 driver */ 818 regs.pqcr = reg; 819 break; 820 821 case WCSR: 822 /* not going to implement wake on LAN */ 823 regs.wcsr = reg; 824 break; 825 826 case PCR: 827 /* not going to implement pause control */ 828 regs.pcr = reg; 829 break; 830 831 case RFCR: 832 regs.rfcr = reg; 833 834 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 835 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 836 acceptMulticast = (reg & RFCR_AAM) ? true : false; 837 acceptUnicast = (reg & RFCR_AAU) ? true : false; 838 acceptPerfect = (reg & RFCR_APM) ? true : false; 839 acceptArp = (reg & RFCR_AARP) ? true : false; 840 841#if 0 842 if (reg & RFCR_APAT) 843 panic("RFCR_APAT not implemented!\n"); 844#endif 845 846 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 847 panic("hash filtering not implemented!\n"); 848 849 if (reg & RFCR_ULM) 850 panic("RFCR_ULM not implemented!\n"); 851 852 break; 853 854 case RFDR: 855 panic("the driver never writes to RFDR, something is wrong!\n"); 856 857 case BRAR: 858 panic("the driver never uses BRAR, something is wrong!\n"); 859 860 case BRDR: 861 panic("the driver never uses BRDR, something is wrong!\n"); 862 863 case SRR: 864 panic("SRR is read only register!\n"); 865 866 case MIBC: 867 panic("the driver never uses MIBC, something is wrong!\n"); 868 869 case VRCR: 870 regs.vrcr = reg; 871 break; 872 873 case VTCR: 874 regs.vtcr = reg; 875 break; 876 877 case VDR: 878 panic("the driver never uses VDR, something is wrong!\n"); 879 break; 880 881 case CCSR: 882 /* not going to implement clockrun stuff */ 883 regs.ccsr = reg; 884 break; 885 886 case TBICR: 887 regs.tbicr = reg; 888 if (reg & TBICR_MR_LOOPBACK) 889 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 890 891 if (reg & TBICR_MR_AN_ENABLE) { 892 regs.tanlpar = regs.tanar; 893 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 894 } 895 896#if 0 897 if (reg & TBICR_MR_RESTART_AN) ; 898#endif 899 900 break; 901 902 case TBISR: 903 panic("TBISR is read only register!\n"); 904 905 case TANAR: 906 regs.tanar = reg; 907 if (reg & TANAR_PS2) 908 panic("this isn't used in driver, something wrong!\n"); 909 910 if (reg & TANAR_PS1) 911 panic("this isn't used in driver, something wrong!\n"); 912 break; 913 914 case TANLPAR: 915 panic("this should only be written to by the fake phy!\n"); 916 917 case TANER: 918 panic("TANER is read only register!\n"); 919 920 case TESR: 921 regs.tesr = reg; 922 break; 923 924 default: 925 panic("invalid register access daddr=%#x", daddr); 926 } 927 } else { 928 panic("Invalid Request Size"); 929 } 930 931 return No_Fault; 932} 933 934void 935NSGigE::devIntrPost(uint32_t interrupts) 936{ 937 if (interrupts & ISR_RESERVE) 938 panic("Cannot set a reserved interrupt"); 939 940 if (interrupts & ISR_NOIMPL) 941 warn("interrupt not implemented %#x\n", interrupts); 942 943 interrupts &= ~ISR_NOIMPL; 944 regs.isr |= interrupts; 945 946 DPRINTF(EthernetIntr, 947 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 948 interrupts, regs.isr, regs.imr); 949 950 if ((regs.isr & regs.imr)) { 951 Tick when = curTick; 952 if (!(regs.isr & regs.imr & ISR_NODELAY)) 953 when += intrDelay; 954 cpuIntrPost(when); 955 } 956} 957 958void 959NSGigE::devIntrClear(uint32_t interrupts) 960{ 961 if (interrupts & ISR_RESERVE) 962 panic("Cannot clear a reserved interrupt"); 963 964 interrupts &= ~ISR_NOIMPL; 965 regs.isr &= ~interrupts; 966 967 DPRINTF(EthernetIntr, 968 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 969 interrupts, regs.isr, regs.imr); 970 971 if (!(regs.isr & regs.imr)) 972 cpuIntrClear(); 973} 974 975void 976NSGigE::devIntrChangeMask() 977{ 978 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 979 regs.isr, regs.imr, regs.isr & regs.imr); 980 981 if (regs.isr & regs.imr) 982 cpuIntrPost(curTick); 983 else 984 cpuIntrClear(); 985} 986 987void 988NSGigE::cpuIntrPost(Tick when) 989{ 990 // If the interrupt you want to post is later than an interrupt 991 // already scheduled, just let it post in the coming one and don't 992 // schedule another. 993 // HOWEVER, must be sure that the scheduled intrTick is in the 994 // future (this was formerly the source of a bug) 995 /** 996 * @todo this warning should be removed and the intrTick code should 997 * be fixed. 998 */ 999 assert(when >= curTick); 1000 assert(intrTick >= curTick || intrTick == 0); 1001 if (when > intrTick && intrTick != 0) { 1002 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 1003 intrTick); 1004 return; 1005 } 1006 1007 intrTick = when; 1008 if (intrTick < curTick) { 1009 debug_break(); 1010 intrTick = curTick; 1011 } 1012 1013 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 1014 intrTick); 1015 1016 if (intrEvent) 1017 intrEvent->squash(); 1018 intrEvent = new IntrEvent(this, true); 1019 intrEvent->schedule(intrTick); 1020} 1021 1022void 1023NSGigE::cpuInterrupt() 1024{ 1025 assert(intrTick == curTick); 1026 1027 // Whether or not there's a pending interrupt, we don't care about 1028 // it anymore 1029 intrEvent = 0; 1030 intrTick = 0; 1031 1032 // Don't send an interrupt if there's already one 1033 if (cpuPendingIntr) { 1034 DPRINTF(EthernetIntr, 1035 "would send an interrupt now, but there's already pending\n"); 1036 } else { 1037 // Send interrupt 1038 cpuPendingIntr = true; 1039 1040 DPRINTF(EthernetIntr, "posting cchip interrupt\n"); 1041 tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine); 1042 } 1043} 1044 1045void 1046NSGigE::cpuIntrClear() 1047{ 1048 if (!cpuPendingIntr) 1049 return; 1050 1051 if (intrEvent) { 1052 intrEvent->squash(); 1053 intrEvent = 0; 1054 } 1055 1056 intrTick = 0; 1057 1058 cpuPendingIntr = false; 1059 1060 DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); 1061 tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); 1062} 1063 1064bool 1065NSGigE::cpuIntrPending() const 1066{ return cpuPendingIntr; } 1067 1068void 1069NSGigE::txReset() 1070{ 1071 1072 DPRINTF(Ethernet, "transmit reset\n"); 1073 1074 CTDD = false; 1075 txFifoAvail = maxTxFifoSize; 1076 txEnable = false;; 1077 txFragPtr = 0; 1078 assert(txDescCnt == 0); 1079 txFifo.clear(); 1080 txState = txIdle; 1081 assert(txDmaState == dmaIdle); 1082} 1083 1084void 1085NSGigE::rxReset() 1086{ 1087 DPRINTF(Ethernet, "receive reset\n"); 1088 1089 CRDD = false; 1090 assert(rxPktBytes == 0); 1091 rxFifoCnt = 0; 1092 rxEnable = false; 1093 rxFragPtr = 0; 1094 assert(rxDescCnt == 0); 1095 assert(rxDmaState == dmaIdle); 1096 rxFifo.clear(); 1097 rxState = rxIdle; 1098} 1099 1100void 1101NSGigE::regsReset() 1102{ 1103 memset(®s, 0, sizeof(regs)); 1104 regs.config = CFG_LNKSTS; 1105 regs.mear = MEAR_MDDIR | MEAR_EEDO; 1106 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1107 // fill threshold to 32 bytes 1108 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1109 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1110 regs.mibc = MIBC_FRZ; 1111 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1112 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1113 1114 extstsEnable = false; 1115 acceptBroadcast = false; 1116 acceptMulticast = false; 1117 acceptUnicast = false; 1118 acceptPerfect = false; 1119 acceptArp = false; 1120} 1121 1122void 1123NSGigE::rxDmaReadCopy() 1124{ 1125 assert(rxDmaState == dmaReading); 1126 1127 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1128 rxDmaState = dmaIdle; 1129 1130 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1131 rxDmaAddr, rxDmaLen); 1132 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1133} 1134 1135bool 1136NSGigE::doRxDmaRead() 1137{ 1138 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1139 rxDmaState = dmaReading; 1140 1141 if (dmaInterface && !rxDmaFree) { 1142 if (dmaInterface->busy()) 1143 rxDmaState = dmaReadWaiting; 1144 else 1145 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1146 &rxDmaReadEvent, true); 1147 return true; 1148 } 1149 1150 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1151 rxDmaReadCopy(); 1152 return false; 1153 } 1154 1155 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1156 Tick start = curTick + dmaReadDelay + factor; 1157 rxDmaReadEvent.schedule(start); 1158 return true; 1159} 1160 1161void 1162NSGigE::rxDmaReadDone() 1163{ 1164 assert(rxDmaState == dmaReading); 1165 rxDmaReadCopy(); 1166 1167 // If the transmit state machine has a pending DMA, let it go first 1168 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1169 txKick(); 1170 1171 rxKick(); 1172} 1173 1174void 1175NSGigE::rxDmaWriteCopy() 1176{ 1177 assert(rxDmaState == dmaWriting); 1178 1179 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1180 rxDmaState = dmaIdle; 1181 1182 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1183 rxDmaAddr, rxDmaLen); 1184 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1185} 1186 1187bool 1188NSGigE::doRxDmaWrite() 1189{ 1190 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1191 rxDmaState = dmaWriting; 1192 1193 if (dmaInterface && !rxDmaFree) { 1194 if (dmaInterface->busy()) 1195 rxDmaState = dmaWriteWaiting; 1196 else 1197 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1198 &rxDmaWriteEvent, true); 1199 return true; 1200 } 1201 1202 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1203 rxDmaWriteCopy(); 1204 return false; 1205 } 1206 1207 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1208 Tick start = curTick + dmaWriteDelay + factor; 1209 rxDmaWriteEvent.schedule(start); 1210 return true; 1211} 1212 1213void 1214NSGigE::rxDmaWriteDone() 1215{ 1216 assert(rxDmaState == dmaWriting); 1217 rxDmaWriteCopy(); 1218 1219 // If the transmit state machine has a pending DMA, let it go first 1220 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1221 txKick(); 1222 1223 rxKick(); 1224} 1225 1226void 1227NSGigE::rxKick() 1228{ 1229 DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", 1230 NsRxStateStrings[rxState], rxFifo.size()); 1231 1232 if (rxKickTick > curTick) { 1233 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1234 rxKickTick); 1235 return; 1236 } 1237 1238 next: 1239 switch(rxDmaState) { 1240 case dmaReadWaiting: 1241 if (doRxDmaRead()) 1242 goto exit; 1243 break; 1244 case dmaWriteWaiting: 1245 if (doRxDmaWrite()) 1246 goto exit; 1247 break; 1248 default: 1249 break; 1250 } 1251 1252 // see state machine from spec for details 1253 // the way this works is, if you finish work on one state and can 1254 // go directly to another, you do that through jumping to the 1255 // label "next". however, if you have intermediate work, like DMA 1256 // so that you can't go to the next state yet, you go to exit and 1257 // exit the loop. however, when the DMA is done it will trigger 1258 // an event and come back to this loop. 1259 switch (rxState) { 1260 case rxIdle: 1261 if (!rxEnable) { 1262 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1263 goto exit; 1264 } 1265 1266 if (CRDD) { 1267 rxState = rxDescRefr; 1268 1269 rxDmaAddr = regs.rxdp & 0x3fffffff; 1270 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1271 rxDmaLen = sizeof(rxDescCache.link); 1272 rxDmaFree = dmaDescFree; 1273 1274 descDmaReads++; 1275 descDmaRdBytes += rxDmaLen; 1276 1277 if (doRxDmaRead()) 1278 goto exit; 1279 } else { 1280 rxState = rxDescRead; 1281 1282 rxDmaAddr = regs.rxdp & 0x3fffffff; 1283 rxDmaData = &rxDescCache; 1284 rxDmaLen = sizeof(ns_desc); 1285 rxDmaFree = dmaDescFree; 1286 1287 descDmaReads++; 1288 descDmaRdBytes += rxDmaLen; 1289 1290 if (doRxDmaRead()) 1291 goto exit; 1292 } 1293 break; 1294 1295 case rxDescRefr: 1296 if (rxDmaState != dmaIdle) 1297 goto exit; 1298 1299 rxState = rxAdvance; 1300 break; 1301 1302 case rxDescRead: 1303 if (rxDmaState != dmaIdle) 1304 goto exit; 1305 1306 DPRINTF(EthernetDesc, 1307 "rxDescCache: addr=%08x read descriptor\n", 1308 regs.rxdp & 0x3fffffff); 1309 DPRINTF(EthernetDesc, 1310 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1311 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1312 rxDescCache.extsts); 1313 1314 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1315 devIntrPost(ISR_RXIDLE); 1316 rxState = rxIdle; 1317 goto exit; 1318 } else { 1319 rxState = rxFifoBlock; 1320 rxFragPtr = rxDescCache.bufptr; 1321 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1322 } 1323 break; 1324 1325 case rxFifoBlock: 1326 if (!rxPacket) { 1327 /** 1328 * @todo in reality, we should be able to start processing 1329 * the packet as it arrives, and not have to wait for the 1330 * full packet ot be in the receive fifo. 1331 */ 1332 if (rxFifo.empty()) 1333 goto exit; 1334 1335 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1336 1337 // If we don't have a packet, grab a new one from the fifo. 1338 rxPacket = rxFifo.front(); 1339 rxPktBytes = rxPacket->length; 1340 rxPacketBufPtr = rxPacket->data; 1341 1342#if TRACING_ON 1343 if (DTRACE(Ethernet)) { 1344 const IpHdr *ip = rxPacket->ip(); 1345 if (ip) { 1346 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1347 const TcpHdr *tcp = rxPacket->tcp(); 1348 if (tcp) { 1349 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 1350 tcp->sport(), tcp->dport()); 1351 } 1352 } 1353 } 1354#endif 1355 1356 // sanity check - i think the driver behaves like this 1357 assert(rxDescCnt >= rxPktBytes); 1358 1359 // Must clear the value before popping to decrement the 1360 // reference count 1361 rxFifo.front() = NULL; 1362 rxFifo.pop_front(); 1363 rxFifoCnt -= rxPacket->length; 1364 } 1365 1366 1367 // dont' need the && rxDescCnt > 0 if driver sanity check 1368 // above holds 1369 if (rxPktBytes > 0) { 1370 rxState = rxFragWrite; 1371 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1372 // check holds 1373 rxXferLen = rxPktBytes; 1374 1375 rxDmaAddr = rxFragPtr & 0x3fffffff; 1376 rxDmaData = rxPacketBufPtr; 1377 rxDmaLen = rxXferLen; 1378 rxDmaFree = dmaDataFree; 1379 1380 if (doRxDmaWrite()) 1381 goto exit; 1382 1383 } else { 1384 rxState = rxDescWrite; 1385 1386 //if (rxPktBytes == 0) { /* packet is done */ 1387 assert(rxPktBytes == 0); 1388 DPRINTF(EthernetSM, "done with receiving packet\n"); 1389 1390 rxDescCache.cmdsts |= CMDSTS_OWN; 1391 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1392 rxDescCache.cmdsts |= CMDSTS_OK; 1393 rxDescCache.cmdsts &= 0xffff0000; 1394 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1395 1396#if 0 1397 /* 1398 * all the driver uses these are for its own stats keeping 1399 * which we don't care about, aren't necessary for 1400 * functionality and doing this would just slow us down. 1401 * if they end up using this in a later version for 1402 * functional purposes, just undef 1403 */ 1404 if (rxFilterEnable) { 1405 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1406 EthHdr *eth = rxFifoFront()->eth(); 1407 if (eth->unicast()) 1408 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1409 if (eth->multicast()) 1410 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1411 if (eth->broadcast()) 1412 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1413 } 1414#endif 1415 1416 if (extstsEnable && rxPacket->ip()) { 1417 rxDescCache.extsts |= EXTSTS_IPPKT; 1418 rxIpChecksums++; 1419 IpHdr *ip = rxPacket->ip(); 1420 if (ip->ip_cksum() != 0) { 1421 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1422 rxDescCache.extsts |= EXTSTS_IPERR; 1423 } 1424 if (rxPacket->tcp()) { 1425 rxDescCache.extsts |= EXTSTS_TCPPKT; 1426 rxTcpChecksums++; 1427 if (ip->tu_cksum() != 0) { 1428 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1429 rxDescCache.extsts |= EXTSTS_TCPERR; 1430 1431 } 1432 } else if (rxPacket->udp()) { 1433 rxDescCache.extsts |= EXTSTS_UDPPKT; 1434 rxUdpChecksums++; 1435 if (ip->tu_cksum() != 0) { 1436 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1437 rxDescCache.extsts |= EXTSTS_UDPERR; 1438 } 1439 } 1440 } 1441 rxPacket = 0; 1442 1443 /* 1444 * the driver seems to always receive into desc buffers 1445 * of size 1514, so you never have a pkt that is split 1446 * into multiple descriptors on the receive side, so 1447 * i don't implement that case, hence the assert above. 1448 */ 1449 1450 DPRINTF(EthernetDesc, 1451 "rxDescCache: addr=%08x writeback cmdsts extsts\n", 1452 regs.rxdp & 0x3fffffff); 1453 DPRINTF(EthernetDesc, 1454 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1455 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1456 rxDescCache.extsts); 1457 1458 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1459 rxDmaData = &(rxDescCache.cmdsts); 1460 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1461 rxDmaFree = dmaDescFree; 1462 1463 descDmaWrites++; 1464 descDmaWrBytes += rxDmaLen; 1465 1466 if (doRxDmaWrite()) 1467 goto exit; 1468 } 1469 break; 1470 1471 case rxFragWrite: 1472 if (rxDmaState != dmaIdle) 1473 goto exit; 1474 1475 rxPacketBufPtr += rxXferLen; 1476 rxFragPtr += rxXferLen; 1477 rxPktBytes -= rxXferLen; 1478 1479 rxState = rxFifoBlock; 1480 break; 1481 1482 case rxDescWrite: 1483 if (rxDmaState != dmaIdle) 1484 goto exit; 1485 1486 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1487 1488 assert(rxPacket == 0); 1489 devIntrPost(ISR_RXOK); 1490 1491 if (rxDescCache.cmdsts & CMDSTS_INTR) 1492 devIntrPost(ISR_RXDESC); 1493 1494 if (!rxEnable) { 1495 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1496 rxState = rxIdle; 1497 goto exit; 1498 } else 1499 rxState = rxAdvance; 1500 break; 1501 1502 case rxAdvance: 1503 if (rxDescCache.link == 0) { 1504 devIntrPost(ISR_RXIDLE); 1505 rxState = rxIdle; 1506 CRDD = true; 1507 goto exit; 1508 } else { 1509 rxState = rxDescRead; 1510 regs.rxdp = rxDescCache.link; 1511 CRDD = false; 1512 1513 rxDmaAddr = regs.rxdp & 0x3fffffff; 1514 rxDmaData = &rxDescCache; 1515 rxDmaLen = sizeof(ns_desc); 1516 rxDmaFree = dmaDescFree; 1517 1518 if (doRxDmaRead()) 1519 goto exit; 1520 } 1521 break; 1522 1523 default: 1524 panic("Invalid rxState!"); 1525 } 1526 1527 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1528 NsRxStateStrings[rxState]); 1529 1530 goto next; 1531 1532 exit: 1533 /** 1534 * @todo do we want to schedule a future kick? 1535 */ 1536 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1537 NsRxStateStrings[rxState]); 1538} 1539 1540void 1541NSGigE::transmit() 1542{ 1543 if (txFifo.empty()) { 1544 DPRINTF(Ethernet, "nothing to transmit\n"); 1545 return; 1546 } 1547 1548 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1549 maxTxFifoSize - txFifoAvail); 1550 if (interface->sendPacket(txFifo.front())) { 1551#if TRACING_ON 1552 if (DTRACE(Ethernet)) { 1553 const IpHdr *ip = txFifo.front()->ip(); 1554 if (ip) { 1555 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1556 const TcpHdr *tcp = txFifo.front()->tcp(); 1557 if (tcp) { 1558 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 1559 tcp->sport(), tcp->dport()); 1560 } 1561 } 1562 } 1563#endif 1564 1565 DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length); 1566 txBytes += txFifo.front()->length; 1567 txPackets++; 1568 1569 txFifoAvail += txFifo.front()->length; 1570 1571 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1572 txFifoAvail); 1573 txFifo.front() = NULL; 1574 txFifo.pop_front(); 1575 1576 /* 1577 * normally do a writeback of the descriptor here, and ONLY 1578 * after that is done, send this interrupt. but since our 1579 * stuff never actually fails, just do this interrupt here, 1580 * otherwise the code has to stray from this nice format. 1581 * besides, it's functionally the same. 1582 */ 1583 devIntrPost(ISR_TXOK); 1584 } else { 1585 DPRINTF(Ethernet, 1586 "May need to rethink always sending the descriptors back?\n"); 1587 } 1588 1589 if (!txFifo.empty() && !txEvent.scheduled()) { 1590 DPRINTF(Ethernet, "reschedule transmit\n"); 1591 txEvent.schedule(curTick + 1000); 1592 } 1593} 1594 1595void 1596NSGigE::txDmaReadCopy() 1597{ 1598 assert(txDmaState == dmaReading); 1599 1600 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1601 txDmaState = dmaIdle; 1602 1603 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1604 txDmaAddr, txDmaLen); 1605 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1606} 1607 1608bool 1609NSGigE::doTxDmaRead() 1610{ 1611 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1612 txDmaState = dmaReading; 1613 1614 if (dmaInterface && !txDmaFree) { 1615 if (dmaInterface->busy()) 1616 txDmaState = dmaReadWaiting; 1617 else 1618 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1619 &txDmaReadEvent, true); 1620 return true; 1621 } 1622 1623 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1624 txDmaReadCopy(); 1625 return false; 1626 } 1627 1628 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1629 Tick start = curTick + dmaReadDelay + factor; 1630 txDmaReadEvent.schedule(start); 1631 return true; 1632} 1633 1634void 1635NSGigE::txDmaReadDone() 1636{ 1637 assert(txDmaState == dmaReading); 1638 txDmaReadCopy(); 1639 1640 // If the receive state machine has a pending DMA, let it go first 1641 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1642 rxKick(); 1643 1644 txKick(); 1645} 1646 1647void 1648NSGigE::txDmaWriteCopy() 1649{ 1650 assert(txDmaState == dmaWriting); 1651 1652 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1653 txDmaState = dmaIdle; 1654 1655 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1656 txDmaAddr, txDmaLen); 1657 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1658} 1659 1660bool 1661NSGigE::doTxDmaWrite() 1662{ 1663 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1664 txDmaState = dmaWriting; 1665 1666 if (dmaInterface && !txDmaFree) { 1667 if (dmaInterface->busy()) 1668 txDmaState = dmaWriteWaiting; 1669 else 1670 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1671 &txDmaWriteEvent, true); 1672 return true; 1673 } 1674 1675 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1676 txDmaWriteCopy(); 1677 return false; 1678 } 1679 1680 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1681 Tick start = curTick + dmaWriteDelay + factor; 1682 txDmaWriteEvent.schedule(start); 1683 return true; 1684} 1685 1686void 1687NSGigE::txDmaWriteDone() 1688{ 1689 assert(txDmaState == dmaWriting); 1690 txDmaWriteCopy(); 1691 1692 // If the receive state machine has a pending DMA, let it go first 1693 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1694 rxKick(); 1695 1696 txKick(); 1697} 1698 1699void 1700NSGigE::txKick() 1701{ 1702 DPRINTF(EthernetSM, "transmit kick txState=%s\n", 1703 NsTxStateStrings[txState]); 1704 1705 if (txKickTick > curTick) { 1706 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1707 txKickTick); 1708 1709 return; 1710 } 1711 1712 next: 1713 switch(txDmaState) { 1714 case dmaReadWaiting: 1715 if (doTxDmaRead()) 1716 goto exit; 1717 break; 1718 case dmaWriteWaiting: 1719 if (doTxDmaWrite()) 1720 goto exit; 1721 break; 1722 default: 1723 break; 1724 } 1725 1726 switch (txState) { 1727 case txIdle: 1728 if (!txEnable) { 1729 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1730 goto exit; 1731 } 1732 1733 if (CTDD) { 1734 txState = txDescRefr; 1735 1736 txDmaAddr = regs.txdp & 0x3fffffff; 1737 txDmaData = &txDescCache + offsetof(ns_desc, link); 1738 txDmaLen = sizeof(txDescCache.link); 1739 txDmaFree = dmaDescFree; 1740 1741 descDmaReads++; 1742 descDmaRdBytes += txDmaLen; 1743 1744 if (doTxDmaRead()) 1745 goto exit; 1746 1747 } else { 1748 txState = txDescRead; 1749 1750 txDmaAddr = regs.txdp & 0x3fffffff; 1751 txDmaData = &txDescCache; 1752 txDmaLen = sizeof(ns_desc); 1753 txDmaFree = dmaDescFree; 1754 1755 descDmaReads++; 1756 descDmaRdBytes += txDmaLen; 1757 1758 if (doTxDmaRead()) 1759 goto exit; 1760 } 1761 break; 1762 1763 case txDescRefr: 1764 if (txDmaState != dmaIdle) 1765 goto exit; 1766 1767 txState = txAdvance; 1768 break; 1769 1770 case txDescRead: 1771 if (txDmaState != dmaIdle) 1772 goto exit; 1773 1774 DPRINTF(EthernetDesc, 1775 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1776 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 1777 txDescCache.extsts); 1778 1779 if (txDescCache.cmdsts & CMDSTS_OWN) { 1780 txState = txFifoBlock; 1781 txFragPtr = txDescCache.bufptr; 1782 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1783 } else { 1784 devIntrPost(ISR_TXIDLE); 1785 txState = txIdle; 1786 goto exit; 1787 } 1788 break; 1789 1790 case txFifoBlock: 1791 if (!txPacket) { 1792 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 1793 txPacket = new PacketData; 1794 txPacket->data = new uint8_t[16384]; 1795 txPacketBufPtr = txPacket->data; 1796 } 1797 1798 if (txDescCnt == 0) { 1799 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 1800 if (txDescCache.cmdsts & CMDSTS_MORE) { 1801 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1802 txState = txDescWrite; 1803 1804 txDescCache.cmdsts &= ~CMDSTS_OWN; 1805 1806 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1807 txDmaAddr &= 0x3fffffff; 1808 txDmaData = &(txDescCache.cmdsts); 1809 txDmaLen = sizeof(txDescCache.cmdsts); 1810 txDmaFree = dmaDescFree; 1811 1812 if (doTxDmaWrite()) 1813 goto exit; 1814 1815 } else { /* this packet is totally done */ 1816 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1817 /* deal with the the packet that just finished */ 1818 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 1819 IpHdr *ip = txPacket->ip(); 1820 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1821 UdpHdr *udp = txPacket->udp(); 1822 udp->sum(0); 1823 udp->sum(ip->tu_cksum()); 1824 txUdpChecksums++; 1825 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1826 TcpHdr *tcp = txPacket->tcp(); 1827 tcp->sum(0); 1828 tcp->sum(ip->tu_cksum()); 1829 txTcpChecksums++; 1830 } 1831 if (txDescCache.extsts & EXTSTS_IPPKT) { 1832 ip->sum(0); 1833 ip->sum(ip->ip_cksum()); 1834 txIpChecksums++; 1835 } 1836 } 1837 1838 txPacket->length = txPacketBufPtr - txPacket->data; 1839 // this is just because the receive can't handle a 1840 // packet bigger want to make sure 1841 assert(txPacket->length <= 1514); 1842 txFifo.push_back(txPacket); 1843 1844 /* 1845 * this following section is not tqo spec, but 1846 * functionally shouldn't be any different. normally, 1847 * the chip will wait til the transmit has occurred 1848 * before writing back the descriptor because it has 1849 * to wait to see that it was successfully transmitted 1850 * to decide whether to set CMDSTS_OK or not. 1851 * however, in the simulator since it is always 1852 * successfully transmitted, and writing it exactly to 1853 * spec would complicate the code, we just do it here 1854 */ 1855 1856 txDescCache.cmdsts &= ~CMDSTS_OWN; 1857 txDescCache.cmdsts |= CMDSTS_OK; 1858 1859 DPRINTF(EthernetDesc, 1860 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 1861 txDescCache.cmdsts, txDescCache.extsts); 1862 1863 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1864 txDmaAddr &= 0x3fffffff; 1865 txDmaData = &(txDescCache.cmdsts); 1866 txDmaLen = sizeof(txDescCache.cmdsts) + 1867 sizeof(txDescCache.extsts); 1868 txDmaFree = dmaDescFree; 1869 1870 descDmaWrites++; 1871 descDmaWrBytes += txDmaLen; 1872 1873 transmit(); 1874 txPacket = 0; 1875 1876 if (!txEnable) { 1877 DPRINTF(EthernetSM, "halting TX state machine\n"); 1878 txState = txIdle; 1879 goto exit; 1880 } else 1881 txState = txAdvance; 1882 1883 if (doTxDmaWrite()) 1884 goto exit; 1885 } 1886 } else { 1887 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 1888 if (txFifoAvail) { 1889 txState = txFragRead; 1890 1891 /* 1892 * The number of bytes transferred is either whatever 1893 * is left in the descriptor (txDescCnt), or if there 1894 * is not enough room in the fifo, just whatever room 1895 * is left in the fifo 1896 */ 1897 txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); 1898 1899 txDmaAddr = txFragPtr & 0x3fffffff; 1900 txDmaData = txPacketBufPtr; 1901 txDmaLen = txXferLen; 1902 txDmaFree = dmaDataFree; 1903 1904 if (doTxDmaRead()) 1905 goto exit; 1906 } else { 1907 txState = txFifoBlock; 1908 transmit(); 1909 1910 goto exit; 1911 } 1912 1913 } 1914 break; 1915 1916 case txFragRead: 1917 if (txDmaState != dmaIdle) 1918 goto exit; 1919 1920 txPacketBufPtr += txXferLen; 1921 txFragPtr += txXferLen; 1922 txDescCnt -= txXferLen; 1923 txFifoAvail -= txXferLen; 1924 1925 txState = txFifoBlock; 1926 break; 1927 1928 case txDescWrite: 1929 if (txDmaState != dmaIdle) 1930 goto exit; 1931 1932 if (txDescCache.cmdsts & CMDSTS_INTR) 1933 devIntrPost(ISR_TXDESC); 1934 1935 txState = txAdvance; 1936 break; 1937 1938 case txAdvance: 1939 if (txDescCache.link == 0) { 1940 devIntrPost(ISR_TXIDLE); 1941 txState = txIdle; 1942 goto exit; 1943 } else { 1944 txState = txDescRead; 1945 regs.txdp = txDescCache.link; 1946 CTDD = false; 1947 1948 txDmaAddr = txDescCache.link & 0x3fffffff; 1949 txDmaData = &txDescCache; 1950 txDmaLen = sizeof(ns_desc); 1951 txDmaFree = dmaDescFree; 1952 1953 if (doTxDmaRead()) 1954 goto exit; 1955 } 1956 break; 1957 1958 default: 1959 panic("invalid state"); 1960 } 1961 1962 DPRINTF(EthernetSM, "entering next txState=%s\n", 1963 NsTxStateStrings[txState]); 1964 1965 goto next; 1966 1967 exit: 1968 /** 1969 * @todo do we want to schedule a future kick? 1970 */ 1971 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1972 NsTxStateStrings[txState]); 1973} 1974 1975void 1976NSGigE::transferDone() 1977{ 1978 if (txFifo.empty()) { 1979 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1980 return; 1981 } 1982 1983 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1984 1985 if (txEvent.scheduled()) 1986 txEvent.reschedule(curTick + 1); 1987 else 1988 txEvent.schedule(curTick + 1); 1989} 1990 1991bool 1992NSGigE::rxFilter(PacketPtr packet) 1993{ 1994 bool drop = true; 1995 string type; 1996 1997 EthHdr *eth = packet->eth(); 1998 if (eth->unicast()) { 1999 // If we're accepting all unicast addresses 2000 if (acceptUnicast) 2001 drop = false; 2002 2003 // If we make a perfect match 2004 if (acceptPerfect && 2005 memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) 2006 drop = false; 2007 2008 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2009 drop = false; 2010 2011 } else if (eth->broadcast()) { 2012 // if we're accepting broadcasts 2013 if (acceptBroadcast) 2014 drop = false; 2015 2016 } else if (eth->multicast()) { 2017 // if we're accepting all multicasts 2018 if (acceptMulticast) 2019 drop = false; 2020 2021 } 2022 2023 if (drop) { 2024 DPRINTF(Ethernet, "rxFilter drop\n"); 2025 DDUMP(EthernetData, packet->data, packet->length); 2026 } 2027 2028 return drop; 2029} 2030 2031bool 2032NSGigE::recvPacket(PacketPtr packet) 2033{ 2034 rxBytes += packet->length; 2035 rxPackets++; 2036 2037 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2038 maxRxFifoSize - rxFifoCnt); 2039 2040 if (!rxEnable) { 2041 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2042 debug_break(); 2043 interface->recvDone(); 2044 return true; 2045 } 2046 2047 if (rxFilterEnable && rxFilter(packet)) { 2048 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2049 interface->recvDone(); 2050 return true; 2051 } 2052 2053 if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { 2054 DPRINTF(Ethernet, 2055 "packet will not fit in receive buffer...packet dropped\n"); 2056 devIntrPost(ISR_RXORN); 2057 return false; 2058 } 2059 2060 rxFifo.push_back(packet); 2061 rxFifoCnt += packet->length; 2062 interface->recvDone(); 2063 2064 rxKick(); 2065 return true; 2066} 2067 2068//===================================================================== 2069// 2070// 2071void 2072NSGigE::serialize(ostream &os) 2073{ 2074 // Serialize the PciDev base class 2075 PciDev::serialize(os); 2076 2077 /* 2078 * Finalize any DMA events now. 2079 */ 2080 if (rxDmaReadEvent.scheduled()) 2081 rxDmaReadCopy(); 2082 if (rxDmaWriteEvent.scheduled()) 2083 rxDmaWriteCopy(); 2084 if (txDmaReadEvent.scheduled()) 2085 txDmaReadCopy(); 2086 if (txDmaWriteEvent.scheduled()) 2087 txDmaWriteCopy(); 2088 2089 /* 2090 * Serialize the device registers 2091 */ 2092 SERIALIZE_SCALAR(regs.command); 2093 SERIALIZE_SCALAR(regs.config); 2094 SERIALIZE_SCALAR(regs.mear); 2095 SERIALIZE_SCALAR(regs.ptscr); 2096 SERIALIZE_SCALAR(regs.isr); 2097 SERIALIZE_SCALAR(regs.imr); 2098 SERIALIZE_SCALAR(regs.ier); 2099 SERIALIZE_SCALAR(regs.ihr); 2100 SERIALIZE_SCALAR(regs.txdp); 2101 SERIALIZE_SCALAR(regs.txdp_hi); 2102 SERIALIZE_SCALAR(regs.txcfg); 2103 SERIALIZE_SCALAR(regs.gpior); 2104 SERIALIZE_SCALAR(regs.rxdp); 2105 SERIALIZE_SCALAR(regs.rxdp_hi); 2106 SERIALIZE_SCALAR(regs.rxcfg); 2107 SERIALIZE_SCALAR(regs.pqcr); 2108 SERIALIZE_SCALAR(regs.wcsr); 2109 SERIALIZE_SCALAR(regs.pcr); 2110 SERIALIZE_SCALAR(regs.rfcr); 2111 SERIALIZE_SCALAR(regs.rfdr); 2112 SERIALIZE_SCALAR(regs.srr); 2113 SERIALIZE_SCALAR(regs.mibc); 2114 SERIALIZE_SCALAR(regs.vrcr); 2115 SERIALIZE_SCALAR(regs.vtcr); 2116 SERIALIZE_SCALAR(regs.vdr); 2117 SERIALIZE_SCALAR(regs.ccsr); 2118 SERIALIZE_SCALAR(regs.tbicr); 2119 SERIALIZE_SCALAR(regs.tbisr); 2120 SERIALIZE_SCALAR(regs.tanar); 2121 SERIALIZE_SCALAR(regs.tanlpar); 2122 SERIALIZE_SCALAR(regs.taner); 2123 SERIALIZE_SCALAR(regs.tesr); 2124 2125 SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2126 2127 SERIALIZE_SCALAR(ioEnable); 2128 2129 /* 2130 * Serialize the data Fifos 2131 */ 2132 int txNumPkts = txFifo.size(); 2133 SERIALIZE_SCALAR(txNumPkts); 2134 int i = 0; 2135 pktiter_t end = txFifo.end(); 2136 for (pktiter_t p = txFifo.begin(); p != end; ++p) { 2137 nameOut(os, csprintf("%s.txFifo%d", name(), i++)); 2138 (*p)->serialize(os); 2139 } 2140 2141 int rxNumPkts = rxFifo.size(); 2142 SERIALIZE_SCALAR(rxNumPkts); 2143 i = 0; 2144 end = rxFifo.end(); 2145 for (pktiter_t p = rxFifo.begin(); p != end; ++p) { 2146 nameOut(os, csprintf("%s.rxFifo%d", name(), i++)); 2147 (*p)->serialize(os); 2148 } 2149 2150 /* 2151 * Serialize the various helper variables 2152 */ 2153 bool txPacketExists = txPacket; 2154 SERIALIZE_SCALAR(txPacketExists); 2155 if (txPacketExists) { 2156 nameOut(os, csprintf("%s.txPacket", name())); 2157 txPacket->serialize(os); 2158 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2159 SERIALIZE_SCALAR(txPktBufPtr); 2160 } 2161 2162 bool rxPacketExists = rxPacket; 2163 SERIALIZE_SCALAR(rxPacketExists); 2164 if (rxPacketExists) { 2165 nameOut(os, csprintf("%s.rxPacket", name())); 2166 rxPacket->serialize(os); 2167 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2168 SERIALIZE_SCALAR(rxPktBufPtr); 2169 } 2170 2171 SERIALIZE_SCALAR(txXferLen); 2172 SERIALIZE_SCALAR(rxXferLen); 2173 2174 /* 2175 * Serialize DescCaches 2176 */ 2177 SERIALIZE_SCALAR(txDescCache.link); 2178 SERIALIZE_SCALAR(txDescCache.bufptr); 2179 SERIALIZE_SCALAR(txDescCache.cmdsts); 2180 SERIALIZE_SCALAR(txDescCache.extsts); 2181 SERIALIZE_SCALAR(rxDescCache.link); 2182 SERIALIZE_SCALAR(rxDescCache.bufptr); 2183 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2184 SERIALIZE_SCALAR(rxDescCache.extsts); 2185 2186 /* 2187 * Serialize tx state machine 2188 */ 2189 int txState = this->txState; 2190 SERIALIZE_SCALAR(txState); 2191 SERIALIZE_SCALAR(txEnable); 2192 SERIALIZE_SCALAR(CTDD); 2193 SERIALIZE_SCALAR(txFifoAvail); 2194 SERIALIZE_SCALAR(txFragPtr); 2195 SERIALIZE_SCALAR(txDescCnt); 2196 int txDmaState = this->txDmaState; 2197 SERIALIZE_SCALAR(txDmaState); 2198 2199 /* 2200 * Serialize rx state machine 2201 */ 2202 int rxState = this->rxState; 2203 SERIALIZE_SCALAR(rxState); 2204 SERIALIZE_SCALAR(rxEnable); 2205 SERIALIZE_SCALAR(CRDD); 2206 SERIALIZE_SCALAR(rxPktBytes); 2207 SERIALIZE_SCALAR(rxFifoCnt); 2208 SERIALIZE_SCALAR(rxDescCnt); 2209 int rxDmaState = this->rxDmaState; 2210 SERIALIZE_SCALAR(rxDmaState); 2211 2212 SERIALIZE_SCALAR(extstsEnable); 2213 2214 /* 2215 * If there's a pending transmit, store the time so we can 2216 * reschedule it later 2217 */ 2218 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2219 SERIALIZE_SCALAR(transmitTick); 2220 2221 /* 2222 * receive address filter settings 2223 */ 2224 SERIALIZE_SCALAR(rxFilterEnable); 2225 SERIALIZE_SCALAR(acceptBroadcast); 2226 SERIALIZE_SCALAR(acceptMulticast); 2227 SERIALIZE_SCALAR(acceptUnicast); 2228 SERIALIZE_SCALAR(acceptPerfect); 2229 SERIALIZE_SCALAR(acceptArp); 2230 2231 /* 2232 * Keep track of pending interrupt status. 2233 */ 2234 SERIALIZE_SCALAR(intrTick); 2235 SERIALIZE_SCALAR(cpuPendingIntr); 2236 Tick intrEventTick = 0; 2237 if (intrEvent) 2238 intrEventTick = intrEvent->when(); 2239 SERIALIZE_SCALAR(intrEventTick); 2240 2241} 2242 2243void 2244NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2245{ 2246 // Unserialize the PciDev base class 2247 PciDev::unserialize(cp, section); 2248 2249 UNSERIALIZE_SCALAR(regs.command); 2250 UNSERIALIZE_SCALAR(regs.config); 2251 UNSERIALIZE_SCALAR(regs.mear); 2252 UNSERIALIZE_SCALAR(regs.ptscr); 2253 UNSERIALIZE_SCALAR(regs.isr); 2254 UNSERIALIZE_SCALAR(regs.imr); 2255 UNSERIALIZE_SCALAR(regs.ier); 2256 UNSERIALIZE_SCALAR(regs.ihr); 2257 UNSERIALIZE_SCALAR(regs.txdp); 2258 UNSERIALIZE_SCALAR(regs.txdp_hi); 2259 UNSERIALIZE_SCALAR(regs.txcfg); 2260 UNSERIALIZE_SCALAR(regs.gpior); 2261 UNSERIALIZE_SCALAR(regs.rxdp); 2262 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2263 UNSERIALIZE_SCALAR(regs.rxcfg); 2264 UNSERIALIZE_SCALAR(regs.pqcr); 2265 UNSERIALIZE_SCALAR(regs.wcsr); 2266 UNSERIALIZE_SCALAR(regs.pcr); 2267 UNSERIALIZE_SCALAR(regs.rfcr); 2268 UNSERIALIZE_SCALAR(regs.rfdr); 2269 UNSERIALIZE_SCALAR(regs.srr); 2270 UNSERIALIZE_SCALAR(regs.mibc); 2271 UNSERIALIZE_SCALAR(regs.vrcr); 2272 UNSERIALIZE_SCALAR(regs.vtcr); 2273 UNSERIALIZE_SCALAR(regs.vdr); 2274 UNSERIALIZE_SCALAR(regs.ccsr); 2275 UNSERIALIZE_SCALAR(regs.tbicr); 2276 UNSERIALIZE_SCALAR(regs.tbisr); 2277 UNSERIALIZE_SCALAR(regs.tanar); 2278 UNSERIALIZE_SCALAR(regs.tanlpar); 2279 UNSERIALIZE_SCALAR(regs.taner); 2280 UNSERIALIZE_SCALAR(regs.tesr); 2281 2282 UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2283 2284 UNSERIALIZE_SCALAR(ioEnable); 2285 2286 /* 2287 * unserialize the data fifos 2288 */ 2289 int txNumPkts; 2290 UNSERIALIZE_SCALAR(txNumPkts); 2291 int i; 2292 for (i = 0; i < txNumPkts; ++i) { 2293 PacketPtr p = new PacketData; 2294 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2295 txFifo.push_back(p); 2296 } 2297 2298 int rxNumPkts; 2299 UNSERIALIZE_SCALAR(rxNumPkts); 2300 for (i = 0; i < rxNumPkts; ++i) { 2301 PacketPtr p = new PacketData; 2302 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2303 rxFifo.push_back(p); 2304 } 2305 2306 /* 2307 * unserialize the various helper variables 2308 */ 2309 bool txPacketExists; 2310 UNSERIALIZE_SCALAR(txPacketExists); 2311 if (txPacketExists) { 2312 txPacket = new PacketData; 2313 txPacket->unserialize(cp, csprintf("%s.txPacket", section)); 2314 uint32_t txPktBufPtr; 2315 UNSERIALIZE_SCALAR(txPktBufPtr); 2316 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2317 } else 2318 txPacket = 0; 2319 2320 bool rxPacketExists; 2321 UNSERIALIZE_SCALAR(rxPacketExists); 2322 rxPacket = 0; 2323 if (rxPacketExists) { 2324 rxPacket = new PacketData; 2325 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 2326 uint32_t rxPktBufPtr; 2327 UNSERIALIZE_SCALAR(rxPktBufPtr); 2328 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2329 } else 2330 rxPacket = 0; 2331 2332 UNSERIALIZE_SCALAR(txXferLen); 2333 UNSERIALIZE_SCALAR(rxXferLen); 2334 2335 /* 2336 * Unserialize DescCaches 2337 */ 2338 UNSERIALIZE_SCALAR(txDescCache.link); 2339 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2340 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2341 UNSERIALIZE_SCALAR(txDescCache.extsts); 2342 UNSERIALIZE_SCALAR(rxDescCache.link); 2343 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2344 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2345 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2346 2347 /* 2348 * unserialize tx state machine 2349 */ 2350 int txState; 2351 UNSERIALIZE_SCALAR(txState); 2352 this->txState = (TxState) txState; 2353 UNSERIALIZE_SCALAR(txEnable); 2354 UNSERIALIZE_SCALAR(CTDD); 2355 UNSERIALIZE_SCALAR(txFifoAvail); 2356 UNSERIALIZE_SCALAR(txFragPtr); 2357 UNSERIALIZE_SCALAR(txDescCnt); 2358 int txDmaState; 2359 UNSERIALIZE_SCALAR(txDmaState); 2360 this->txDmaState = (DmaState) txDmaState; 2361 2362 /* 2363 * unserialize rx state machine 2364 */ 2365 int rxState; 2366 UNSERIALIZE_SCALAR(rxState); 2367 this->rxState = (RxState) rxState; 2368 UNSERIALIZE_SCALAR(rxEnable); 2369 UNSERIALIZE_SCALAR(CRDD); 2370 UNSERIALIZE_SCALAR(rxPktBytes); 2371 UNSERIALIZE_SCALAR(rxFifoCnt); 2372 UNSERIALIZE_SCALAR(rxDescCnt); 2373 int rxDmaState; 2374 UNSERIALIZE_SCALAR(rxDmaState); 2375 this->rxDmaState = (DmaState) rxDmaState; 2376 2377 UNSERIALIZE_SCALAR(extstsEnable); 2378 2379 /* 2380 * If there's a pending transmit, reschedule it now 2381 */ 2382 Tick transmitTick; 2383 UNSERIALIZE_SCALAR(transmitTick); 2384 if (transmitTick) 2385 txEvent.schedule(curTick + transmitTick); 2386 2387 /* 2388 * unserialize receive address filter settings 2389 */ 2390 UNSERIALIZE_SCALAR(rxFilterEnable); 2391 UNSERIALIZE_SCALAR(acceptBroadcast); 2392 UNSERIALIZE_SCALAR(acceptMulticast); 2393 UNSERIALIZE_SCALAR(acceptUnicast); 2394 UNSERIALIZE_SCALAR(acceptPerfect); 2395 UNSERIALIZE_SCALAR(acceptArp); 2396 2397 /* 2398 * Keep track of pending interrupt status. 2399 */ 2400 UNSERIALIZE_SCALAR(intrTick); 2401 UNSERIALIZE_SCALAR(cpuPendingIntr); 2402 Tick intrEventTick; 2403 UNSERIALIZE_SCALAR(intrEventTick); 2404 if (intrEventTick) { 2405 intrEvent = new IntrEvent(this, true); 2406 intrEvent->schedule(intrEventTick); 2407 } 2408 2409 /* 2410 * re-add addrRanges to bus bridges 2411 */ 2412 if (pioInterface) { 2413 pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1); 2414 pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1); 2415 } 2416} 2417 2418Tick 2419NSGigE::cacheAccess(MemReqPtr &req) 2420{ 2421 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2422 req->paddr, req->paddr - addr); 2423 return curTick + pioLatency; 2424} 2425 2426BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2427 2428 SimObjectParam<EtherInt *> peer; 2429 SimObjectParam<NSGigE *> device; 2430 2431END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2432 2433BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2434 2435 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2436 INIT_PARAM(device, "Ethernet device of this interface") 2437 2438END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2439 2440CREATE_SIM_OBJECT(NSGigEInt) 2441{ 2442 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2443 2444 EtherInt *p = (EtherInt *)peer; 2445 if (p) { 2446 dev_int->setPeer(p); 2447 p->setPeer(dev_int); 2448 } 2449 2450 return dev_int; 2451} 2452 2453REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2454 2455 2456BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2457 2458 Param<Tick> tx_delay; 2459 Param<Tick> rx_delay; 2460 SimObjectParam<IntrControl *> intr_ctrl; 2461 Param<Tick> intr_delay; 2462 SimObjectParam<MemoryController *> mmu; 2463 SimObjectParam<PhysicalMemory *> physmem; 2464 Param<bool> rx_filter; 2465 Param<string> hardware_address; 2466 SimObjectParam<Bus*> header_bus; 2467 SimObjectParam<Bus*> payload_bus; 2468 SimObjectParam<HierParams *> hier; 2469 Param<Tick> pio_latency; 2470 Param<bool> dma_desc_free; 2471 Param<bool> dma_data_free; 2472 Param<Tick> dma_read_delay; 2473 Param<Tick> dma_write_delay; 2474 Param<Tick> dma_read_factor; 2475 Param<Tick> dma_write_factor; 2476 SimObjectParam<PciConfigAll *> configspace; 2477 SimObjectParam<PciConfigData *> configdata; 2478 SimObjectParam<Tsunami *> tsunami; 2479 Param<uint32_t> pci_bus; 2480 Param<uint32_t> pci_dev; 2481 Param<uint32_t> pci_func; 2482 Param<uint32_t> tx_fifo_size; 2483 Param<uint32_t> rx_fifo_size; 2484 2485END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2486 2487BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2488 2489 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 2490 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 2491 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 2492 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), 2493 INIT_PARAM(mmu, "Memory Controller"), 2494 INIT_PARAM(physmem, "Physical Memory"), 2495 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2496 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2497 "00:99:00:00:00:01"), 2498 INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), 2499 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2500 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2501 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2502 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2503 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2504 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2505 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2506 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2507 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2508 INIT_PARAM(configspace, "PCI Configspace"), 2509 INIT_PARAM(configdata, "PCI Config data"), 2510 INIT_PARAM(tsunami, "Tsunami"), 2511 INIT_PARAM(pci_bus, "PCI bus"), 2512 INIT_PARAM(pci_dev, "PCI device number"), 2513 INIT_PARAM(pci_func, "PCI function code"), 2514 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2515 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072) 2516 2517END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2518 2519 2520CREATE_SIM_OBJECT(NSGigE) 2521{ 2522 int eaddr[6]; 2523 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 2524 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 2525 2526 return new NSGigE(getInstanceName(), intr_ctrl, intr_delay, 2527 physmem, tx_delay, rx_delay, mmu, hier, header_bus, 2528 payload_bus, pio_latency, dma_desc_free, dma_data_free, 2529 dma_read_delay, dma_write_delay, dma_read_factor, 2530 dma_write_factor, configspace, configdata, 2531 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 2532 tx_fifo_size, rx_fifo_size); 2533} 2534 2535REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2536