ns_gige.cc revision 1801
16019Shines@cs.fsu.edu/* 26019Shines@cs.fsu.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 37178Sgblack@eecs.umich.edu * All rights reserved. 47178Sgblack@eecs.umich.edu * 57178Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67178Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77178Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97178Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117178Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127178Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137178Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147178Sgblack@eecs.umich.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu */ 286019Shines@cs.fsu.edu 296019Shines@cs.fsu.edu/** @file 306019Shines@cs.fsu.edu * Device module for modelling the National Semiconductor 316019Shines@cs.fsu.edu * DP83820 ethernet controller. Does not support priority queueing 326019Shines@cs.fsu.edu */ 336019Shines@cs.fsu.edu#include <cstdio> 346019Shines@cs.fsu.edu#include <deque> 356019Shines@cs.fsu.edu#include <string> 366019Shines@cs.fsu.edu 376019Shines@cs.fsu.edu#include "base/inet.hh" 386019Shines@cs.fsu.edu#include "cpu/exec_context.hh" 396019Shines@cs.fsu.edu#include "dev/etherlink.hh" 406019Shines@cs.fsu.edu#include "dev/ns_gige.hh" 416019Shines@cs.fsu.edu#include "dev/pciconfigall.hh" 426019Shines@cs.fsu.edu#include "mem/bus/bus.hh" 436019Shines@cs.fsu.edu#include "mem/bus/dma_interface.hh" 446019Shines@cs.fsu.edu#include "mem/bus/pio_interface.hh" 456019Shines@cs.fsu.edu#include "mem/bus/pio_interface_impl.hh" 466019Shines@cs.fsu.edu#include "mem/functional/memory_control.hh" 476019Shines@cs.fsu.edu#include "mem/functional/physical.hh" 486019Shines@cs.fsu.edu#include "sim/builder.hh" 496019Shines@cs.fsu.edu#include "sim/debug.hh" 506019Shines@cs.fsu.edu#include "sim/host.hh" 516019Shines@cs.fsu.edu#include "sim/stats.hh" 526019Shines@cs.fsu.edu#include "targetarch/vtophys.hh" 536019Shines@cs.fsu.edu 546019Shines@cs.fsu.educonst char *NsRxStateStrings[] = 556019Shines@cs.fsu.edu{ 566019Shines@cs.fsu.edu "rxIdle", 576019Shines@cs.fsu.edu "rxDescRefr", 586243Sgblack@eecs.umich.edu "rxDescRead", 596243Sgblack@eecs.umich.edu "rxFifoBlock", 606243Sgblack@eecs.umich.edu "rxFragWrite", 616243Sgblack@eecs.umich.edu "rxDescWrite", 626243Sgblack@eecs.umich.edu "rxAdvance" 636019Shines@cs.fsu.edu}; 646019Shines@cs.fsu.edu 656019Shines@cs.fsu.educonst char *NsTxStateStrings[] = 666019Shines@cs.fsu.edu{ 676019Shines@cs.fsu.edu "txIdle", 686019Shines@cs.fsu.edu "txDescRefr", 696019Shines@cs.fsu.edu "txDescRead", 706019Shines@cs.fsu.edu "txFifoBlock", 716019Shines@cs.fsu.edu "txFragRead", 726019Shines@cs.fsu.edu "txDescWrite", 736019Shines@cs.fsu.edu "txAdvance" 746019Shines@cs.fsu.edu}; 756019Shines@cs.fsu.edu 766019Shines@cs.fsu.educonst char *NsDmaState[] = 776019Shines@cs.fsu.edu{ 786019Shines@cs.fsu.edu "dmaIdle", 796019Shines@cs.fsu.edu "dmaReading", 806019Shines@cs.fsu.edu "dmaWriting", 816019Shines@cs.fsu.edu "dmaReadWaiting", 826019Shines@cs.fsu.edu "dmaWriteWaiting" 836019Shines@cs.fsu.edu}; 846019Shines@cs.fsu.edu 856019Shines@cs.fsu.eduusing namespace std; 866019Shines@cs.fsu.eduusing namespace Net; 876019Shines@cs.fsu.edu 886019Shines@cs.fsu.edu/////////////////////////////////////////////////////////////////////// 896019Shines@cs.fsu.edu// 906019Shines@cs.fsu.edu// NSGigE PCI Device 916019Shines@cs.fsu.edu// 926019Shines@cs.fsu.eduNSGigE::NSGigE(Params *p) 936019Shines@cs.fsu.edu : PciDev(p), ioEnable(false), 946252Sgblack@eecs.umich.edu txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 956243Sgblack@eecs.umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 966243Sgblack@eecs.umich.edu txXferLen(0), rxXferLen(0), clock(p->clock), 976243Sgblack@eecs.umich.edu txState(txIdle), txEnable(false), CTDD(false), 986019Shines@cs.fsu.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 996019Shines@cs.fsu.edu rxEnable(false), CRDD(false), rxPktBytes(0), 1006019Shines@cs.fsu.edu rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1016019Shines@cs.fsu.edu rxDmaReadEvent(this), rxDmaWriteEvent(this), 1026019Shines@cs.fsu.edu txDmaReadEvent(this), txDmaWriteEvent(this), 1036252Sgblack@eecs.umich.edu dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1046243Sgblack@eecs.umich.edu txDelay(p->tx_delay), rxDelay(p->rx_delay), 1056243Sgblack@eecs.umich.edu rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1066243Sgblack@eecs.umich.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1076019Shines@cs.fsu.edu acceptMulticast(false), acceptUnicast(false), 1086019Shines@cs.fsu.edu acceptPerfect(false), acceptArp(false), 1096019Shines@cs.fsu.edu physmem(p->pmem), intrTick(0), cpuPendingIntr(false), 1106019Shines@cs.fsu.edu intrEvent(0), interface(0) 1116019Shines@cs.fsu.edu{ 1126019Shines@cs.fsu.edu if (p->header_bus) { 1136019Shines@cs.fsu.edu pioInterface = newPioInterface(name(), p->hier, 1146252Sgblack@eecs.umich.edu p->header_bus, this, 1156243Sgblack@eecs.umich.edu &NSGigE::cacheAccess); 1166243Sgblack@eecs.umich.edu 1176243Sgblack@eecs.umich.edu pioLatency = p->pio_latency * p->header_bus->clockRate; 1186019Shines@cs.fsu.edu 1196019Shines@cs.fsu.edu if (p->payload_bus) 1206019Shines@cs.fsu.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1216019Shines@cs.fsu.edu p->header_bus, 1226019Shines@cs.fsu.edu p->payload_bus, 1, 1236019Shines@cs.fsu.edu p->dma_no_allocate); 1246019Shines@cs.fsu.edu else 1256019Shines@cs.fsu.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1266019Shines@cs.fsu.edu p->header_bus, 1276019Shines@cs.fsu.edu p->header_bus, 1, 1286019Shines@cs.fsu.edu p->dma_no_allocate); 1296019Shines@cs.fsu.edu } else if (p->payload_bus) { 1306019Shines@cs.fsu.edu pioInterface = newPioInterface(name(), p->hier, 1316019Shines@cs.fsu.edu p->payload_bus, this, 1326019Shines@cs.fsu.edu &NSGigE::cacheAccess); 1336019Shines@cs.fsu.edu 1346724Sgblack@eecs.umich.edu pioLatency = p->pio_latency * p->payload_bus->clockRate; 1356724Sgblack@eecs.umich.edu 1366019Shines@cs.fsu.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1376019Shines@cs.fsu.edu p->payload_bus, 1386019Shines@cs.fsu.edu p->payload_bus, 1, 1396019Shines@cs.fsu.edu p->dma_no_allocate); 1406019Shines@cs.fsu.edu } 1416252Sgblack@eecs.umich.edu 1426243Sgblack@eecs.umich.edu 1436243Sgblack@eecs.umich.edu intrDelay = p->intr_delay; 1446243Sgblack@eecs.umich.edu dmaReadDelay = p->dma_read_delay; 1456019Shines@cs.fsu.edu dmaWriteDelay = p->dma_write_delay; 1466019Shines@cs.fsu.edu dmaReadFactor = p->dma_read_factor; 1476019Shines@cs.fsu.edu dmaWriteFactor = p->dma_write_factor; 1486019Shines@cs.fsu.edu 1496019Shines@cs.fsu.edu regsReset(); 1506019Shines@cs.fsu.edu memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1517356Sgblack@eecs.umich.edu} 1527356Sgblack@eecs.umich.edu 1537356Sgblack@eecs.umich.eduNSGigE::~NSGigE() 1547356Sgblack@eecs.umich.edu{} 1557356Sgblack@eecs.umich.edu 1567356Sgblack@eecs.umich.eduvoid 1577356Sgblack@eecs.umich.eduNSGigE::regStats() 1587356Sgblack@eecs.umich.edu{ 1597178Sgblack@eecs.umich.edu txBytes 1607178Sgblack@eecs.umich.edu .name(name() + ".txBytes") 1617178Sgblack@eecs.umich.edu .desc("Bytes Transmitted") 1627337Sgblack@eecs.umich.edu .prereq(txBytes) 1637178Sgblack@eecs.umich.edu ; 1647178Sgblack@eecs.umich.edu 1657178Sgblack@eecs.umich.edu rxBytes 1667178Sgblack@eecs.umich.edu .name(name() + ".rxBytes") 1677178Sgblack@eecs.umich.edu .desc("Bytes Received") 1687178Sgblack@eecs.umich.edu .prereq(rxBytes) 1697178Sgblack@eecs.umich.edu ; 1707178Sgblack@eecs.umich.edu 1717178Sgblack@eecs.umich.edu txPackets 1727178Sgblack@eecs.umich.edu .name(name() + ".txPackets") 1737178Sgblack@eecs.umich.edu .desc("Number of Packets Transmitted") 1747335Sgblack@eecs.umich.edu .prereq(txBytes) 1757335Sgblack@eecs.umich.edu ; 1767335Sgblack@eecs.umich.edu 1777335Sgblack@eecs.umich.edu rxPackets 1787335Sgblack@eecs.umich.edu .name(name() + ".rxPackets") 1797335Sgblack@eecs.umich.edu .desc("Number of Packets Received") 1807335Sgblack@eecs.umich.edu .prereq(rxBytes) 1817335Sgblack@eecs.umich.edu ; 1827335Sgblack@eecs.umich.edu 1837335Sgblack@eecs.umich.edu txIpChecksums 1847335Sgblack@eecs.umich.edu .name(name() + ".txIpChecksums") 1857335Sgblack@eecs.umich.edu .desc("Number of tx IP Checksums done by device") 1867337Sgblack@eecs.umich.edu .precision(0) 1877335Sgblack@eecs.umich.edu .prereq(txBytes) 1887335Sgblack@eecs.umich.edu ; 1897335Sgblack@eecs.umich.edu 1907335Sgblack@eecs.umich.edu rxIpChecksums 1917335Sgblack@eecs.umich.edu .name(name() + ".rxIpChecksums") 1927335Sgblack@eecs.umich.edu .desc("Number of rx IP Checksums done by device") 1937335Sgblack@eecs.umich.edu .precision(0) 1947335Sgblack@eecs.umich.edu .prereq(rxBytes) 1957335Sgblack@eecs.umich.edu ; 1967335Sgblack@eecs.umich.edu 1977335Sgblack@eecs.umich.edu txTcpChecksums 1987335Sgblack@eecs.umich.edu .name(name() + ".txTcpChecksums") 1997178Sgblack@eecs.umich.edu .desc("Number of tx TCP Checksums done by device") 2007178Sgblack@eecs.umich.edu .precision(0) 2017178Sgblack@eecs.umich.edu .prereq(txBytes) 2027178Sgblack@eecs.umich.edu ; 2037178Sgblack@eecs.umich.edu 2047178Sgblack@eecs.umich.edu rxTcpChecksums 2057178Sgblack@eecs.umich.edu .name(name() + ".rxTcpChecksums") 2067178Sgblack@eecs.umich.edu .desc("Number of rx TCP Checksums done by device") 2077178Sgblack@eecs.umich.edu .precision(0) 2087178Sgblack@eecs.umich.edu .prereq(rxBytes) 2097178Sgblack@eecs.umich.edu ; 2107178Sgblack@eecs.umich.edu 2117178Sgblack@eecs.umich.edu txUdpChecksums 2127178Sgblack@eecs.umich.edu .name(name() + ".txUdpChecksums") 2137178Sgblack@eecs.umich.edu .desc("Number of tx UDP Checksums done by device") 2147178Sgblack@eecs.umich.edu .precision(0) 2157178Sgblack@eecs.umich.edu .prereq(txBytes) 2167178Sgblack@eecs.umich.edu ; 2177178Sgblack@eecs.umich.edu 2187178Sgblack@eecs.umich.edu rxUdpChecksums 2197178Sgblack@eecs.umich.edu .name(name() + ".rxUdpChecksums") 2207178Sgblack@eecs.umich.edu .desc("Number of rx UDP Checksums done by device") 2217178Sgblack@eecs.umich.edu .precision(0) 2227178Sgblack@eecs.umich.edu .prereq(rxBytes) 2237178Sgblack@eecs.umich.edu ; 2247178Sgblack@eecs.umich.edu 2257178Sgblack@eecs.umich.edu descDmaReads 2267178Sgblack@eecs.umich.edu .name(name() + ".descDMAReads") 2277178Sgblack@eecs.umich.edu .desc("Number of descriptors the device read w/ DMA") 2287346Sgblack@eecs.umich.edu .precision(0) 2297346Sgblack@eecs.umich.edu ; 2307346Sgblack@eecs.umich.edu 2317346Sgblack@eecs.umich.edu descDmaWrites 2327346Sgblack@eecs.umich.edu .name(name() + ".descDMAWrites") 2337346Sgblack@eecs.umich.edu .desc("Number of descriptors the device wrote w/ DMA") 2347346Sgblack@eecs.umich.edu .precision(0) 2357346Sgblack@eecs.umich.edu ; 2367346Sgblack@eecs.umich.edu 2377346Sgblack@eecs.umich.edu descDmaRdBytes 2387178Sgblack@eecs.umich.edu .name(name() + ".descDmaReadBytes") 2397346Sgblack@eecs.umich.edu .desc("number of descriptor bytes read w/ DMA") 2407346Sgblack@eecs.umich.edu .precision(0) 2417346Sgblack@eecs.umich.edu ; 2427346Sgblack@eecs.umich.edu 2437346Sgblack@eecs.umich.edu descDmaWrBytes 2447346Sgblack@eecs.umich.edu .name(name() + ".descDmaWriteBytes") 2457346Sgblack@eecs.umich.edu .desc("number of descriptor bytes write w/ DMA") 2467346Sgblack@eecs.umich.edu .precision(0) 2477346Sgblack@eecs.umich.edu ; 2487346Sgblack@eecs.umich.edu 2497346Sgblack@eecs.umich.edu txBandwidth 2507346Sgblack@eecs.umich.edu .name(name() + ".txBandwidth") 2517346Sgblack@eecs.umich.edu .desc("Transmit Bandwidth (bits/s)") 2527346Sgblack@eecs.umich.edu .precision(0) 2537346Sgblack@eecs.umich.edu .prereq(txBytes) 2547178Sgblack@eecs.umich.edu ; 2557337Sgblack@eecs.umich.edu 2567337Sgblack@eecs.umich.edu rxBandwidth 2577337Sgblack@eecs.umich.edu .name(name() + ".rxBandwidth") 2587337Sgblack@eecs.umich.edu .desc("Receive Bandwidth (bits/s)") 2597337Sgblack@eecs.umich.edu .precision(0) 2607337Sgblack@eecs.umich.edu .prereq(rxBytes) 2617337Sgblack@eecs.umich.edu ; 2627337Sgblack@eecs.umich.edu 2637337Sgblack@eecs.umich.edu totBandwidth 2647337Sgblack@eecs.umich.edu .name(name() + ".totBandwidth") 2657337Sgblack@eecs.umich.edu .desc("Total Bandwidth (bits/s)") 2667337Sgblack@eecs.umich.edu .precision(0) 2677337Sgblack@eecs.umich.edu .prereq(totBytes) 2687337Sgblack@eecs.umich.edu ; 2697337Sgblack@eecs.umich.edu 2707178Sgblack@eecs.umich.edu totPackets 2717178Sgblack@eecs.umich.edu .name(name() + ".totPackets") 2727178Sgblack@eecs.umich.edu .desc("Total Packets") 2737178Sgblack@eecs.umich.edu .precision(0) 2747337Sgblack@eecs.umich.edu .prereq(totBytes) 2757337Sgblack@eecs.umich.edu ; 2767337Sgblack@eecs.umich.edu 2777337Sgblack@eecs.umich.edu totBytes 2787346Sgblack@eecs.umich.edu .name(name() + ".totBytes") 2797346Sgblack@eecs.umich.edu .desc("Total Bytes") 2807346Sgblack@eecs.umich.edu .precision(0) 2817346Sgblack@eecs.umich.edu .prereq(totBytes) 2827346Sgblack@eecs.umich.edu ; 2837337Sgblack@eecs.umich.edu 2847178Sgblack@eecs.umich.edu totPacketRate 2857321Sgblack@eecs.umich.edu .name(name() + ".totPPS") 2867356Sgblack@eecs.umich.edu .desc("Total Tranmission Rate (packets/s)") 2877321Sgblack@eecs.umich.edu .precision(0) 2887356Sgblack@eecs.umich.edu .prereq(totBytes) 2897356Sgblack@eecs.umich.edu ; 2907356Sgblack@eecs.umich.edu 2917356Sgblack@eecs.umich.edu txPacketRate 2927356Sgblack@eecs.umich.edu .name(name() + ".txPPS") 2937356Sgblack@eecs.umich.edu .desc("Packet Tranmission Rate (packets/s)") 2947356Sgblack@eecs.umich.edu .precision(0) 2957356Sgblack@eecs.umich.edu .prereq(txBytes) 2967356Sgblack@eecs.umich.edu ; 2977356Sgblack@eecs.umich.edu 2987356Sgblack@eecs.umich.edu rxPacketRate 2997356Sgblack@eecs.umich.edu .name(name() + ".rxPPS") 3007321Sgblack@eecs.umich.edu .desc("Packet Reception Rate (packets/s)") 3017321Sgblack@eecs.umich.edu .precision(0) 3027321Sgblack@eecs.umich.edu .prereq(rxBytes) 3037321Sgblack@eecs.umich.edu ; 3047321Sgblack@eecs.umich.edu 3057321Sgblack@eecs.umich.edu postedSwi 3067321Sgblack@eecs.umich.edu .name(name() + ".postedSwi") 3077321Sgblack@eecs.umich.edu .desc("number of software interrupts posted to CPU") 3087321Sgblack@eecs.umich.edu .precision(0) 3097321Sgblack@eecs.umich.edu ; 3107321Sgblack@eecs.umich.edu 3117335Sgblack@eecs.umich.edu totalSwi 3127335Sgblack@eecs.umich.edu .name(name() + ".totalSwi") 3137335Sgblack@eecs.umich.edu .desc("number of total Swi written to ISR") 3147335Sgblack@eecs.umich.edu .precision(0) 3157335Sgblack@eecs.umich.edu ; 3167335Sgblack@eecs.umich.edu 3177335Sgblack@eecs.umich.edu coalescedSwi 3187335Sgblack@eecs.umich.edu .name(name() + ".coalescedSwi") 3197335Sgblack@eecs.umich.edu .desc("average number of Swi's coalesced into each post") 3207321Sgblack@eecs.umich.edu .precision(0) 3217323Sgblack@eecs.umich.edu ; 3227323Sgblack@eecs.umich.edu 3237323Sgblack@eecs.umich.edu postedRxIdle 3247323Sgblack@eecs.umich.edu .name(name() + ".postedRxIdle") 3257323Sgblack@eecs.umich.edu .desc("number of rxIdle interrupts posted to CPU") 3267323Sgblack@eecs.umich.edu .precision(0) 3277323Sgblack@eecs.umich.edu ; 3287323Sgblack@eecs.umich.edu 3297323Sgblack@eecs.umich.edu totalRxIdle 3307323Sgblack@eecs.umich.edu .name(name() + ".totalRxIdle") 3317323Sgblack@eecs.umich.edu .desc("number of total RxIdle written to ISR") 3327323Sgblack@eecs.umich.edu .precision(0) 3337323Sgblack@eecs.umich.edu ; 3347323Sgblack@eecs.umich.edu 3357323Sgblack@eecs.umich.edu coalescedRxIdle 3367323Sgblack@eecs.umich.edu .name(name() + ".coalescedRxIdle") 3377323Sgblack@eecs.umich.edu .desc("average number of RxIdle's coalesced into each post") 3387321Sgblack@eecs.umich.edu .precision(0) 3397321Sgblack@eecs.umich.edu ; 3407321Sgblack@eecs.umich.edu 3417335Sgblack@eecs.umich.edu postedRxOk 3427335Sgblack@eecs.umich.edu .name(name() + ".postedRxOk") 3437335Sgblack@eecs.umich.edu .desc("number of RxOk interrupts posted to CPU") 3447335Sgblack@eecs.umich.edu .precision(0) 3457335Sgblack@eecs.umich.edu ; 3467335Sgblack@eecs.umich.edu 3477335Sgblack@eecs.umich.edu totalRxOk 3487335Sgblack@eecs.umich.edu .name(name() + ".totalRxOk") 3497335Sgblack@eecs.umich.edu .desc("number of total RxOk written to ISR") 3507335Sgblack@eecs.umich.edu .precision(0) 3517335Sgblack@eecs.umich.edu ; 3527335Sgblack@eecs.umich.edu 3537335Sgblack@eecs.umich.edu coalescedRxOk 3547335Sgblack@eecs.umich.edu .name(name() + ".coalescedRxOk") 3557335Sgblack@eecs.umich.edu .desc("average number of RxOk's coalesced into each post") 3567335Sgblack@eecs.umich.edu .precision(0) 3577335Sgblack@eecs.umich.edu ; 3587335Sgblack@eecs.umich.edu 3597335Sgblack@eecs.umich.edu postedRxDesc 3607335Sgblack@eecs.umich.edu .name(name() + ".postedRxDesc") 3617335Sgblack@eecs.umich.edu .desc("number of RxDesc interrupts posted to CPU") 3627335Sgblack@eecs.umich.edu .precision(0) 3637335Sgblack@eecs.umich.edu ; 3647335Sgblack@eecs.umich.edu 3657335Sgblack@eecs.umich.edu totalRxDesc 3667335Sgblack@eecs.umich.edu .name(name() + ".totalRxDesc") 3677335Sgblack@eecs.umich.edu .desc("number of total RxDesc written to ISR") 3687335Sgblack@eecs.umich.edu .precision(0) 3697335Sgblack@eecs.umich.edu ; 3707335Sgblack@eecs.umich.edu 3717335Sgblack@eecs.umich.edu coalescedRxDesc 3727335Sgblack@eecs.umich.edu .name(name() + ".coalescedRxDesc") 3737335Sgblack@eecs.umich.edu .desc("average number of RxDesc's coalesced into each post") 3747321Sgblack@eecs.umich.edu .precision(0) 3757321Sgblack@eecs.umich.edu ; 3767321Sgblack@eecs.umich.edu 3777321Sgblack@eecs.umich.edu postedTxOk 3787321Sgblack@eecs.umich.edu .name(name() + ".postedTxOk") 3797321Sgblack@eecs.umich.edu .desc("number of TxOk interrupts posted to CPU") 3807335Sgblack@eecs.umich.edu .precision(0) 3817335Sgblack@eecs.umich.edu ; 3827335Sgblack@eecs.umich.edu 3837335Sgblack@eecs.umich.edu totalTxOk 3847335Sgblack@eecs.umich.edu .name(name() + ".totalTxOk") 3857335Sgblack@eecs.umich.edu .desc("number of total TxOk written to ISR") 3867335Sgblack@eecs.umich.edu .precision(0) 3877335Sgblack@eecs.umich.edu ; 3887335Sgblack@eecs.umich.edu 3897321Sgblack@eecs.umich.edu coalescedTxOk 3907326Sgblack@eecs.umich.edu .name(name() + ".coalescedTxOk") 3917326Sgblack@eecs.umich.edu .desc("average number of TxOk's coalesced into each post") 3927326Sgblack@eecs.umich.edu .precision(0) 3937326Sgblack@eecs.umich.edu ; 3947326Sgblack@eecs.umich.edu 3957326Sgblack@eecs.umich.edu postedTxIdle 3967326Sgblack@eecs.umich.edu .name(name() + ".postedTxIdle") 3977326Sgblack@eecs.umich.edu .desc("number of TxIdle interrupts posted to CPU") 3987326Sgblack@eecs.umich.edu .precision(0) 3997326Sgblack@eecs.umich.edu ; 4007326Sgblack@eecs.umich.edu 4017326Sgblack@eecs.umich.edu totalTxIdle 4027326Sgblack@eecs.umich.edu .name(name() + ".totalTxIdle") 4037326Sgblack@eecs.umich.edu .desc("number of total TxIdle written to ISR") 4047326Sgblack@eecs.umich.edu .precision(0) 4057326Sgblack@eecs.umich.edu ; 4067326Sgblack@eecs.umich.edu 4077326Sgblack@eecs.umich.edu coalescedTxIdle 4087326Sgblack@eecs.umich.edu .name(name() + ".coalescedTxIdle") 4097326Sgblack@eecs.umich.edu .desc("average number of TxIdle's coalesced into each post") 4107326Sgblack@eecs.umich.edu .precision(0) 4117326Sgblack@eecs.umich.edu ; 4127326Sgblack@eecs.umich.edu 4137321Sgblack@eecs.umich.edu postedTxDesc 4147321Sgblack@eecs.umich.edu .name(name() + ".postedTxDesc") 4157335Sgblack@eecs.umich.edu .desc("number of TxDesc interrupts posted to CPU") 4167335Sgblack@eecs.umich.edu .precision(0) 4177335Sgblack@eecs.umich.edu ; 4187335Sgblack@eecs.umich.edu 4197335Sgblack@eecs.umich.edu totalTxDesc 4207335Sgblack@eecs.umich.edu .name(name() + ".totalTxDesc") 4217335Sgblack@eecs.umich.edu .desc("number of total TxDesc written to ISR") 4227335Sgblack@eecs.umich.edu .precision(0) 4237335Sgblack@eecs.umich.edu ; 4247335Sgblack@eecs.umich.edu 4257335Sgblack@eecs.umich.edu coalescedTxDesc 4267335Sgblack@eecs.umich.edu .name(name() + ".coalescedTxDesc") 4277335Sgblack@eecs.umich.edu .desc("average number of TxDesc's coalesced into each post") 4287335Sgblack@eecs.umich.edu .precision(0) 4297335Sgblack@eecs.umich.edu ; 4307335Sgblack@eecs.umich.edu 4317335Sgblack@eecs.umich.edu postedRxOrn 4327335Sgblack@eecs.umich.edu .name(name() + ".postedRxOrn") 4337335Sgblack@eecs.umich.edu .desc("number of RxOrn posted to CPU") 4347335Sgblack@eecs.umich.edu .precision(0) 4357335Sgblack@eecs.umich.edu ; 4367335Sgblack@eecs.umich.edu 4377335Sgblack@eecs.umich.edu totalRxOrn 4387335Sgblack@eecs.umich.edu .name(name() + ".totalRxOrn") 4397335Sgblack@eecs.umich.edu .desc("number of total RxOrn written to ISR") 4407335Sgblack@eecs.umich.edu .precision(0) 4417335Sgblack@eecs.umich.edu ; 4427335Sgblack@eecs.umich.edu 4437335Sgblack@eecs.umich.edu coalescedRxOrn 4447335Sgblack@eecs.umich.edu .name(name() + ".coalescedRxOrn") 4457335Sgblack@eecs.umich.edu .desc("average number of RxOrn's coalesced into each post") 4467335Sgblack@eecs.umich.edu .precision(0) 4477335Sgblack@eecs.umich.edu ; 4487335Sgblack@eecs.umich.edu 4497335Sgblack@eecs.umich.edu coalescedTotal 4507335Sgblack@eecs.umich.edu .name(name() + ".coalescedTotal") 4517335Sgblack@eecs.umich.edu .desc("average number of interrupts coalesced into each post") 4527335Sgblack@eecs.umich.edu .precision(0) 4537335Sgblack@eecs.umich.edu ; 4547335Sgblack@eecs.umich.edu 4557335Sgblack@eecs.umich.edu postedInterrupts 4567335Sgblack@eecs.umich.edu .name(name() + ".postedInterrupts") 4577335Sgblack@eecs.umich.edu .desc("number of posts to CPU") 4587335Sgblack@eecs.umich.edu .precision(0) 4597321Sgblack@eecs.umich.edu ; 4607321Sgblack@eecs.umich.edu 4617321Sgblack@eecs.umich.edu droppedPackets 4627321Sgblack@eecs.umich.edu .name(name() + ".droppedPackets") 4637321Sgblack@eecs.umich.edu .desc("number of packets dropped") 4647356Sgblack@eecs.umich.edu .precision(0) 4657356Sgblack@eecs.umich.edu ; 4667356Sgblack@eecs.umich.edu 4677356Sgblack@eecs.umich.edu coalescedSwi = totalSwi / postedInterrupts; 4687356Sgblack@eecs.umich.edu coalescedRxIdle = totalRxIdle / postedInterrupts; 4697356Sgblack@eecs.umich.edu coalescedRxOk = totalRxOk / postedInterrupts; 4707363Sgblack@eecs.umich.edu coalescedRxDesc = totalRxDesc / postedInterrupts; 4717363Sgblack@eecs.umich.edu coalescedTxOk = totalTxOk / postedInterrupts; 4727363Sgblack@eecs.umich.edu coalescedTxIdle = totalTxIdle / postedInterrupts; 4737363Sgblack@eecs.umich.edu coalescedTxDesc = totalTxDesc / postedInterrupts; 4747363Sgblack@eecs.umich.edu coalescedRxOrn = totalRxOrn / postedInterrupts; 4757363Sgblack@eecs.umich.edu 4767363Sgblack@eecs.umich.edu coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 4777363Sgblack@eecs.umich.edu totalTxOk + totalTxIdle + totalTxDesc + 4787363Sgblack@eecs.umich.edu totalRxOrn) / postedInterrupts; 4797363Sgblack@eecs.umich.edu 4807363Sgblack@eecs.umich.edu txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4817363Sgblack@eecs.umich.edu rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4827363Sgblack@eecs.umich.edu totBandwidth = txBandwidth + rxBandwidth; 4837363Sgblack@eecs.umich.edu totBytes = txBytes + rxBytes; 4847363Sgblack@eecs.umich.edu totPackets = txPackets + rxPackets; 4857363Sgblack@eecs.umich.edu 4867363Sgblack@eecs.umich.edu txPacketRate = txPackets / simSeconds; 4877363Sgblack@eecs.umich.edu rxPacketRate = rxPackets / simSeconds; 4887363Sgblack@eecs.umich.edu} 4897364Sgblack@eecs.umich.edu 4907364Sgblack@eecs.umich.edu/** 4917364Sgblack@eecs.umich.edu * This is to read the PCI general configuration registers 4927364Sgblack@eecs.umich.edu */ 4937364Sgblack@eecs.umich.eduvoid 4947364Sgblack@eecs.umich.eduNSGigE::ReadConfig(int offset, int size, uint8_t *data) 4957364Sgblack@eecs.umich.edu{ 4967364Sgblack@eecs.umich.edu if (offset < PCI_DEVICE_SPECIFIC) 4977364Sgblack@eecs.umich.edu PciDev::ReadConfig(offset, size, data); 4987364Sgblack@eecs.umich.edu else 4997364Sgblack@eecs.umich.edu panic("Device specific PCI config space not implemented!\n"); 5007364Sgblack@eecs.umich.edu} 5017364Sgblack@eecs.umich.edu 5027364Sgblack@eecs.umich.edu/** 5037364Sgblack@eecs.umich.edu * This is to write to the PCI general configuration registers 5047364Sgblack@eecs.umich.edu */ 5057364Sgblack@eecs.umich.eduvoid 5067364Sgblack@eecs.umich.eduNSGigE::WriteConfig(int offset, int size, uint32_t data) 5077364Sgblack@eecs.umich.edu{ 5087363Sgblack@eecs.umich.edu if (offset < PCI_DEVICE_SPECIFIC) 5097363Sgblack@eecs.umich.edu PciDev::WriteConfig(offset, size, data); 5107363Sgblack@eecs.umich.edu else 5117363Sgblack@eecs.umich.edu panic("Device specific PCI config space not implemented!\n"); 5127363Sgblack@eecs.umich.edu 5137367Sgblack@eecs.umich.edu // Need to catch writes to BARs to update the PIO interface 5147367Sgblack@eecs.umich.edu switch (offset) { 5157367Sgblack@eecs.umich.edu // seems to work fine without all these PCI settings, but i 5167367Sgblack@eecs.umich.edu // put in the IO to double check, an assertion will fail if we 5177367Sgblack@eecs.umich.edu // need to properly implement it 5187367Sgblack@eecs.umich.edu case PCI_COMMAND: 5197367Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_IOSE) 5207367Sgblack@eecs.umich.edu ioEnable = true; 5217367Sgblack@eecs.umich.edu else 5227367Sgblack@eecs.umich.edu ioEnable = false; 5237367Sgblack@eecs.umich.edu 5247367Sgblack@eecs.umich.edu#if 0 5257367Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_BME) { 5267367Sgblack@eecs.umich.edu bmEnabled = true; 5277367Sgblack@eecs.umich.edu } 5287367Sgblack@eecs.umich.edu else { 5297367Sgblack@eecs.umich.edu bmEnabled = false; 5307367Sgblack@eecs.umich.edu } 5317367Sgblack@eecs.umich.edu 5327363Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_MSE) { 5337368Sgblack@eecs.umich.edu memEnable = true; 5347368Sgblack@eecs.umich.edu } 5357368Sgblack@eecs.umich.edu else { 5367368Sgblack@eecs.umich.edu memEnable = false; 5377368Sgblack@eecs.umich.edu } 5387368Sgblack@eecs.umich.edu#endif 5397368Sgblack@eecs.umich.edu break; 5407368Sgblack@eecs.umich.edu 5417368Sgblack@eecs.umich.edu case PCI0_BASE_ADDR0: 5427368Sgblack@eecs.umich.edu if (BARAddrs[0] != 0) { 5437368Sgblack@eecs.umich.edu if (pioInterface) 5447368Sgblack@eecs.umich.edu pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 5457368Sgblack@eecs.umich.edu 5467368Sgblack@eecs.umich.edu BARAddrs[0] &= EV5::PAddrUncachedMask; 5477368Sgblack@eecs.umich.edu } 5487368Sgblack@eecs.umich.edu break; 5497368Sgblack@eecs.umich.edu case PCI0_BASE_ADDR1: 5507368Sgblack@eecs.umich.edu if (BARAddrs[1] != 0) { 5517368Sgblack@eecs.umich.edu if (pioInterface) 5527363Sgblack@eecs.umich.edu pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 5537363Sgblack@eecs.umich.edu 5547363Sgblack@eecs.umich.edu BARAddrs[1] &= EV5::PAddrUncachedMask; 5557363Sgblack@eecs.umich.edu } 5567363Sgblack@eecs.umich.edu break; 5577363Sgblack@eecs.umich.edu } 5587363Sgblack@eecs.umich.edu} 5597363Sgblack@eecs.umich.edu 5607363Sgblack@eecs.umich.edu/** 5617363Sgblack@eecs.umich.edu * This reads the device registers, which are detailed in the NS83820 5627363Sgblack@eecs.umich.edu * spec sheet 5637363Sgblack@eecs.umich.edu */ 5647363Sgblack@eecs.umich.eduFault 5657363Sgblack@eecs.umich.eduNSGigE::read(MemReqPtr &req, uint8_t *data) 5667363Sgblack@eecs.umich.edu{ 5677363Sgblack@eecs.umich.edu assert(ioEnable); 5687363Sgblack@eecs.umich.edu 5697363Sgblack@eecs.umich.edu //The mask is to give you only the offset into the device register file 5707363Sgblack@eecs.umich.edu Addr daddr = req->paddr & 0xfff; 5717363Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 5727363Sgblack@eecs.umich.edu daddr, req->paddr, req->vaddr, req->size); 5737363Sgblack@eecs.umich.edu 5747363Sgblack@eecs.umich.edu 5757363Sgblack@eecs.umich.edu // there are some reserved registers, you can see ns_gige_reg.h and 5767363Sgblack@eecs.umich.edu // the spec sheet for details 5777363Sgblack@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 5787363Sgblack@eecs.umich.edu panic("Accessing reserved register"); 5797363Sgblack@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 5807363Sgblack@eecs.umich.edu ReadConfig(daddr & 0xff, req->size, data); 5817363Sgblack@eecs.umich.edu return No_Fault; 5827363Sgblack@eecs.umich.edu } else if (daddr >= MIB_START && daddr <= MIB_END) { 5837363Sgblack@eecs.umich.edu // don't implement all the MIB's. hopefully the kernel 5847363Sgblack@eecs.umich.edu // doesn't actually DEPEND upon their values 5857363Sgblack@eecs.umich.edu // MIB are just hardware stats keepers 5867363Sgblack@eecs.umich.edu uint32_t ® = *(uint32_t *) data; 5877363Sgblack@eecs.umich.edu reg = 0; 5887363Sgblack@eecs.umich.edu return No_Fault; 5897363Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 5907363Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 5917363Sgblack@eecs.umich.edu 5927363Sgblack@eecs.umich.edu switch (req->size) { 5937366Sgblack@eecs.umich.edu case sizeof(uint32_t): 5947366Sgblack@eecs.umich.edu { 5957366Sgblack@eecs.umich.edu uint32_t ® = *(uint32_t *)data; 5967366Sgblack@eecs.umich.edu 5977366Sgblack@eecs.umich.edu switch (daddr) { 5987366Sgblack@eecs.umich.edu case CR: 5997366Sgblack@eecs.umich.edu reg = regs.command; 6007366Sgblack@eecs.umich.edu //these are supposed to be cleared on a read 6017366Sgblack@eecs.umich.edu reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 6027366Sgblack@eecs.umich.edu break; 6037366Sgblack@eecs.umich.edu 6047366Sgblack@eecs.umich.edu case CFGR: 6057366Sgblack@eecs.umich.edu reg = regs.config; 6067366Sgblack@eecs.umich.edu break; 6077366Sgblack@eecs.umich.edu 6087363Sgblack@eecs.umich.edu case MEAR: 6097363Sgblack@eecs.umich.edu reg = regs.mear; 6107363Sgblack@eecs.umich.edu break; 6117365Sgblack@eecs.umich.edu 6127365Sgblack@eecs.umich.edu case PTSCR: 6137365Sgblack@eecs.umich.edu reg = regs.ptscr; 6147365Sgblack@eecs.umich.edu break; 6157365Sgblack@eecs.umich.edu 6167365Sgblack@eecs.umich.edu case ISR: 6177365Sgblack@eecs.umich.edu reg = regs.isr; 6187365Sgblack@eecs.umich.edu devIntrClear(ISR_ALL); 6197365Sgblack@eecs.umich.edu break; 6207365Sgblack@eecs.umich.edu 6217365Sgblack@eecs.umich.edu case IMR: 6227365Sgblack@eecs.umich.edu reg = regs.imr; 6237365Sgblack@eecs.umich.edu break; 6247365Sgblack@eecs.umich.edu 6257365Sgblack@eecs.umich.edu case IER: 6267363Sgblack@eecs.umich.edu reg = regs.ier; 6277363Sgblack@eecs.umich.edu break; 6287363Sgblack@eecs.umich.edu 6297363Sgblack@eecs.umich.edu case IHR: 6307363Sgblack@eecs.umich.edu reg = regs.ihr; 6317363Sgblack@eecs.umich.edu break; 6327363Sgblack@eecs.umich.edu 6337363Sgblack@eecs.umich.edu case TXDP: 6347363Sgblack@eecs.umich.edu reg = regs.txdp; 6357363Sgblack@eecs.umich.edu break; 6367363Sgblack@eecs.umich.edu 6377363Sgblack@eecs.umich.edu case TXDP_HI: 6387363Sgblack@eecs.umich.edu reg = regs.txdp_hi; 6397363Sgblack@eecs.umich.edu break; 6407363Sgblack@eecs.umich.edu 6417363Sgblack@eecs.umich.edu case TX_CFG: 6427363Sgblack@eecs.umich.edu reg = regs.txcfg; 6437363Sgblack@eecs.umich.edu break; 6447363Sgblack@eecs.umich.edu 6457363Sgblack@eecs.umich.edu case GPIOR: 6467363Sgblack@eecs.umich.edu reg = regs.gpior; 6477363Sgblack@eecs.umich.edu break; 6487363Sgblack@eecs.umich.edu 6497363Sgblack@eecs.umich.edu case RXDP: 6507363Sgblack@eecs.umich.edu reg = regs.rxdp; 6517363Sgblack@eecs.umich.edu break; 6527363Sgblack@eecs.umich.edu 6537363Sgblack@eecs.umich.edu case RXDP_HI: 6547363Sgblack@eecs.umich.edu reg = regs.rxdp_hi; 6557363Sgblack@eecs.umich.edu break; 6567363Sgblack@eecs.umich.edu 6577363Sgblack@eecs.umich.edu case RX_CFG: 6587363Sgblack@eecs.umich.edu reg = regs.rxcfg; 6597363Sgblack@eecs.umich.edu break; 6607363Sgblack@eecs.umich.edu 6617363Sgblack@eecs.umich.edu case PQCR: 6627363Sgblack@eecs.umich.edu reg = regs.pqcr; 6637363Sgblack@eecs.umich.edu break; 6647363Sgblack@eecs.umich.edu 6657363Sgblack@eecs.umich.edu case WCSR: 6667363Sgblack@eecs.umich.edu reg = regs.wcsr; 6677363Sgblack@eecs.umich.edu break; 6687363Sgblack@eecs.umich.edu 6697363Sgblack@eecs.umich.edu case PCR: 670 reg = regs.pcr; 671 break; 672 673 // see the spec sheet for how RFCR and RFDR work 674 // basically, you write to RFCR to tell the machine 675 // what you want to do next, then you act upon RFDR, 676 // and the device will be prepared b/c of what you 677 // wrote to RFCR 678 case RFCR: 679 reg = regs.rfcr; 680 break; 681 682 case RFDR: 683 switch (regs.rfcr & RFCR_RFADDR) { 684 case 0x000: 685 reg = rom.perfectMatch[1]; 686 reg = reg << 8; 687 reg += rom.perfectMatch[0]; 688 break; 689 case 0x002: 690 reg = rom.perfectMatch[3] << 8; 691 reg += rom.perfectMatch[2]; 692 break; 693 case 0x004: 694 reg = rom.perfectMatch[5] << 8; 695 reg += rom.perfectMatch[4]; 696 break; 697 default: 698 panic("reading RFDR for something other than PMATCH!\n"); 699 // didn't implement other RFDR functionality b/c 700 // driver didn't use it 701 } 702 break; 703 704 case SRR: 705 reg = regs.srr; 706 break; 707 708 case MIBC: 709 reg = regs.mibc; 710 reg &= ~(MIBC_MIBS | MIBC_ACLR); 711 break; 712 713 case VRCR: 714 reg = regs.vrcr; 715 break; 716 717 case VTCR: 718 reg = regs.vtcr; 719 break; 720 721 case VDR: 722 reg = regs.vdr; 723 break; 724 725 case CCSR: 726 reg = regs.ccsr; 727 break; 728 729 case TBICR: 730 reg = regs.tbicr; 731 break; 732 733 case TBISR: 734 reg = regs.tbisr; 735 break; 736 737 case TANAR: 738 reg = regs.tanar; 739 break; 740 741 case TANLPAR: 742 reg = regs.tanlpar; 743 break; 744 745 case TANER: 746 reg = regs.taner; 747 break; 748 749 case TESR: 750 reg = regs.tesr; 751 break; 752 753 case M5REG: 754 reg = params()->m5reg; 755 break; 756 757 default: 758 panic("reading unimplemented register: addr=%#x", daddr); 759 } 760 761 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 762 daddr, reg, reg); 763 } 764 break; 765 766 default: 767 panic("accessing register with invalid size: addr=%#x, size=%d", 768 daddr, req->size); 769 } 770 771 return No_Fault; 772} 773 774Fault 775NSGigE::write(MemReqPtr &req, const uint8_t *data) 776{ 777 assert(ioEnable); 778 779 Addr daddr = req->paddr & 0xfff; 780 DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 781 daddr, req->paddr, req->vaddr, req->size); 782 783 if (daddr > LAST && daddr <= RESERVED) { 784 panic("Accessing reserved register"); 785 } else if (daddr > RESERVED && daddr <= 0x3FC) { 786 WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 787 return No_Fault; 788 } else if (daddr > 0x3FC) 789 panic("Something is messed up!\n"); 790 791 if (req->size == sizeof(uint32_t)) { 792 uint32_t reg = *(uint32_t *)data; 793 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 794 795 switch (daddr) { 796 case CR: 797 regs.command = reg; 798 if (reg & CR_TXD) { 799 txEnable = false; 800 } else if (reg & CR_TXE) { 801 txEnable = true; 802 803 // the kernel is enabling the transmit machine 804 if (txState == txIdle) 805 txKick(); 806 } 807 808 if (reg & CR_RXD) { 809 rxEnable = false; 810 } else if (reg & CR_RXE) { 811 rxEnable = true; 812 813 if (rxState == rxIdle) 814 rxKick(); 815 } 816 817 if (reg & CR_TXR) 818 txReset(); 819 820 if (reg & CR_RXR) 821 rxReset(); 822 823 if (reg & CR_SWI) 824 devIntrPost(ISR_SWI); 825 826 if (reg & CR_RST) { 827 txReset(); 828 rxReset(); 829 830 regsReset(); 831 } 832 break; 833 834 case CFGR: 835 if (reg & CFGR_LNKSTS || 836 reg & CFGR_SPDSTS || 837 reg & CFGR_DUPSTS || 838 reg & CFGR_RESERVED || 839 reg & CFGR_T64ADDR || 840 reg & CFGR_PCI64_DET) 841 panic("writing to read-only or reserved CFGR bits!\n"); 842 843 regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 844 CFGR_RESERVED | CFGR_T64ADDR | 845 CFGR_PCI64_DET); 846 847// all these #if 0's are because i don't THINK the kernel needs to 848// have these implemented. if there is a problem relating to one of 849// these, you may need to add functionality in. 850#if 0 851 if (reg & CFGR_TBI_EN) ; 852 if (reg & CFGR_MODE_1000) ; 853#endif 854 855 if (reg & CFGR_AUTO_1000) 856 panic("CFGR_AUTO_1000 not implemented!\n"); 857 858#if 0 859 if (reg & CFGR_PINT_DUPSTS || 860 reg & CFGR_PINT_LNKSTS || 861 reg & CFGR_PINT_SPDSTS) 862 ; 863 864 if (reg & CFGR_TMRTEST) ; 865 if (reg & CFGR_MRM_DIS) ; 866 if (reg & CFGR_MWI_DIS) ; 867 868 if (reg & CFGR_T64ADDR) 869 panic("CFGR_T64ADDR is read only register!\n"); 870 871 if (reg & CFGR_PCI64_DET) 872 panic("CFGR_PCI64_DET is read only register!\n"); 873 874 if (reg & CFGR_DATA64_EN) ; 875 if (reg & CFGR_M64ADDR) ; 876 if (reg & CFGR_PHY_RST) ; 877 if (reg & CFGR_PHY_DIS) ; 878#endif 879 880 if (reg & CFGR_EXTSTS_EN) 881 extstsEnable = true; 882 else 883 extstsEnable = false; 884 885#if 0 886 if (reg & CFGR_REQALG) ; 887 if (reg & CFGR_SB) ; 888 if (reg & CFGR_POW) ; 889 if (reg & CFGR_EXD) ; 890 if (reg & CFGR_PESEL) ; 891 if (reg & CFGR_BROM_DIS) ; 892 if (reg & CFGR_EXT_125) ; 893 if (reg & CFGR_BEM) ; 894#endif 895 break; 896 897 case MEAR: 898 regs.mear = reg; 899 // since phy is completely faked, MEAR_MD* don't matter 900 // and since the driver never uses MEAR_EE*, they don't 901 // matter 902#if 0 903 if (reg & MEAR_EEDI) ; 904 if (reg & MEAR_EEDO) ; // this one is read only 905 if (reg & MEAR_EECLK) ; 906 if (reg & MEAR_EESEL) ; 907 if (reg & MEAR_MDIO) ; 908 if (reg & MEAR_MDDIR) ; 909 if (reg & MEAR_MDC) ; 910#endif 911 break; 912 913 case PTSCR: 914 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 915 // these control BISTs for various parts of chip - we 916 // don't care or do just fake that the BIST is done 917 if (reg & PTSCR_RBIST_EN) 918 regs.ptscr |= PTSCR_RBIST_DONE; 919 if (reg & PTSCR_EEBIST_EN) 920 regs.ptscr &= ~PTSCR_EEBIST_EN; 921 if (reg & PTSCR_EELOAD_EN) 922 regs.ptscr &= ~PTSCR_EELOAD_EN; 923 break; 924 925 case ISR: /* writing to the ISR has no effect */ 926 panic("ISR is a read only register!\n"); 927 928 case IMR: 929 regs.imr = reg; 930 devIntrChangeMask(); 931 break; 932 933 case IER: 934 regs.ier = reg; 935 break; 936 937 case IHR: 938 regs.ihr = reg; 939 /* not going to implement real interrupt holdoff */ 940 break; 941 942 case TXDP: 943 regs.txdp = (reg & 0xFFFFFFFC); 944 assert(txState == txIdle); 945 CTDD = false; 946 break; 947 948 case TXDP_HI: 949 regs.txdp_hi = reg; 950 break; 951 952 case TX_CFG: 953 regs.txcfg = reg; 954#if 0 955 if (reg & TX_CFG_CSI) ; 956 if (reg & TX_CFG_HBI) ; 957 if (reg & TX_CFG_MLB) ; 958 if (reg & TX_CFG_ATP) ; 959 if (reg & TX_CFG_ECRETRY) { 960 /* 961 * this could easily be implemented, but considering 962 * the network is just a fake pipe, wouldn't make 963 * sense to do this 964 */ 965 } 966 967 if (reg & TX_CFG_BRST_DIS) ; 968#endif 969 970#if 0 971 /* we handle our own DMA, ignore the kernel's exhortations */ 972 if (reg & TX_CFG_MXDMA) ; 973#endif 974 975 // also, we currently don't care about fill/drain 976 // thresholds though this may change in the future with 977 // more realistic networks or a driver which changes it 978 // according to feedback 979 980 break; 981 982 case GPIOR: 983 regs.gpior = reg; 984 /* these just control general purpose i/o pins, don't matter */ 985 break; 986 987 case RXDP: 988 regs.rxdp = reg; 989 CRDD = false; 990 break; 991 992 case RXDP_HI: 993 regs.rxdp_hi = reg; 994 break; 995 996 case RX_CFG: 997 regs.rxcfg = reg; 998#if 0 999 if (reg & RX_CFG_AEP) ; 1000 if (reg & RX_CFG_ARP) ; 1001 if (reg & RX_CFG_STRIPCRC) ; 1002 if (reg & RX_CFG_RX_RD) ; 1003 if (reg & RX_CFG_ALP) ; 1004 if (reg & RX_CFG_AIRL) ; 1005 1006 /* we handle our own DMA, ignore what kernel says about it */ 1007 if (reg & RX_CFG_MXDMA) ; 1008 1009 //also, we currently don't care about fill/drain thresholds 1010 //though this may change in the future with more realistic 1011 //networks or a driver which changes it according to feedback 1012 if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 1013#endif 1014 break; 1015 1016 case PQCR: 1017 /* there is no priority queueing used in the linux 2.6 driver */ 1018 regs.pqcr = reg; 1019 break; 1020 1021 case WCSR: 1022 /* not going to implement wake on LAN */ 1023 regs.wcsr = reg; 1024 break; 1025 1026 case PCR: 1027 /* not going to implement pause control */ 1028 regs.pcr = reg; 1029 break; 1030 1031 case RFCR: 1032 regs.rfcr = reg; 1033 1034 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 1035 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 1036 acceptMulticast = (reg & RFCR_AAM) ? true : false; 1037 acceptUnicast = (reg & RFCR_AAU) ? true : false; 1038 acceptPerfect = (reg & RFCR_APM) ? true : false; 1039 acceptArp = (reg & RFCR_AARP) ? true : false; 1040 1041#if 0 1042 if (reg & RFCR_APAT) 1043 panic("RFCR_APAT not implemented!\n"); 1044#endif 1045 1046 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 1047 panic("hash filtering not implemented!\n"); 1048 1049 if (reg & RFCR_ULM) 1050 panic("RFCR_ULM not implemented!\n"); 1051 1052 break; 1053 1054 case RFDR: 1055 panic("the driver never writes to RFDR, something is wrong!\n"); 1056 1057 case BRAR: 1058 panic("the driver never uses BRAR, something is wrong!\n"); 1059 1060 case BRDR: 1061 panic("the driver never uses BRDR, something is wrong!\n"); 1062 1063 case SRR: 1064 panic("SRR is read only register!\n"); 1065 1066 case MIBC: 1067 panic("the driver never uses MIBC, something is wrong!\n"); 1068 1069 case VRCR: 1070 regs.vrcr = reg; 1071 break; 1072 1073 case VTCR: 1074 regs.vtcr = reg; 1075 break; 1076 1077 case VDR: 1078 panic("the driver never uses VDR, something is wrong!\n"); 1079 break; 1080 1081 case CCSR: 1082 /* not going to implement clockrun stuff */ 1083 regs.ccsr = reg; 1084 break; 1085 1086 case TBICR: 1087 regs.tbicr = reg; 1088 if (reg & TBICR_MR_LOOPBACK) 1089 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 1090 1091 if (reg & TBICR_MR_AN_ENABLE) { 1092 regs.tanlpar = regs.tanar; 1093 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 1094 } 1095 1096#if 0 1097 if (reg & TBICR_MR_RESTART_AN) ; 1098#endif 1099 1100 break; 1101 1102 case TBISR: 1103 panic("TBISR is read only register!\n"); 1104 1105 case TANAR: 1106 regs.tanar = reg; 1107 if (reg & TANAR_PS2) 1108 panic("this isn't used in driver, something wrong!\n"); 1109 1110 if (reg & TANAR_PS1) 1111 panic("this isn't used in driver, something wrong!\n"); 1112 break; 1113 1114 case TANLPAR: 1115 panic("this should only be written to by the fake phy!\n"); 1116 1117 case TANER: 1118 panic("TANER is read only register!\n"); 1119 1120 case TESR: 1121 regs.tesr = reg; 1122 break; 1123 1124 default: 1125 panic("invalid register access daddr=%#x", daddr); 1126 } 1127 } else { 1128 panic("Invalid Request Size"); 1129 } 1130 1131 return No_Fault; 1132} 1133 1134void 1135NSGigE::devIntrPost(uint32_t interrupts) 1136{ 1137 if (interrupts & ISR_RESERVE) 1138 panic("Cannot set a reserved interrupt"); 1139 1140 if (interrupts & ISR_NOIMPL) 1141 warn("interrupt not implemented %#x\n", interrupts); 1142 1143 interrupts &= ~ISR_NOIMPL; 1144 regs.isr |= interrupts; 1145 1146 if (interrupts & regs.imr) { 1147 if (interrupts & ISR_SWI) { 1148 totalSwi++; 1149 } 1150 if (interrupts & ISR_RXIDLE) { 1151 totalRxIdle++; 1152 } 1153 if (interrupts & ISR_RXOK) { 1154 totalRxOk++; 1155 } 1156 if (interrupts & ISR_RXDESC) { 1157 totalRxDesc++; 1158 } 1159 if (interrupts & ISR_TXOK) { 1160 totalTxOk++; 1161 } 1162 if (interrupts & ISR_TXIDLE) { 1163 totalTxIdle++; 1164 } 1165 if (interrupts & ISR_TXDESC) { 1166 totalTxDesc++; 1167 } 1168 if (interrupts & ISR_RXORN) { 1169 totalRxOrn++; 1170 } 1171 } 1172 1173 DPRINTF(EthernetIntr, 1174 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 1175 interrupts, regs.isr, regs.imr); 1176 1177 if ((regs.isr & regs.imr)) { 1178 Tick when = curTick; 1179 if (!(regs.isr & regs.imr & ISR_NODELAY)) 1180 when += intrDelay; 1181 cpuIntrPost(when); 1182 } 1183} 1184 1185/* writing this interrupt counting stats inside this means that this function 1186 is now limited to being used to clear all interrupts upon the kernel 1187 reading isr and servicing. just telling you in case you were thinking 1188 of expanding use. 1189*/ 1190void 1191NSGigE::devIntrClear(uint32_t interrupts) 1192{ 1193 if (interrupts & ISR_RESERVE) 1194 panic("Cannot clear a reserved interrupt"); 1195 1196 if (regs.isr & regs.imr & ISR_SWI) { 1197 postedSwi++; 1198 } 1199 if (regs.isr & regs.imr & ISR_RXIDLE) { 1200 postedRxIdle++; 1201 } 1202 if (regs.isr & regs.imr & ISR_RXOK) { 1203 postedRxOk++; 1204 } 1205 if (regs.isr & regs.imr & ISR_RXDESC) { 1206 postedRxDesc++; 1207 } 1208 if (regs.isr & regs.imr & ISR_TXOK) { 1209 postedTxOk++; 1210 } 1211 if (regs.isr & regs.imr & ISR_TXIDLE) { 1212 postedTxIdle++; 1213 } 1214 if (regs.isr & regs.imr & ISR_TXDESC) { 1215 postedTxDesc++; 1216 } 1217 if (regs.isr & regs.imr & ISR_RXORN) { 1218 postedRxOrn++; 1219 } 1220 1221 if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC | 1222 ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) ) 1223 postedInterrupts++; 1224 1225 interrupts &= ~ISR_NOIMPL; 1226 regs.isr &= ~interrupts; 1227 1228 DPRINTF(EthernetIntr, 1229 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 1230 interrupts, regs.isr, regs.imr); 1231 1232 if (!(regs.isr & regs.imr)) 1233 cpuIntrClear(); 1234} 1235 1236void 1237NSGigE::devIntrChangeMask() 1238{ 1239 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 1240 regs.isr, regs.imr, regs.isr & regs.imr); 1241 1242 if (regs.isr & regs.imr) 1243 cpuIntrPost(curTick); 1244 else 1245 cpuIntrClear(); 1246} 1247 1248void 1249NSGigE::cpuIntrPost(Tick when) 1250{ 1251 // If the interrupt you want to post is later than an interrupt 1252 // already scheduled, just let it post in the coming one and don't 1253 // schedule another. 1254 // HOWEVER, must be sure that the scheduled intrTick is in the 1255 // future (this was formerly the source of a bug) 1256 /** 1257 * @todo this warning should be removed and the intrTick code should 1258 * be fixed. 1259 */ 1260 assert(when >= curTick); 1261 assert(intrTick >= curTick || intrTick == 0); 1262 if (when > intrTick && intrTick != 0) { 1263 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 1264 intrTick); 1265 return; 1266 } 1267 1268 intrTick = when; 1269 if (intrTick < curTick) { 1270 debug_break(); 1271 intrTick = curTick; 1272 } 1273 1274 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 1275 intrTick); 1276 1277 if (intrEvent) 1278 intrEvent->squash(); 1279 intrEvent = new IntrEvent(this, true); 1280 intrEvent->schedule(intrTick); 1281} 1282 1283void 1284NSGigE::cpuInterrupt() 1285{ 1286 assert(intrTick == curTick); 1287 1288 // Whether or not there's a pending interrupt, we don't care about 1289 // it anymore 1290 intrEvent = 0; 1291 intrTick = 0; 1292 1293 // Don't send an interrupt if there's already one 1294 if (cpuPendingIntr) { 1295 DPRINTF(EthernetIntr, 1296 "would send an interrupt now, but there's already pending\n"); 1297 } else { 1298 // Send interrupt 1299 cpuPendingIntr = true; 1300 1301 DPRINTF(EthernetIntr, "posting interrupt\n"); 1302 intrPost(); 1303 } 1304} 1305 1306void 1307NSGigE::cpuIntrClear() 1308{ 1309 if (!cpuPendingIntr) 1310 return; 1311 1312 if (intrEvent) { 1313 intrEvent->squash(); 1314 intrEvent = 0; 1315 } 1316 1317 intrTick = 0; 1318 1319 cpuPendingIntr = false; 1320 1321 DPRINTF(EthernetIntr, "clearing interrupt\n"); 1322 intrClear(); 1323} 1324 1325bool 1326NSGigE::cpuIntrPending() const 1327{ return cpuPendingIntr; } 1328 1329void 1330NSGigE::txReset() 1331{ 1332 1333 DPRINTF(Ethernet, "transmit reset\n"); 1334 1335 CTDD = false; 1336 txEnable = false;; 1337 txFragPtr = 0; 1338 assert(txDescCnt == 0); 1339 txFifo.clear(); 1340 txState = txIdle; 1341 assert(txDmaState == dmaIdle); 1342} 1343 1344void 1345NSGigE::rxReset() 1346{ 1347 DPRINTF(Ethernet, "receive reset\n"); 1348 1349 CRDD = false; 1350 assert(rxPktBytes == 0); 1351 rxEnable = false; 1352 rxFragPtr = 0; 1353 assert(rxDescCnt == 0); 1354 assert(rxDmaState == dmaIdle); 1355 rxFifo.clear(); 1356 rxState = rxIdle; 1357} 1358 1359void 1360NSGigE::regsReset() 1361{ 1362 memset(®s, 0, sizeof(regs)); 1363 regs.config = CFGR_LNKSTS; 1364 regs.mear = 0x22; 1365 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1366 // fill threshold to 32 bytes 1367 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1368 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1369 regs.mibc = MIBC_FRZ; 1370 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1371 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1372 1373 extstsEnable = false; 1374 acceptBroadcast = false; 1375 acceptMulticast = false; 1376 acceptUnicast = false; 1377 acceptPerfect = false; 1378 acceptArp = false; 1379} 1380 1381void 1382NSGigE::rxDmaReadCopy() 1383{ 1384 assert(rxDmaState == dmaReading); 1385 1386 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1387 rxDmaState = dmaIdle; 1388 1389 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1390 rxDmaAddr, rxDmaLen); 1391 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1392} 1393 1394bool 1395NSGigE::doRxDmaRead() 1396{ 1397 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1398 rxDmaState = dmaReading; 1399 1400 if (dmaInterface && !rxDmaFree) { 1401 if (dmaInterface->busy()) 1402 rxDmaState = dmaReadWaiting; 1403 else 1404 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1405 &rxDmaReadEvent, true); 1406 return true; 1407 } 1408 1409 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1410 rxDmaReadCopy(); 1411 return false; 1412 } 1413 1414 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1415 Tick start = curTick + dmaReadDelay + factor; 1416 rxDmaReadEvent.schedule(start); 1417 return true; 1418} 1419 1420void 1421NSGigE::rxDmaReadDone() 1422{ 1423 assert(rxDmaState == dmaReading); 1424 rxDmaReadCopy(); 1425 1426 // If the transmit state machine has a pending DMA, let it go first 1427 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1428 txKick(); 1429 1430 rxKick(); 1431} 1432 1433void 1434NSGigE::rxDmaWriteCopy() 1435{ 1436 assert(rxDmaState == dmaWriting); 1437 1438 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1439 rxDmaState = dmaIdle; 1440 1441 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1442 rxDmaAddr, rxDmaLen); 1443 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1444} 1445 1446bool 1447NSGigE::doRxDmaWrite() 1448{ 1449 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1450 rxDmaState = dmaWriting; 1451 1452 if (dmaInterface && !rxDmaFree) { 1453 if (dmaInterface->busy()) 1454 rxDmaState = dmaWriteWaiting; 1455 else 1456 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1457 &rxDmaWriteEvent, true); 1458 return true; 1459 } 1460 1461 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1462 rxDmaWriteCopy(); 1463 return false; 1464 } 1465 1466 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1467 Tick start = curTick + dmaWriteDelay + factor; 1468 rxDmaWriteEvent.schedule(start); 1469 return true; 1470} 1471 1472void 1473NSGigE::rxDmaWriteDone() 1474{ 1475 assert(rxDmaState == dmaWriting); 1476 rxDmaWriteCopy(); 1477 1478 // If the transmit state machine has a pending DMA, let it go first 1479 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1480 txKick(); 1481 1482 rxKick(); 1483} 1484 1485void 1486NSGigE::rxKick() 1487{ 1488 DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", 1489 NsRxStateStrings[rxState], rxFifo.size()); 1490 1491 next: 1492 if (clock) { 1493 if (rxKickTick > curTick) { 1494 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1495 rxKickTick); 1496 1497 goto exit; 1498 } 1499 1500 // Go to the next state machine clock tick. 1501 rxKickTick = curTick + cycles(1); 1502 } 1503 1504 switch(rxDmaState) { 1505 case dmaReadWaiting: 1506 if (doRxDmaRead()) 1507 goto exit; 1508 break; 1509 case dmaWriteWaiting: 1510 if (doRxDmaWrite()) 1511 goto exit; 1512 break; 1513 default: 1514 break; 1515 } 1516 1517 // see state machine from spec for details 1518 // the way this works is, if you finish work on one state and can 1519 // go directly to another, you do that through jumping to the 1520 // label "next". however, if you have intermediate work, like DMA 1521 // so that you can't go to the next state yet, you go to exit and 1522 // exit the loop. however, when the DMA is done it will trigger 1523 // an event and come back to this loop. 1524 switch (rxState) { 1525 case rxIdle: 1526 if (!rxEnable) { 1527 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1528 goto exit; 1529 } 1530 1531 if (CRDD) { 1532 rxState = rxDescRefr; 1533 1534 rxDmaAddr = regs.rxdp & 0x3fffffff; 1535 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1536 rxDmaLen = sizeof(rxDescCache.link); 1537 rxDmaFree = dmaDescFree; 1538 1539 descDmaReads++; 1540 descDmaRdBytes += rxDmaLen; 1541 1542 if (doRxDmaRead()) 1543 goto exit; 1544 } else { 1545 rxState = rxDescRead; 1546 1547 rxDmaAddr = regs.rxdp & 0x3fffffff; 1548 rxDmaData = &rxDescCache; 1549 rxDmaLen = sizeof(ns_desc); 1550 rxDmaFree = dmaDescFree; 1551 1552 descDmaReads++; 1553 descDmaRdBytes += rxDmaLen; 1554 1555 if (doRxDmaRead()) 1556 goto exit; 1557 } 1558 break; 1559 1560 case rxDescRefr: 1561 if (rxDmaState != dmaIdle) 1562 goto exit; 1563 1564 rxState = rxAdvance; 1565 break; 1566 1567 case rxDescRead: 1568 if (rxDmaState != dmaIdle) 1569 goto exit; 1570 1571 DPRINTF(EthernetDesc, "rxDescCache: addr=%08x read descriptor\n", 1572 regs.rxdp & 0x3fffffff); 1573 DPRINTF(EthernetDesc, 1574 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1575 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1576 rxDescCache.extsts); 1577 1578 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1579 devIntrPost(ISR_RXIDLE); 1580 rxState = rxIdle; 1581 goto exit; 1582 } else { 1583 rxState = rxFifoBlock; 1584 rxFragPtr = rxDescCache.bufptr; 1585 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1586 } 1587 break; 1588 1589 case rxFifoBlock: 1590 if (!rxPacket) { 1591 /** 1592 * @todo in reality, we should be able to start processing 1593 * the packet as it arrives, and not have to wait for the 1594 * full packet ot be in the receive fifo. 1595 */ 1596 if (rxFifo.empty()) 1597 goto exit; 1598 1599 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1600 1601 // If we don't have a packet, grab a new one from the fifo. 1602 rxPacket = rxFifo.front(); 1603 rxPktBytes = rxPacket->length; 1604 rxPacketBufPtr = rxPacket->data; 1605 1606#if TRACING_ON 1607 if (DTRACE(Ethernet)) { 1608 IpPtr ip(rxPacket); 1609 if (ip) { 1610 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1611 TcpPtr tcp(ip); 1612 if (tcp) { 1613 DPRINTF(Ethernet, 1614 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1615 tcp->sport(), tcp->dport(), tcp->seq(), 1616 tcp->ack()); 1617 } 1618 } 1619 } 1620#endif 1621 1622 // sanity check - i think the driver behaves like this 1623 assert(rxDescCnt >= rxPktBytes); 1624 rxFifo.pop(); 1625 } 1626 1627 1628 // dont' need the && rxDescCnt > 0 if driver sanity check 1629 // above holds 1630 if (rxPktBytes > 0) { 1631 rxState = rxFragWrite; 1632 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1633 // check holds 1634 rxXferLen = rxPktBytes; 1635 1636 rxDmaAddr = rxFragPtr & 0x3fffffff; 1637 rxDmaData = rxPacketBufPtr; 1638 rxDmaLen = rxXferLen; 1639 rxDmaFree = dmaDataFree; 1640 1641 if (doRxDmaWrite()) 1642 goto exit; 1643 1644 } else { 1645 rxState = rxDescWrite; 1646 1647 //if (rxPktBytes == 0) { /* packet is done */ 1648 assert(rxPktBytes == 0); 1649 DPRINTF(EthernetSM, "done with receiving packet\n"); 1650 1651 rxDescCache.cmdsts |= CMDSTS_OWN; 1652 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1653 rxDescCache.cmdsts |= CMDSTS_OK; 1654 rxDescCache.cmdsts &= 0xffff0000; 1655 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1656 1657#if 0 1658 /* 1659 * all the driver uses these are for its own stats keeping 1660 * which we don't care about, aren't necessary for 1661 * functionality and doing this would just slow us down. 1662 * if they end up using this in a later version for 1663 * functional purposes, just undef 1664 */ 1665 if (rxFilterEnable) { 1666 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1667 const EthAddr &dst = rxFifoFront()->dst(); 1668 if (dst->unicast()) 1669 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1670 if (dst->multicast()) 1671 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1672 if (dst->broadcast()) 1673 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1674 } 1675#endif 1676 1677 IpPtr ip(rxPacket); 1678 if (extstsEnable && ip) { 1679 rxDescCache.extsts |= EXTSTS_IPPKT; 1680 rxIpChecksums++; 1681 if (cksum(ip) != 0) { 1682 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1683 rxDescCache.extsts |= EXTSTS_IPERR; 1684 } 1685 TcpPtr tcp(ip); 1686 UdpPtr udp(ip); 1687 if (tcp) { 1688 rxDescCache.extsts |= EXTSTS_TCPPKT; 1689 rxTcpChecksums++; 1690 if (cksum(tcp) != 0) { 1691 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1692 rxDescCache.extsts |= EXTSTS_TCPERR; 1693 1694 } 1695 } else if (udp) { 1696 rxDescCache.extsts |= EXTSTS_UDPPKT; 1697 rxUdpChecksums++; 1698 if (cksum(udp) != 0) { 1699 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1700 rxDescCache.extsts |= EXTSTS_UDPERR; 1701 } 1702 } 1703 } 1704 rxPacket = 0; 1705 1706 /* 1707 * the driver seems to always receive into desc buffers 1708 * of size 1514, so you never have a pkt that is split 1709 * into multiple descriptors on the receive side, so 1710 * i don't implement that case, hence the assert above. 1711 */ 1712 1713 DPRINTF(EthernetDesc, 1714 "rxDescCache: addr=%08x writeback cmdsts extsts\n", 1715 regs.rxdp & 0x3fffffff); 1716 DPRINTF(EthernetDesc, 1717 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1718 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1719 rxDescCache.extsts); 1720 1721 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1722 rxDmaData = &(rxDescCache.cmdsts); 1723 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1724 rxDmaFree = dmaDescFree; 1725 1726 descDmaWrites++; 1727 descDmaWrBytes += rxDmaLen; 1728 1729 if (doRxDmaWrite()) 1730 goto exit; 1731 } 1732 break; 1733 1734 case rxFragWrite: 1735 if (rxDmaState != dmaIdle) 1736 goto exit; 1737 1738 rxPacketBufPtr += rxXferLen; 1739 rxFragPtr += rxXferLen; 1740 rxPktBytes -= rxXferLen; 1741 1742 rxState = rxFifoBlock; 1743 break; 1744 1745 case rxDescWrite: 1746 if (rxDmaState != dmaIdle) 1747 goto exit; 1748 1749 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1750 1751 assert(rxPacket == 0); 1752 devIntrPost(ISR_RXOK); 1753 1754 if (rxDescCache.cmdsts & CMDSTS_INTR) 1755 devIntrPost(ISR_RXDESC); 1756 1757 if (!rxEnable) { 1758 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1759 rxState = rxIdle; 1760 goto exit; 1761 } else 1762 rxState = rxAdvance; 1763 break; 1764 1765 case rxAdvance: 1766 if (rxDescCache.link == 0) { 1767 devIntrPost(ISR_RXIDLE); 1768 rxState = rxIdle; 1769 CRDD = true; 1770 goto exit; 1771 } else { 1772 rxState = rxDescRead; 1773 regs.rxdp = rxDescCache.link; 1774 CRDD = false; 1775 1776 rxDmaAddr = regs.rxdp & 0x3fffffff; 1777 rxDmaData = &rxDescCache; 1778 rxDmaLen = sizeof(ns_desc); 1779 rxDmaFree = dmaDescFree; 1780 1781 if (doRxDmaRead()) 1782 goto exit; 1783 } 1784 break; 1785 1786 default: 1787 panic("Invalid rxState!"); 1788 } 1789 1790 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1791 NsRxStateStrings[rxState]); 1792 goto next; 1793 1794 exit: 1795 /** 1796 * @todo do we want to schedule a future kick? 1797 */ 1798 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1799 NsRxStateStrings[rxState]); 1800 1801 if (clock && !rxKickEvent.scheduled()) 1802 rxKickEvent.schedule(rxKickTick); 1803} 1804 1805void 1806NSGigE::transmit() 1807{ 1808 if (txFifo.empty()) { 1809 DPRINTF(Ethernet, "nothing to transmit\n"); 1810 return; 1811 } 1812 1813 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1814 txFifo.size()); 1815 if (interface->sendPacket(txFifo.front())) { 1816#if TRACING_ON 1817 if (DTRACE(Ethernet)) { 1818 IpPtr ip(txFifo.front()); 1819 if (ip) { 1820 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1821 TcpPtr tcp(ip); 1822 if (tcp) { 1823 DPRINTF(Ethernet, 1824 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1825 tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack()); 1826 } 1827 } 1828 } 1829#endif 1830 1831 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1832 txBytes += txFifo.front()->length; 1833 txPackets++; 1834 1835 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1836 txFifo.avail()); 1837 txFifo.pop(); 1838 1839 /* 1840 * normally do a writeback of the descriptor here, and ONLY 1841 * after that is done, send this interrupt. but since our 1842 * stuff never actually fails, just do this interrupt here, 1843 * otherwise the code has to stray from this nice format. 1844 * besides, it's functionally the same. 1845 */ 1846 devIntrPost(ISR_TXOK); 1847 } 1848 1849 if (!txFifo.empty() && !txEvent.scheduled()) { 1850 DPRINTF(Ethernet, "reschedule transmit\n"); 1851 txEvent.schedule(curTick + retryTime); 1852 } 1853} 1854 1855void 1856NSGigE::txDmaReadCopy() 1857{ 1858 assert(txDmaState == dmaReading); 1859 1860 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1861 txDmaState = dmaIdle; 1862 1863 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1864 txDmaAddr, txDmaLen); 1865 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1866} 1867 1868bool 1869NSGigE::doTxDmaRead() 1870{ 1871 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1872 txDmaState = dmaReading; 1873 1874 if (dmaInterface && !txDmaFree) { 1875 if (dmaInterface->busy()) 1876 txDmaState = dmaReadWaiting; 1877 else 1878 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1879 &txDmaReadEvent, true); 1880 return true; 1881 } 1882 1883 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1884 txDmaReadCopy(); 1885 return false; 1886 } 1887 1888 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1889 Tick start = curTick + dmaReadDelay + factor; 1890 txDmaReadEvent.schedule(start); 1891 return true; 1892} 1893 1894void 1895NSGigE::txDmaReadDone() 1896{ 1897 assert(txDmaState == dmaReading); 1898 txDmaReadCopy(); 1899 1900 // If the receive state machine has a pending DMA, let it go first 1901 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1902 rxKick(); 1903 1904 txKick(); 1905} 1906 1907void 1908NSGigE::txDmaWriteCopy() 1909{ 1910 assert(txDmaState == dmaWriting); 1911 1912 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1913 txDmaState = dmaIdle; 1914 1915 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1916 txDmaAddr, txDmaLen); 1917 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1918} 1919 1920bool 1921NSGigE::doTxDmaWrite() 1922{ 1923 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1924 txDmaState = dmaWriting; 1925 1926 if (dmaInterface && !txDmaFree) { 1927 if (dmaInterface->busy()) 1928 txDmaState = dmaWriteWaiting; 1929 else 1930 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1931 &txDmaWriteEvent, true); 1932 return true; 1933 } 1934 1935 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1936 txDmaWriteCopy(); 1937 return false; 1938 } 1939 1940 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1941 Tick start = curTick + dmaWriteDelay + factor; 1942 txDmaWriteEvent.schedule(start); 1943 return true; 1944} 1945 1946void 1947NSGigE::txDmaWriteDone() 1948{ 1949 assert(txDmaState == dmaWriting); 1950 txDmaWriteCopy(); 1951 1952 // If the receive state machine has a pending DMA, let it go first 1953 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1954 rxKick(); 1955 1956 txKick(); 1957} 1958 1959void 1960NSGigE::txKick() 1961{ 1962 DPRINTF(EthernetSM, "transmit kick txState=%s\n", 1963 NsTxStateStrings[txState]); 1964 1965 next: 1966 if (clock) { 1967 if (txKickTick > curTick) { 1968 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1969 txKickTick); 1970 goto exit; 1971 } 1972 1973 // Go to the next state machine clock tick. 1974 txKickTick = curTick + cycles(1); 1975 } 1976 1977 switch(txDmaState) { 1978 case dmaReadWaiting: 1979 if (doTxDmaRead()) 1980 goto exit; 1981 break; 1982 case dmaWriteWaiting: 1983 if (doTxDmaWrite()) 1984 goto exit; 1985 break; 1986 default: 1987 break; 1988 } 1989 1990 switch (txState) { 1991 case txIdle: 1992 if (!txEnable) { 1993 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1994 goto exit; 1995 } 1996 1997 if (CTDD) { 1998 txState = txDescRefr; 1999 2000 txDmaAddr = regs.txdp & 0x3fffffff; 2001 txDmaData = &txDescCache + offsetof(ns_desc, link); 2002 txDmaLen = sizeof(txDescCache.link); 2003 txDmaFree = dmaDescFree; 2004 2005 descDmaReads++; 2006 descDmaRdBytes += txDmaLen; 2007 2008 if (doTxDmaRead()) 2009 goto exit; 2010 2011 } else { 2012 txState = txDescRead; 2013 2014 txDmaAddr = regs.txdp & 0x3fffffff; 2015 txDmaData = &txDescCache; 2016 txDmaLen = sizeof(ns_desc); 2017 txDmaFree = dmaDescFree; 2018 2019 descDmaReads++; 2020 descDmaRdBytes += txDmaLen; 2021 2022 if (doTxDmaRead()) 2023 goto exit; 2024 } 2025 break; 2026 2027 case txDescRefr: 2028 if (txDmaState != dmaIdle) 2029 goto exit; 2030 2031 txState = txAdvance; 2032 break; 2033 2034 case txDescRead: 2035 if (txDmaState != dmaIdle) 2036 goto exit; 2037 2038 DPRINTF(EthernetDesc, "txDescCache: addr=%08x read descriptor\n", 2039 regs.txdp & 0x3fffffff); 2040 DPRINTF(EthernetDesc, 2041 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 2042 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 2043 txDescCache.extsts); 2044 2045 if (txDescCache.cmdsts & CMDSTS_OWN) { 2046 txState = txFifoBlock; 2047 txFragPtr = txDescCache.bufptr; 2048 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 2049 } else { 2050 devIntrPost(ISR_TXIDLE); 2051 txState = txIdle; 2052 goto exit; 2053 } 2054 break; 2055 2056 case txFifoBlock: 2057 if (!txPacket) { 2058 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2059 txPacket = new PacketData(16384); 2060 txPacketBufPtr = txPacket->data; 2061 } 2062 2063 if (txDescCnt == 0) { 2064 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 2065 if (txDescCache.cmdsts & CMDSTS_MORE) { 2066 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2067 txState = txDescWrite; 2068 2069 txDescCache.cmdsts &= ~CMDSTS_OWN; 2070 2071 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2072 txDmaAddr &= 0x3fffffff; 2073 txDmaData = &(txDescCache.cmdsts); 2074 txDmaLen = sizeof(txDescCache.cmdsts); 2075 txDmaFree = dmaDescFree; 2076 2077 if (doTxDmaWrite()) 2078 goto exit; 2079 2080 } else { /* this packet is totally done */ 2081 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2082 /* deal with the the packet that just finished */ 2083 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2084 IpPtr ip(txPacket); 2085 if (txDescCache.extsts & EXTSTS_UDPPKT) { 2086 UdpPtr udp(ip); 2087 udp->sum(0); 2088 udp->sum(cksum(udp)); 2089 txUdpChecksums++; 2090 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 2091 TcpPtr tcp(ip); 2092 tcp->sum(0); 2093 tcp->sum(cksum(tcp)); 2094 txTcpChecksums++; 2095 } 2096 if (txDescCache.extsts & EXTSTS_IPPKT) { 2097 ip->sum(0); 2098 ip->sum(cksum(ip)); 2099 txIpChecksums++; 2100 } 2101 } 2102 2103 txPacket->length = txPacketBufPtr - txPacket->data; 2104 // this is just because the receive can't handle a 2105 // packet bigger want to make sure 2106 assert(txPacket->length <= 1514); 2107#ifndef NDEBUG 2108 bool success = 2109#endif 2110 txFifo.push(txPacket); 2111 assert(success); 2112 2113 /* 2114 * this following section is not tqo spec, but 2115 * functionally shouldn't be any different. normally, 2116 * the chip will wait til the transmit has occurred 2117 * before writing back the descriptor because it has 2118 * to wait to see that it was successfully transmitted 2119 * to decide whether to set CMDSTS_OK or not. 2120 * however, in the simulator since it is always 2121 * successfully transmitted, and writing it exactly to 2122 * spec would complicate the code, we just do it here 2123 */ 2124 2125 txDescCache.cmdsts &= ~CMDSTS_OWN; 2126 txDescCache.cmdsts |= CMDSTS_OK; 2127 2128 DPRINTF(EthernetDesc, 2129 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2130 txDescCache.cmdsts, txDescCache.extsts); 2131 2132 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2133 txDmaAddr &= 0x3fffffff; 2134 txDmaData = &(txDescCache.cmdsts); 2135 txDmaLen = sizeof(txDescCache.cmdsts) + 2136 sizeof(txDescCache.extsts); 2137 txDmaFree = dmaDescFree; 2138 2139 descDmaWrites++; 2140 descDmaWrBytes += txDmaLen; 2141 2142 transmit(); 2143 txPacket = 0; 2144 2145 if (!txEnable) { 2146 DPRINTF(EthernetSM, "halting TX state machine\n"); 2147 txState = txIdle; 2148 goto exit; 2149 } else 2150 txState = txAdvance; 2151 2152 if (doTxDmaWrite()) 2153 goto exit; 2154 } 2155 } else { 2156 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2157 if (!txFifo.full()) { 2158 txState = txFragRead; 2159 2160 /* 2161 * The number of bytes transferred is either whatever 2162 * is left in the descriptor (txDescCnt), or if there 2163 * is not enough room in the fifo, just whatever room 2164 * is left in the fifo 2165 */ 2166 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2167 2168 txDmaAddr = txFragPtr & 0x3fffffff; 2169 txDmaData = txPacketBufPtr; 2170 txDmaLen = txXferLen; 2171 txDmaFree = dmaDataFree; 2172 2173 if (doTxDmaRead()) 2174 goto exit; 2175 } else { 2176 txState = txFifoBlock; 2177 transmit(); 2178 2179 goto exit; 2180 } 2181 2182 } 2183 break; 2184 2185 case txFragRead: 2186 if (txDmaState != dmaIdle) 2187 goto exit; 2188 2189 txPacketBufPtr += txXferLen; 2190 txFragPtr += txXferLen; 2191 txDescCnt -= txXferLen; 2192 txFifo.reserve(txXferLen); 2193 2194 txState = txFifoBlock; 2195 break; 2196 2197 case txDescWrite: 2198 if (txDmaState != dmaIdle) 2199 goto exit; 2200 2201 if (txDescCache.cmdsts & CMDSTS_INTR) 2202 devIntrPost(ISR_TXDESC); 2203 2204 if (!txEnable) { 2205 DPRINTF(EthernetSM, "halting TX state machine\n"); 2206 txState = txIdle; 2207 goto exit; 2208 } else 2209 txState = txAdvance; 2210 break; 2211 2212 case txAdvance: 2213 if (txDescCache.link == 0) { 2214 devIntrPost(ISR_TXIDLE); 2215 txState = txIdle; 2216 goto exit; 2217 } else { 2218 txState = txDescRead; 2219 regs.txdp = txDescCache.link; 2220 CTDD = false; 2221 2222 txDmaAddr = txDescCache.link & 0x3fffffff; 2223 txDmaData = &txDescCache; 2224 txDmaLen = sizeof(ns_desc); 2225 txDmaFree = dmaDescFree; 2226 2227 if (doTxDmaRead()) 2228 goto exit; 2229 } 2230 break; 2231 2232 default: 2233 panic("invalid state"); 2234 } 2235 2236 DPRINTF(EthernetSM, "entering next txState=%s\n", 2237 NsTxStateStrings[txState]); 2238 goto next; 2239 2240 exit: 2241 /** 2242 * @todo do we want to schedule a future kick? 2243 */ 2244 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2245 NsTxStateStrings[txState]); 2246 2247 if (clock && !txKickEvent.scheduled()) 2248 txKickEvent.schedule(txKickTick); 2249} 2250 2251void 2252NSGigE::transferDone() 2253{ 2254 if (txFifo.empty()) { 2255 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2256 return; 2257 } 2258 2259 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2260 2261 if (txEvent.scheduled()) 2262 txEvent.reschedule(curTick + cycles(1)); 2263 else 2264 txEvent.schedule(curTick + cycles(1)); 2265} 2266 2267bool 2268NSGigE::rxFilter(const PacketPtr &packet) 2269{ 2270 EthPtr eth = packet; 2271 bool drop = true; 2272 string type; 2273 2274 const EthAddr &dst = eth->dst(); 2275 if (dst.unicast()) { 2276 // If we're accepting all unicast addresses 2277 if (acceptUnicast) 2278 drop = false; 2279 2280 // If we make a perfect match 2281 if (acceptPerfect && dst == rom.perfectMatch) 2282 drop = false; 2283 2284 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2285 drop = false; 2286 2287 } else if (dst.broadcast()) { 2288 // if we're accepting broadcasts 2289 if (acceptBroadcast) 2290 drop = false; 2291 2292 } else if (dst.multicast()) { 2293 // if we're accepting all multicasts 2294 if (acceptMulticast) 2295 drop = false; 2296 2297 } 2298 2299 if (drop) { 2300 DPRINTF(Ethernet, "rxFilter drop\n"); 2301 DDUMP(EthernetData, packet->data, packet->length); 2302 } 2303 2304 return drop; 2305} 2306 2307bool 2308NSGigE::recvPacket(PacketPtr packet) 2309{ 2310 rxBytes += packet->length; 2311 rxPackets++; 2312 2313 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2314 rxFifo.avail()); 2315 2316 if (!rxEnable) { 2317 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2318 interface->recvDone(); 2319 return true; 2320 } 2321 2322 if (rxFilterEnable && rxFilter(packet)) { 2323 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2324 interface->recvDone(); 2325 return true; 2326 } 2327 2328 if (rxFifo.avail() < packet->length) { 2329#if TRACING_ON 2330 IpPtr ip(packet); 2331 TcpPtr tcp(ip); 2332 if (ip) { 2333 DPRINTF(Ethernet, 2334 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2335 ip->id()); 2336 if (tcp) { 2337 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2338 } 2339 } 2340#endif 2341 droppedPackets++; 2342 devIntrPost(ISR_RXORN); 2343 return false; 2344 } 2345 2346 rxFifo.push(packet); 2347 interface->recvDone(); 2348 2349 rxKick(); 2350 return true; 2351} 2352 2353//===================================================================== 2354// 2355// 2356void 2357NSGigE::serialize(ostream &os) 2358{ 2359 // Serialize the PciDev base class 2360 PciDev::serialize(os); 2361 2362 /* 2363 * Finalize any DMA events now. 2364 */ 2365 if (rxDmaReadEvent.scheduled()) 2366 rxDmaReadCopy(); 2367 if (rxDmaWriteEvent.scheduled()) 2368 rxDmaWriteCopy(); 2369 if (txDmaReadEvent.scheduled()) 2370 txDmaReadCopy(); 2371 if (txDmaWriteEvent.scheduled()) 2372 txDmaWriteCopy(); 2373 2374 /* 2375 * Serialize the device registers 2376 */ 2377 SERIALIZE_SCALAR(regs.command); 2378 SERIALIZE_SCALAR(regs.config); 2379 SERIALIZE_SCALAR(regs.mear); 2380 SERIALIZE_SCALAR(regs.ptscr); 2381 SERIALIZE_SCALAR(regs.isr); 2382 SERIALIZE_SCALAR(regs.imr); 2383 SERIALIZE_SCALAR(regs.ier); 2384 SERIALIZE_SCALAR(regs.ihr); 2385 SERIALIZE_SCALAR(regs.txdp); 2386 SERIALIZE_SCALAR(regs.txdp_hi); 2387 SERIALIZE_SCALAR(regs.txcfg); 2388 SERIALIZE_SCALAR(regs.gpior); 2389 SERIALIZE_SCALAR(regs.rxdp); 2390 SERIALIZE_SCALAR(regs.rxdp_hi); 2391 SERIALIZE_SCALAR(regs.rxcfg); 2392 SERIALIZE_SCALAR(regs.pqcr); 2393 SERIALIZE_SCALAR(regs.wcsr); 2394 SERIALIZE_SCALAR(regs.pcr); 2395 SERIALIZE_SCALAR(regs.rfcr); 2396 SERIALIZE_SCALAR(regs.rfdr); 2397 SERIALIZE_SCALAR(regs.srr); 2398 SERIALIZE_SCALAR(regs.mibc); 2399 SERIALIZE_SCALAR(regs.vrcr); 2400 SERIALIZE_SCALAR(regs.vtcr); 2401 SERIALIZE_SCALAR(regs.vdr); 2402 SERIALIZE_SCALAR(regs.ccsr); 2403 SERIALIZE_SCALAR(regs.tbicr); 2404 SERIALIZE_SCALAR(regs.tbisr); 2405 SERIALIZE_SCALAR(regs.tanar); 2406 SERIALIZE_SCALAR(regs.tanlpar); 2407 SERIALIZE_SCALAR(regs.taner); 2408 SERIALIZE_SCALAR(regs.tesr); 2409 2410 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2411 2412 SERIALIZE_SCALAR(ioEnable); 2413 2414 /* 2415 * Serialize the data Fifos 2416 */ 2417 rxFifo.serialize("rxFifo", os); 2418 txFifo.serialize("txFifo", os); 2419 2420 /* 2421 * Serialize the various helper variables 2422 */ 2423 bool txPacketExists = txPacket; 2424 SERIALIZE_SCALAR(txPacketExists); 2425 if (txPacketExists) { 2426 txPacket->length = txPacketBufPtr - txPacket->data; 2427 txPacket->serialize("txPacket", os); 2428 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2429 SERIALIZE_SCALAR(txPktBufPtr); 2430 } 2431 2432 bool rxPacketExists = rxPacket; 2433 SERIALIZE_SCALAR(rxPacketExists); 2434 if (rxPacketExists) { 2435 rxPacket->serialize("rxPacket", os); 2436 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2437 SERIALIZE_SCALAR(rxPktBufPtr); 2438 } 2439 2440 SERIALIZE_SCALAR(txXferLen); 2441 SERIALIZE_SCALAR(rxXferLen); 2442 2443 /* 2444 * Serialize DescCaches 2445 */ 2446 SERIALIZE_SCALAR(txDescCache.link); 2447 SERIALIZE_SCALAR(txDescCache.bufptr); 2448 SERIALIZE_SCALAR(txDescCache.cmdsts); 2449 SERIALIZE_SCALAR(txDescCache.extsts); 2450 SERIALIZE_SCALAR(rxDescCache.link); 2451 SERIALIZE_SCALAR(rxDescCache.bufptr); 2452 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2453 SERIALIZE_SCALAR(rxDescCache.extsts); 2454 SERIALIZE_SCALAR(extstsEnable); 2455 2456 /* 2457 * Serialize tx state machine 2458 */ 2459 int txState = this->txState; 2460 SERIALIZE_SCALAR(txState); 2461 SERIALIZE_SCALAR(txEnable); 2462 SERIALIZE_SCALAR(CTDD); 2463 SERIALIZE_SCALAR(txFragPtr); 2464 SERIALIZE_SCALAR(txDescCnt); 2465 int txDmaState = this->txDmaState; 2466 SERIALIZE_SCALAR(txDmaState); 2467 SERIALIZE_SCALAR(txKickTick); 2468 2469 /* 2470 * Serialize rx state machine 2471 */ 2472 int rxState = this->rxState; 2473 SERIALIZE_SCALAR(rxState); 2474 SERIALIZE_SCALAR(rxEnable); 2475 SERIALIZE_SCALAR(CRDD); 2476 SERIALIZE_SCALAR(rxPktBytes); 2477 SERIALIZE_SCALAR(rxFragPtr); 2478 SERIALIZE_SCALAR(rxDescCnt); 2479 int rxDmaState = this->rxDmaState; 2480 SERIALIZE_SCALAR(rxDmaState); 2481 SERIALIZE_SCALAR(rxKickTick); 2482 2483 /* 2484 * If there's a pending transmit, store the time so we can 2485 * reschedule it later 2486 */ 2487 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2488 SERIALIZE_SCALAR(transmitTick); 2489 2490 /* 2491 * receive address filter settings 2492 */ 2493 SERIALIZE_SCALAR(rxFilterEnable); 2494 SERIALIZE_SCALAR(acceptBroadcast); 2495 SERIALIZE_SCALAR(acceptMulticast); 2496 SERIALIZE_SCALAR(acceptUnicast); 2497 SERIALIZE_SCALAR(acceptPerfect); 2498 SERIALIZE_SCALAR(acceptArp); 2499 2500 /* 2501 * Keep track of pending interrupt status. 2502 */ 2503 SERIALIZE_SCALAR(intrTick); 2504 SERIALIZE_SCALAR(cpuPendingIntr); 2505 Tick intrEventTick = 0; 2506 if (intrEvent) 2507 intrEventTick = intrEvent->when(); 2508 SERIALIZE_SCALAR(intrEventTick); 2509 2510} 2511 2512void 2513NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2514{ 2515 // Unserialize the PciDev base class 2516 PciDev::unserialize(cp, section); 2517 2518 UNSERIALIZE_SCALAR(regs.command); 2519 UNSERIALIZE_SCALAR(regs.config); 2520 UNSERIALIZE_SCALAR(regs.mear); 2521 UNSERIALIZE_SCALAR(regs.ptscr); 2522 UNSERIALIZE_SCALAR(regs.isr); 2523 UNSERIALIZE_SCALAR(regs.imr); 2524 UNSERIALIZE_SCALAR(regs.ier); 2525 UNSERIALIZE_SCALAR(regs.ihr); 2526 UNSERIALIZE_SCALAR(regs.txdp); 2527 UNSERIALIZE_SCALAR(regs.txdp_hi); 2528 UNSERIALIZE_SCALAR(regs.txcfg); 2529 UNSERIALIZE_SCALAR(regs.gpior); 2530 UNSERIALIZE_SCALAR(regs.rxdp); 2531 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2532 UNSERIALIZE_SCALAR(regs.rxcfg); 2533 UNSERIALIZE_SCALAR(regs.pqcr); 2534 UNSERIALIZE_SCALAR(regs.wcsr); 2535 UNSERIALIZE_SCALAR(regs.pcr); 2536 UNSERIALIZE_SCALAR(regs.rfcr); 2537 UNSERIALIZE_SCALAR(regs.rfdr); 2538 UNSERIALIZE_SCALAR(regs.srr); 2539 UNSERIALIZE_SCALAR(regs.mibc); 2540 UNSERIALIZE_SCALAR(regs.vrcr); 2541 UNSERIALIZE_SCALAR(regs.vtcr); 2542 UNSERIALIZE_SCALAR(regs.vdr); 2543 UNSERIALIZE_SCALAR(regs.ccsr); 2544 UNSERIALIZE_SCALAR(regs.tbicr); 2545 UNSERIALIZE_SCALAR(regs.tbisr); 2546 UNSERIALIZE_SCALAR(regs.tanar); 2547 UNSERIALIZE_SCALAR(regs.tanlpar); 2548 UNSERIALIZE_SCALAR(regs.taner); 2549 UNSERIALIZE_SCALAR(regs.tesr); 2550 2551 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2552 2553 UNSERIALIZE_SCALAR(ioEnable); 2554 2555 /* 2556 * unserialize the data fifos 2557 */ 2558 rxFifo.unserialize("rxFifo", cp, section); 2559 txFifo.unserialize("txFifo", cp, section); 2560 2561 /* 2562 * unserialize the various helper variables 2563 */ 2564 bool txPacketExists; 2565 UNSERIALIZE_SCALAR(txPacketExists); 2566 if (txPacketExists) { 2567 txPacket = new PacketData(16384); 2568 txPacket->unserialize("txPacket", cp, section); 2569 uint32_t txPktBufPtr; 2570 UNSERIALIZE_SCALAR(txPktBufPtr); 2571 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2572 } else 2573 txPacket = 0; 2574 2575 bool rxPacketExists; 2576 UNSERIALIZE_SCALAR(rxPacketExists); 2577 rxPacket = 0; 2578 if (rxPacketExists) { 2579 rxPacket = new PacketData(16384); 2580 rxPacket->unserialize("rxPacket", cp, section); 2581 uint32_t rxPktBufPtr; 2582 UNSERIALIZE_SCALAR(rxPktBufPtr); 2583 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2584 } else 2585 rxPacket = 0; 2586 2587 UNSERIALIZE_SCALAR(txXferLen); 2588 UNSERIALIZE_SCALAR(rxXferLen); 2589 2590 /* 2591 * Unserialize DescCaches 2592 */ 2593 UNSERIALIZE_SCALAR(txDescCache.link); 2594 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2595 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2596 UNSERIALIZE_SCALAR(txDescCache.extsts); 2597 UNSERIALIZE_SCALAR(rxDescCache.link); 2598 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2599 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2600 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2601 UNSERIALIZE_SCALAR(extstsEnable); 2602 2603 /* 2604 * unserialize tx state machine 2605 */ 2606 int txState; 2607 UNSERIALIZE_SCALAR(txState); 2608 this->txState = (TxState) txState; 2609 UNSERIALIZE_SCALAR(txEnable); 2610 UNSERIALIZE_SCALAR(CTDD); 2611 UNSERIALIZE_SCALAR(txFragPtr); 2612 UNSERIALIZE_SCALAR(txDescCnt); 2613 int txDmaState; 2614 UNSERIALIZE_SCALAR(txDmaState); 2615 this->txDmaState = (DmaState) txDmaState; 2616 UNSERIALIZE_SCALAR(txKickTick); 2617 if (txKickTick) 2618 txKickEvent.schedule(txKickTick); 2619 2620 /* 2621 * unserialize rx state machine 2622 */ 2623 int rxState; 2624 UNSERIALIZE_SCALAR(rxState); 2625 this->rxState = (RxState) rxState; 2626 UNSERIALIZE_SCALAR(rxEnable); 2627 UNSERIALIZE_SCALAR(CRDD); 2628 UNSERIALIZE_SCALAR(rxPktBytes); 2629 UNSERIALIZE_SCALAR(rxFragPtr); 2630 UNSERIALIZE_SCALAR(rxDescCnt); 2631 int rxDmaState; 2632 UNSERIALIZE_SCALAR(rxDmaState); 2633 this->rxDmaState = (DmaState) rxDmaState; 2634 UNSERIALIZE_SCALAR(rxKickTick); 2635 if (rxKickTick) 2636 rxKickEvent.schedule(rxKickTick); 2637 2638 /* 2639 * If there's a pending transmit, reschedule it now 2640 */ 2641 Tick transmitTick; 2642 UNSERIALIZE_SCALAR(transmitTick); 2643 if (transmitTick) 2644 txEvent.schedule(curTick + transmitTick); 2645 2646 /* 2647 * unserialize receive address filter settings 2648 */ 2649 UNSERIALIZE_SCALAR(rxFilterEnable); 2650 UNSERIALIZE_SCALAR(acceptBroadcast); 2651 UNSERIALIZE_SCALAR(acceptMulticast); 2652 UNSERIALIZE_SCALAR(acceptUnicast); 2653 UNSERIALIZE_SCALAR(acceptPerfect); 2654 UNSERIALIZE_SCALAR(acceptArp); 2655 2656 /* 2657 * Keep track of pending interrupt status. 2658 */ 2659 UNSERIALIZE_SCALAR(intrTick); 2660 UNSERIALIZE_SCALAR(cpuPendingIntr); 2661 Tick intrEventTick; 2662 UNSERIALIZE_SCALAR(intrEventTick); 2663 if (intrEventTick) { 2664 intrEvent = new IntrEvent(this, true); 2665 intrEvent->schedule(intrEventTick); 2666 } 2667 2668 /* 2669 * re-add addrRanges to bus bridges 2670 */ 2671 if (pioInterface) { 2672 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 2673 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 2674 } 2675} 2676 2677Tick 2678NSGigE::cacheAccess(MemReqPtr &req) 2679{ 2680 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2681 req->paddr, req->paddr - addr); 2682 return curTick + pioLatency; 2683} 2684 2685BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2686 2687 SimObjectParam<EtherInt *> peer; 2688 SimObjectParam<NSGigE *> device; 2689 2690END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2691 2692BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2693 2694 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2695 INIT_PARAM(device, "Ethernet device of this interface") 2696 2697END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2698 2699CREATE_SIM_OBJECT(NSGigEInt) 2700{ 2701 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2702 2703 EtherInt *p = (EtherInt *)peer; 2704 if (p) { 2705 dev_int->setPeer(p); 2706 p->setPeer(dev_int); 2707 } 2708 2709 return dev_int; 2710} 2711 2712REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2713 2714 2715BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2716 2717 Param<Addr> addr; 2718 Param<Tick> clock; 2719 Param<Tick> tx_delay; 2720 Param<Tick> rx_delay; 2721 Param<Tick> intr_delay; 2722 SimObjectParam<MemoryController *> mmu; 2723 SimObjectParam<PhysicalMemory *> physmem; 2724 Param<bool> rx_filter; 2725 Param<string> hardware_address; 2726 SimObjectParam<Bus*> io_bus; 2727 SimObjectParam<Bus*> payload_bus; 2728 SimObjectParam<HierParams *> hier; 2729 Param<Tick> pio_latency; 2730 Param<bool> dma_desc_free; 2731 Param<bool> dma_data_free; 2732 Param<Tick> dma_read_delay; 2733 Param<Tick> dma_write_delay; 2734 Param<Tick> dma_read_factor; 2735 Param<Tick> dma_write_factor; 2736 SimObjectParam<PciConfigAll *> configspace; 2737 SimObjectParam<PciConfigData *> configdata; 2738 SimObjectParam<Platform *> platform; 2739 Param<uint32_t> pci_bus; 2740 Param<uint32_t> pci_dev; 2741 Param<uint32_t> pci_func; 2742 Param<uint32_t> tx_fifo_size; 2743 Param<uint32_t> rx_fifo_size; 2744 Param<uint32_t> m5reg; 2745 Param<bool> dma_no_allocate; 2746 2747END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2748 2749BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2750 2751 INIT_PARAM(addr, "Device Address"), 2752 INIT_PARAM(clock, "State machine processor frequency"), 2753 INIT_PARAM(tx_delay, "Transmit Delay"), 2754 INIT_PARAM(rx_delay, "Receive Delay"), 2755 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2756 INIT_PARAM(mmu, "Memory Controller"), 2757 INIT_PARAM(physmem, "Physical Memory"), 2758 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2759 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2760 "00:99:00:00:00:01"), 2761 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), 2762 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2763 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2764 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2765 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2766 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2767 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2768 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2769 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2770 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2771 INIT_PARAM(configspace, "PCI Configspace"), 2772 INIT_PARAM(configdata, "PCI Config data"), 2773 INIT_PARAM(platform, "Platform"), 2774 INIT_PARAM(pci_bus, "PCI bus"), 2775 INIT_PARAM(pci_dev, "PCI device number"), 2776 INIT_PARAM(pci_func, "PCI function code"), 2777 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2778 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072), 2779 INIT_PARAM(m5reg, "m5 register"), 2780 INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true) 2781 2782END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2783 2784 2785CREATE_SIM_OBJECT(NSGigE) 2786{ 2787 NSGigE::Params *params = new NSGigE::Params; 2788 2789 params->name = getInstanceName(); 2790 params->mmu = mmu; 2791 params->configSpace = configspace; 2792 params->configData = configdata; 2793 params->plat = platform; 2794 params->busNum = pci_bus; 2795 params->deviceNum = pci_dev; 2796 params->functionNum = pci_func; 2797 2798 params->clock = clock; 2799 params->intr_delay = intr_delay; 2800 params->pmem = physmem; 2801 params->tx_delay = tx_delay; 2802 params->rx_delay = rx_delay; 2803 params->hier = hier; 2804 params->header_bus = io_bus; 2805 params->payload_bus = payload_bus; 2806 params->pio_latency = pio_latency; 2807 params->dma_desc_free = dma_desc_free; 2808 params->dma_data_free = dma_data_free; 2809 params->dma_read_delay = dma_read_delay; 2810 params->dma_write_delay = dma_write_delay; 2811 params->dma_read_factor = dma_read_factor; 2812 params->dma_write_factor = dma_write_factor; 2813 params->rx_filter = rx_filter; 2814 params->eaddr = hardware_address; 2815 params->tx_fifo_size = tx_fifo_size; 2816 params->rx_fifo_size = rx_fifo_size; 2817 params->m5reg = m5reg; 2818 params->dma_no_allocate = dma_no_allocate; 2819 return new NSGigE(params); 2820} 2821 2822REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2823