ns_gige.cc revision 3349
17322Sgblack@eecs.umich.edu/* 27322Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 37322Sgblack@eecs.umich.edu * All rights reserved. 47322Sgblack@eecs.umich.edu * 57322Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67322Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77322Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87322Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97322Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107322Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117322Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127322Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137322Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147322Sgblack@eecs.umich.edu * this software without specific prior written permission. 157322Sgblack@eecs.umich.edu * 167322Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177322Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187322Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197322Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207322Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217322Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227322Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237322Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247322Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257322Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267322Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277322Sgblack@eecs.umich.edu * 287322Sgblack@eecs.umich.edu * Authors: Nathan Binkert 297322Sgblack@eecs.umich.edu * Lisa Hsu 307322Sgblack@eecs.umich.edu */ 317322Sgblack@eecs.umich.edu 327322Sgblack@eecs.umich.edu/** @file 337322Sgblack@eecs.umich.edu * Device module for modelling the National Semiconductor 347322Sgblack@eecs.umich.edu * DP83820 ethernet controller. Does not support priority queueing 357322Sgblack@eecs.umich.edu */ 367322Sgblack@eecs.umich.edu#include <deque> 377322Sgblack@eecs.umich.edu#include <string> 387322Sgblack@eecs.umich.edu 397322Sgblack@eecs.umich.edu#include "arch/alpha/ev5.hh" 407376Sgblack@eecs.umich.edu#include "base/inet.hh" 417376Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 427376Sgblack@eecs.umich.edu#include "dev/etherlink.hh" 437376Sgblack@eecs.umich.edu#include "dev/ns_gige.hh" 447376Sgblack@eecs.umich.edu#include "dev/pciconfigall.hh" 457376Sgblack@eecs.umich.edu#include "mem/packet.hh" 467376Sgblack@eecs.umich.edu#include "mem/packet_access.hh" 477376Sgblack@eecs.umich.edu#include "sim/builder.hh" 487376Sgblack@eecs.umich.edu#include "sim/debug.hh" 497376Sgblack@eecs.umich.edu#include "sim/host.hh" 507376Sgblack@eecs.umich.edu#include "sim/stats.hh" 517376Sgblack@eecs.umich.edu#include "sim/system.hh" 527376Sgblack@eecs.umich.edu 537376Sgblack@eecs.umich.educonst char *NsRxStateStrings[] = 547376Sgblack@eecs.umich.edu{ 557376Sgblack@eecs.umich.edu "rxIdle", 567376Sgblack@eecs.umich.edu "rxDescRefr", 577376Sgblack@eecs.umich.edu "rxDescRead", 587376Sgblack@eecs.umich.edu "rxFifoBlock", 597376Sgblack@eecs.umich.edu "rxFragWrite", 607376Sgblack@eecs.umich.edu "rxDescWrite", 617376Sgblack@eecs.umich.edu "rxAdvance" 627376Sgblack@eecs.umich.edu}; 637376Sgblack@eecs.umich.edu 647376Sgblack@eecs.umich.educonst char *NsTxStateStrings[] = 657376Sgblack@eecs.umich.edu{ 667376Sgblack@eecs.umich.edu "txIdle", 677376Sgblack@eecs.umich.edu "txDescRefr", 687376Sgblack@eecs.umich.edu "txDescRead", 697376Sgblack@eecs.umich.edu "txFifoBlock", 707376Sgblack@eecs.umich.edu "txFragRead", 717376Sgblack@eecs.umich.edu "txDescWrite", 727376Sgblack@eecs.umich.edu "txAdvance" 737376Sgblack@eecs.umich.edu}; 747376Sgblack@eecs.umich.edu 757376Sgblack@eecs.umich.educonst char *NsDmaState[] = 767376Sgblack@eecs.umich.edu{ 777376Sgblack@eecs.umich.edu "dmaIdle", 787376Sgblack@eecs.umich.edu "dmaReading", 797376Sgblack@eecs.umich.edu "dmaWriting", 807376Sgblack@eecs.umich.edu "dmaReadWaiting", 817376Sgblack@eecs.umich.edu "dmaWriteWaiting" 827376Sgblack@eecs.umich.edu}; 837376Sgblack@eecs.umich.edu 847376Sgblack@eecs.umich.eduusing namespace std; 857376Sgblack@eecs.umich.eduusing namespace Net; 867376Sgblack@eecs.umich.eduusing namespace TheISA; 877376Sgblack@eecs.umich.edu 887376Sgblack@eecs.umich.edu/////////////////////////////////////////////////////////////////////// 897376Sgblack@eecs.umich.edu// 907376Sgblack@eecs.umich.edu// NSGigE PCI Device 917376Sgblack@eecs.umich.edu// 927376Sgblack@eecs.umich.eduNSGigE::NSGigE(Params *p) 937376Sgblack@eecs.umich.edu : PciDev(p), ioEnable(false), 947376Sgblack@eecs.umich.edu txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 957376Sgblack@eecs.umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 967376Sgblack@eecs.umich.edu txXferLen(0), rxXferLen(0), clock(p->clock), 977376Sgblack@eecs.umich.edu txState(txIdle), txEnable(false), CTDD(false), 987376Sgblack@eecs.umich.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 997376Sgblack@eecs.umich.edu rxEnable(false), CRDD(false), rxPktBytes(0), 1007376Sgblack@eecs.umich.edu rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1017376Sgblack@eecs.umich.edu eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), 1027376Sgblack@eecs.umich.edu txDmaReadEvent(this), txDmaWriteEvent(this), 1037376Sgblack@eecs.umich.edu dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1047376Sgblack@eecs.umich.edu txDelay(p->tx_delay), rxDelay(p->rx_delay), 1057376Sgblack@eecs.umich.edu rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1067376Sgblack@eecs.umich.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1077376Sgblack@eecs.umich.edu acceptMulticast(false), acceptUnicast(false), 1087376Sgblack@eecs.umich.edu acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1097376Sgblack@eecs.umich.edu intrTick(0), cpuPendingIntr(false), 1107376Sgblack@eecs.umich.edu intrEvent(0), interface(0) 1117376Sgblack@eecs.umich.edu{ 1127376Sgblack@eecs.umich.edu 1137376Sgblack@eecs.umich.edu intrDelay = p->intr_delay; 1147376Sgblack@eecs.umich.edu dmaReadDelay = p->dma_read_delay; 1157376Sgblack@eecs.umich.edu dmaWriteDelay = p->dma_write_delay; 1167376Sgblack@eecs.umich.edu dmaReadFactor = p->dma_read_factor; 1177376Sgblack@eecs.umich.edu dmaWriteFactor = p->dma_write_factor; 1187376Sgblack@eecs.umich.edu 1197376Sgblack@eecs.umich.edu regsReset(); 1207376Sgblack@eecs.umich.edu memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1217376Sgblack@eecs.umich.edu 1227376Sgblack@eecs.umich.edu memset(&rxDesc32, 0, sizeof(rxDesc32)); 1237376Sgblack@eecs.umich.edu memset(&txDesc32, 0, sizeof(txDesc32)); 1247376Sgblack@eecs.umich.edu memset(&rxDesc64, 0, sizeof(rxDesc64)); 1257376Sgblack@eecs.umich.edu memset(&txDesc64, 0, sizeof(txDesc64)); 1267376Sgblack@eecs.umich.edu} 1277376Sgblack@eecs.umich.edu 1287376Sgblack@eecs.umich.eduNSGigE::~NSGigE() 1297376Sgblack@eecs.umich.edu{} 1307376Sgblack@eecs.umich.edu 1317376Sgblack@eecs.umich.eduvoid 1327376Sgblack@eecs.umich.eduNSGigE::regStats() 1337376Sgblack@eecs.umich.edu{ 1347376Sgblack@eecs.umich.edu txBytes 1357376Sgblack@eecs.umich.edu .name(name() + ".txBytes") 1367376Sgblack@eecs.umich.edu .desc("Bytes Transmitted") 1377376Sgblack@eecs.umich.edu .prereq(txBytes) 1387376Sgblack@eecs.umich.edu ; 1397376Sgblack@eecs.umich.edu 1407376Sgblack@eecs.umich.edu rxBytes 1417376Sgblack@eecs.umich.edu .name(name() + ".rxBytes") 1427376Sgblack@eecs.umich.edu .desc("Bytes Received") 1437376Sgblack@eecs.umich.edu .prereq(rxBytes) 1447376Sgblack@eecs.umich.edu ; 1457376Sgblack@eecs.umich.edu 1467376Sgblack@eecs.umich.edu txPackets 1477376Sgblack@eecs.umich.edu .name(name() + ".txPackets") 1487376Sgblack@eecs.umich.edu .desc("Number of Packets Transmitted") 1497376Sgblack@eecs.umich.edu .prereq(txBytes) 1507376Sgblack@eecs.umich.edu ; 1517376Sgblack@eecs.umich.edu 1527376Sgblack@eecs.umich.edu rxPackets 1537376Sgblack@eecs.umich.edu .name(name() + ".rxPackets") 1547376Sgblack@eecs.umich.edu .desc("Number of Packets Received") 1557376Sgblack@eecs.umich.edu .prereq(rxBytes) 1567376Sgblack@eecs.umich.edu ; 1577376Sgblack@eecs.umich.edu 1587376Sgblack@eecs.umich.edu txIpChecksums 1597376Sgblack@eecs.umich.edu .name(name() + ".txIpChecksums") 1607376Sgblack@eecs.umich.edu .desc("Number of tx IP Checksums done by device") 1617376Sgblack@eecs.umich.edu .precision(0) 1627376Sgblack@eecs.umich.edu .prereq(txBytes) 1637376Sgblack@eecs.umich.edu ; 1647376Sgblack@eecs.umich.edu 1657376Sgblack@eecs.umich.edu rxIpChecksums 1667376Sgblack@eecs.umich.edu .name(name() + ".rxIpChecksums") 1677376Sgblack@eecs.umich.edu .desc("Number of rx IP Checksums done by device") 1687376Sgblack@eecs.umich.edu .precision(0) 1697376Sgblack@eecs.umich.edu .prereq(rxBytes) 1707376Sgblack@eecs.umich.edu ; 1717376Sgblack@eecs.umich.edu 1727376Sgblack@eecs.umich.edu txTcpChecksums 1737376Sgblack@eecs.umich.edu .name(name() + ".txTcpChecksums") 1747376Sgblack@eecs.umich.edu .desc("Number of tx TCP Checksums done by device") 1757376Sgblack@eecs.umich.edu .precision(0) 1767376Sgblack@eecs.umich.edu .prereq(txBytes) 1777376Sgblack@eecs.umich.edu ; 1787376Sgblack@eecs.umich.edu 1797376Sgblack@eecs.umich.edu rxTcpChecksums 1807376Sgblack@eecs.umich.edu .name(name() + ".rxTcpChecksums") 1817376Sgblack@eecs.umich.edu .desc("Number of rx TCP Checksums done by device") 1827376Sgblack@eecs.umich.edu .precision(0) 1837376Sgblack@eecs.umich.edu .prereq(rxBytes) 1847376Sgblack@eecs.umich.edu ; 1857376Sgblack@eecs.umich.edu 1867376Sgblack@eecs.umich.edu txUdpChecksums 1877376Sgblack@eecs.umich.edu .name(name() + ".txUdpChecksums") 1887322Sgblack@eecs.umich.edu .desc("Number of tx UDP Checksums done by device") 1897322Sgblack@eecs.umich.edu .precision(0) 1907322Sgblack@eecs.umich.edu .prereq(txBytes) 1917322Sgblack@eecs.umich.edu ; 1927322Sgblack@eecs.umich.edu 1937322Sgblack@eecs.umich.edu rxUdpChecksums 1947375Sgblack@eecs.umich.edu .name(name() + ".rxUdpChecksums") 1957322Sgblack@eecs.umich.edu .desc("Number of rx UDP Checksums done by device") 1967322Sgblack@eecs.umich.edu .precision(0) 1977375Sgblack@eecs.umich.edu .prereq(rxBytes) 1987375Sgblack@eecs.umich.edu ; 1997322Sgblack@eecs.umich.edu 2007324Sgblack@eecs.umich.edu descDmaReads 2017375Sgblack@eecs.umich.edu .name(name() + ".descDMAReads") 2027324Sgblack@eecs.umich.edu .desc("Number of descriptors the device read w/ DMA") 2037324Sgblack@eecs.umich.edu .precision(0) 2047375Sgblack@eecs.umich.edu ; 2057375Sgblack@eecs.umich.edu 2067324Sgblack@eecs.umich.edu descDmaWrites 2077333Sgblack@eecs.umich.edu .name(name() + ".descDMAWrites") 2087333Sgblack@eecs.umich.edu .desc("Number of descriptors the device wrote w/ DMA") 2097333Sgblack@eecs.umich.edu .precision(0) 2107333Sgblack@eecs.umich.edu ; 2117375Sgblack@eecs.umich.edu 2127333Sgblack@eecs.umich.edu descDmaRdBytes 2137333Sgblack@eecs.umich.edu .name(name() + ".descDmaReadBytes") 2147375Sgblack@eecs.umich.edu .desc("number of descriptor bytes read w/ DMA") 2157375Sgblack@eecs.umich.edu .precision(0) 2167333Sgblack@eecs.umich.edu ; 2177333Sgblack@eecs.umich.edu 2187333Sgblack@eecs.umich.edu descDmaWrBytes 2197333Sgblack@eecs.umich.edu .name(name() + ".descDmaWriteBytes") 2207333Sgblack@eecs.umich.edu .desc("number of descriptor bytes write w/ DMA") 2217333Sgblack@eecs.umich.edu .precision(0) 2227375Sgblack@eecs.umich.edu ; 2237333Sgblack@eecs.umich.edu 2247333Sgblack@eecs.umich.edu txBandwidth 2257375Sgblack@eecs.umich.edu .name(name() + ".txBandwidth") 2267375Sgblack@eecs.umich.edu .desc("Transmit Bandwidth (bits/s)") 2277333Sgblack@eecs.umich.edu .precision(0) 2287333Sgblack@eecs.umich.edu .prereq(txBytes) 2297333Sgblack@eecs.umich.edu ; 2307333Sgblack@eecs.umich.edu 2317333Sgblack@eecs.umich.edu rxBandwidth 2327333Sgblack@eecs.umich.edu .name(name() + ".rxBandwidth") 2337333Sgblack@eecs.umich.edu .desc("Receive Bandwidth (bits/s)") 2347333Sgblack@eecs.umich.edu .precision(0) 2357375Sgblack@eecs.umich.edu .prereq(rxBytes) 2367333Sgblack@eecs.umich.edu ; 2377333Sgblack@eecs.umich.edu 2387375Sgblack@eecs.umich.edu totBandwidth 2397375Sgblack@eecs.umich.edu .name(name() + ".totBandwidth") 2407333Sgblack@eecs.umich.edu .desc("Total Bandwidth (bits/s)") 2417333Sgblack@eecs.umich.edu .precision(0) 2427333Sgblack@eecs.umich.edu .prereq(totBytes) 2437333Sgblack@eecs.umich.edu ; 2447333Sgblack@eecs.umich.edu 2457375Sgblack@eecs.umich.edu totPackets 2467333Sgblack@eecs.umich.edu .name(name() + ".totPackets") 2477333Sgblack@eecs.umich.edu .desc("Total Packets") 2487375Sgblack@eecs.umich.edu .precision(0) 2497375Sgblack@eecs.umich.edu .prereq(totBytes) 2507333Sgblack@eecs.umich.edu ; 2517333Sgblack@eecs.umich.edu 2527333Sgblack@eecs.umich.edu totBytes 2537333Sgblack@eecs.umich.edu .name(name() + ".totBytes") 2547333Sgblack@eecs.umich.edu .desc("Total Bytes") 2557333Sgblack@eecs.umich.edu .precision(0) 2567375Sgblack@eecs.umich.edu .prereq(totBytes) 2577333Sgblack@eecs.umich.edu ; 2587333Sgblack@eecs.umich.edu 2597375Sgblack@eecs.umich.edu totPacketRate 2607375Sgblack@eecs.umich.edu .name(name() + ".totPPS") 2617333Sgblack@eecs.umich.edu .desc("Total Tranmission Rate (packets/s)") 2627333Sgblack@eecs.umich.edu .precision(0) 2637333Sgblack@eecs.umich.edu .prereq(totBytes) 2647333Sgblack@eecs.umich.edu ; 2657333Sgblack@eecs.umich.edu 2667333Sgblack@eecs.umich.edu txPacketRate 2677333Sgblack@eecs.umich.edu .name(name() + ".txPPS") 2687333Sgblack@eecs.umich.edu .desc("Packet Tranmission Rate (packets/s)") 2697375Sgblack@eecs.umich.edu .precision(0) 2707333Sgblack@eecs.umich.edu .prereq(txBytes) 2717333Sgblack@eecs.umich.edu ; 2727375Sgblack@eecs.umich.edu 2737375Sgblack@eecs.umich.edu rxPacketRate 2747333Sgblack@eecs.umich.edu .name(name() + ".rxPPS") 2757333Sgblack@eecs.umich.edu .desc("Packet Reception Rate (packets/s)") 2767333Sgblack@eecs.umich.edu .precision(0) 2777333Sgblack@eecs.umich.edu .prereq(rxBytes) 2787333Sgblack@eecs.umich.edu ; 2797375Sgblack@eecs.umich.edu 2807333Sgblack@eecs.umich.edu postedSwi 2817333Sgblack@eecs.umich.edu .name(name() + ".postedSwi") 2827375Sgblack@eecs.umich.edu .desc("number of software interrupts posted to CPU") 2837375Sgblack@eecs.umich.edu .precision(0) 2847333Sgblack@eecs.umich.edu ; 2857333Sgblack@eecs.umich.edu 2867333Sgblack@eecs.umich.edu totalSwi 2877333Sgblack@eecs.umich.edu .name(name() + ".totalSwi") 2887333Sgblack@eecs.umich.edu .desc("total number of Swi written to ISR") 2897375Sgblack@eecs.umich.edu .precision(0) 2907333Sgblack@eecs.umich.edu ; 2917333Sgblack@eecs.umich.edu 2927375Sgblack@eecs.umich.edu coalescedSwi 2937375Sgblack@eecs.umich.edu .name(name() + ".coalescedSwi") 2947333Sgblack@eecs.umich.edu .desc("average number of Swi's coalesced into each post") 2957333Sgblack@eecs.umich.edu .precision(0) 2967333Sgblack@eecs.umich.edu ; 2977333Sgblack@eecs.umich.edu 2987333Sgblack@eecs.umich.edu postedRxIdle 2997375Sgblack@eecs.umich.edu .name(name() + ".postedRxIdle") 3007333Sgblack@eecs.umich.edu .desc("number of rxIdle interrupts posted to CPU") 3017333Sgblack@eecs.umich.edu .precision(0) 3027375Sgblack@eecs.umich.edu ; 3037375Sgblack@eecs.umich.edu 3047333Sgblack@eecs.umich.edu totalRxIdle 3057333Sgblack@eecs.umich.edu .name(name() + ".totalRxIdle") 3067333Sgblack@eecs.umich.edu .desc("total number of RxIdle written to ISR") 3077333Sgblack@eecs.umich.edu .precision(0) 3087333Sgblack@eecs.umich.edu ; 3097375Sgblack@eecs.umich.edu 3107333Sgblack@eecs.umich.edu coalescedRxIdle 3117333Sgblack@eecs.umich.edu .name(name() + ".coalescedRxIdle") 3127375Sgblack@eecs.umich.edu .desc("average number of RxIdle's coalesced into each post") 3137375Sgblack@eecs.umich.edu .precision(0) 3147333Sgblack@eecs.umich.edu ; 3157333Sgblack@eecs.umich.edu 3167333Sgblack@eecs.umich.edu postedRxOk 3177333Sgblack@eecs.umich.edu .name(name() + ".postedRxOk") 3187333Sgblack@eecs.umich.edu .desc("number of RxOk interrupts posted to CPU") 3197375Sgblack@eecs.umich.edu .precision(0) 3207333Sgblack@eecs.umich.edu ; 3217333Sgblack@eecs.umich.edu 3227375Sgblack@eecs.umich.edu totalRxOk 3237375Sgblack@eecs.umich.edu .name(name() + ".totalRxOk") 3247333Sgblack@eecs.umich.edu .desc("total number of RxOk written to ISR") 3257333Sgblack@eecs.umich.edu .precision(0) 3267333Sgblack@eecs.umich.edu ; 3277333Sgblack@eecs.umich.edu 3287333Sgblack@eecs.umich.edu coalescedRxOk 3297375Sgblack@eecs.umich.edu .name(name() + ".coalescedRxOk") 3307333Sgblack@eecs.umich.edu .desc("average number of RxOk's coalesced into each post") 3317333Sgblack@eecs.umich.edu .precision(0) 3327375Sgblack@eecs.umich.edu ; 3337375Sgblack@eecs.umich.edu 3347333Sgblack@eecs.umich.edu postedRxDesc 3357333Sgblack@eecs.umich.edu .name(name() + ".postedRxDesc") 3367333Sgblack@eecs.umich.edu .desc("number of RxDesc interrupts posted to CPU") 3377333Sgblack@eecs.umich.edu .precision(0) 3387333Sgblack@eecs.umich.edu ; 3397375Sgblack@eecs.umich.edu 3407333Sgblack@eecs.umich.edu totalRxDesc 3417333Sgblack@eecs.umich.edu .name(name() + ".totalRxDesc") 3427375Sgblack@eecs.umich.edu .desc("total number of RxDesc written to ISR") 3437375Sgblack@eecs.umich.edu .precision(0) 3447333Sgblack@eecs.umich.edu ; 3457333Sgblack@eecs.umich.edu 3467333Sgblack@eecs.umich.edu coalescedRxDesc 3477333Sgblack@eecs.umich.edu .name(name() + ".coalescedRxDesc") 3487333Sgblack@eecs.umich.edu .desc("average number of RxDesc's coalesced into each post") 3497375Sgblack@eecs.umich.edu .precision(0) 3507333Sgblack@eecs.umich.edu ; 3517333Sgblack@eecs.umich.edu 3527375Sgblack@eecs.umich.edu postedTxOk 3537375Sgblack@eecs.umich.edu .name(name() + ".postedTxOk") 3547333Sgblack@eecs.umich.edu .desc("number of TxOk interrupts posted to CPU") 3557333Sgblack@eecs.umich.edu .precision(0) 3567333Sgblack@eecs.umich.edu ; 3577333Sgblack@eecs.umich.edu 3587333Sgblack@eecs.umich.edu totalTxOk 3597333Sgblack@eecs.umich.edu .name(name() + ".totalTxOk") 3607375Sgblack@eecs.umich.edu .desc("total number of TxOk written to ISR") 3617333Sgblack@eecs.umich.edu .precision(0) 3627333Sgblack@eecs.umich.edu ; 3637375Sgblack@eecs.umich.edu 3647375Sgblack@eecs.umich.edu coalescedTxOk 3657333Sgblack@eecs.umich.edu .name(name() + ".coalescedTxOk") 3667333Sgblack@eecs.umich.edu .desc("average number of TxOk's coalesced into each post") 3677333Sgblack@eecs.umich.edu .precision(0) 3687333Sgblack@eecs.umich.edu ; 3697333Sgblack@eecs.umich.edu 3707333Sgblack@eecs.umich.edu postedTxIdle 3717375Sgblack@eecs.umich.edu .name(name() + ".postedTxIdle") 3727333Sgblack@eecs.umich.edu .desc("number of TxIdle interrupts posted to CPU") 3737333Sgblack@eecs.umich.edu .precision(0) 3747375Sgblack@eecs.umich.edu ; 3757375Sgblack@eecs.umich.edu 3767333Sgblack@eecs.umich.edu totalTxIdle 3777364Sgblack@eecs.umich.edu .name(name() + ".totalTxIdle") 3787364Sgblack@eecs.umich.edu .desc("total number of TxIdle written to ISR") 3797378Sgblack@eecs.umich.edu .precision(0) 3807364Sgblack@eecs.umich.edu ; 3817378Sgblack@eecs.umich.edu 3827364Sgblack@eecs.umich.edu coalescedTxIdle 3837364Sgblack@eecs.umich.edu .name(name() + ".coalescedTxIdle") 3847364Sgblack@eecs.umich.edu .desc("average number of TxIdle's coalesced into each post") 3857364Sgblack@eecs.umich.edu .precision(0) 3867375Sgblack@eecs.umich.edu ; 3877364Sgblack@eecs.umich.edu 3887364Sgblack@eecs.umich.edu postedTxDesc 3897375Sgblack@eecs.umich.edu .name(name() + ".postedTxDesc") 3907375Sgblack@eecs.umich.edu .desc("number of TxDesc interrupts posted to CPU") 3917364Sgblack@eecs.umich.edu .precision(0) 3927364Sgblack@eecs.umich.edu ; 3937364Sgblack@eecs.umich.edu 3947364Sgblack@eecs.umich.edu totalTxDesc 3957364Sgblack@eecs.umich.edu .name(name() + ".totalTxDesc") 3967364Sgblack@eecs.umich.edu .desc("total number of TxDesc written to ISR") 3977378Sgblack@eecs.umich.edu .precision(0) 3987364Sgblack@eecs.umich.edu ; 3997378Sgblack@eecs.umich.edu 4007364Sgblack@eecs.umich.edu coalescedTxDesc 4017364Sgblack@eecs.umich.edu .name(name() + ".coalescedTxDesc") 4027364Sgblack@eecs.umich.edu .desc("average number of TxDesc's coalesced into each post") 4037364Sgblack@eecs.umich.edu .precision(0) 4047364Sgblack@eecs.umich.edu ; 4057364Sgblack@eecs.umich.edu 4067364Sgblack@eecs.umich.edu postedRxOrn 4077375Sgblack@eecs.umich.edu .name(name() + ".postedRxOrn") 4087364Sgblack@eecs.umich.edu .desc("number of RxOrn posted to CPU") 4097364Sgblack@eecs.umich.edu .precision(0) 4107375Sgblack@eecs.umich.edu ; 4117375Sgblack@eecs.umich.edu 4127364Sgblack@eecs.umich.edu totalRxOrn 4137365Sgblack@eecs.umich.edu .name(name() + ".totalRxOrn") 4147365Sgblack@eecs.umich.edu .desc("total number of RxOrn written to ISR") 4157365Sgblack@eecs.umich.edu .precision(0) 4167365Sgblack@eecs.umich.edu ; 4177375Sgblack@eecs.umich.edu 4187365Sgblack@eecs.umich.edu coalescedRxOrn 4197365Sgblack@eecs.umich.edu .name(name() + ".coalescedRxOrn") 4207375Sgblack@eecs.umich.edu .desc("average number of RxOrn's coalesced into each post") 4217375Sgblack@eecs.umich.edu .precision(0) 4227365Sgblack@eecs.umich.edu ; 4237365Sgblack@eecs.umich.edu 4247365Sgblack@eecs.umich.edu coalescedTotal 4257365Sgblack@eecs.umich.edu .name(name() + ".coalescedTotal") 4267365Sgblack@eecs.umich.edu .desc("average number of interrupts coalesced into each post") 4277365Sgblack@eecs.umich.edu .precision(0) 4287365Sgblack@eecs.umich.edu ; 4297365Sgblack@eecs.umich.edu 4307365Sgblack@eecs.umich.edu postedInterrupts 4317375Sgblack@eecs.umich.edu .name(name() + ".postedInterrupts") 4327365Sgblack@eecs.umich.edu .desc("number of posts to CPU") 4337365Sgblack@eecs.umich.edu .precision(0) 4347375Sgblack@eecs.umich.edu ; 4357375Sgblack@eecs.umich.edu 4367365Sgblack@eecs.umich.edu droppedPackets 4377366Sgblack@eecs.umich.edu .name(name() + ".droppedPackets") 4387366Sgblack@eecs.umich.edu .desc("number of packets dropped") 4397366Sgblack@eecs.umich.edu .precision(0) 4407366Sgblack@eecs.umich.edu ; 4417375Sgblack@eecs.umich.edu 4427366Sgblack@eecs.umich.edu coalescedSwi = totalSwi / postedInterrupts; 4437366Sgblack@eecs.umich.edu coalescedRxIdle = totalRxIdle / postedInterrupts; 4447375Sgblack@eecs.umich.edu coalescedRxOk = totalRxOk / postedInterrupts; 4457375Sgblack@eecs.umich.edu coalescedRxDesc = totalRxDesc / postedInterrupts; 4467366Sgblack@eecs.umich.edu coalescedTxOk = totalTxOk / postedInterrupts; 4477366Sgblack@eecs.umich.edu coalescedTxIdle = totalTxIdle / postedInterrupts; 4487366Sgblack@eecs.umich.edu coalescedTxDesc = totalTxDesc / postedInterrupts; 4497366Sgblack@eecs.umich.edu coalescedRxOrn = totalRxOrn / postedInterrupts; 4507366Sgblack@eecs.umich.edu 4517366Sgblack@eecs.umich.edu coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 4527366Sgblack@eecs.umich.edu totalTxOk + totalTxIdle + totalTxDesc + 4537366Sgblack@eecs.umich.edu totalRxOrn) / postedInterrupts; 4547366Sgblack@eecs.umich.edu 4557375Sgblack@eecs.umich.edu txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4567366Sgblack@eecs.umich.edu rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4577366Sgblack@eecs.umich.edu totBandwidth = txBandwidth + rxBandwidth; 4587375Sgblack@eecs.umich.edu totBytes = txBytes + rxBytes; 4597375Sgblack@eecs.umich.edu totPackets = txPackets + rxPackets; 4607366Sgblack@eecs.umich.edu 4617367Sgblack@eecs.umich.edu txPacketRate = txPackets / simSeconds; 4627367Sgblack@eecs.umich.edu rxPacketRate = rxPackets / simSeconds; 4637378Sgblack@eecs.umich.edu} 4647367Sgblack@eecs.umich.edu 4657378Sgblack@eecs.umich.edu 4667367Sgblack@eecs.umich.edu/** 4677375Sgblack@eecs.umich.edu * This is to write to the PCI general configuration registers 4687367Sgblack@eecs.umich.edu */ 4697367Sgblack@eecs.umich.eduTick 4707375Sgblack@eecs.umich.eduNSGigE::writeConfig(PacketPtr pkt) 4717375Sgblack@eecs.umich.edu{ 4727367Sgblack@eecs.umich.edu int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 4737367Sgblack@eecs.umich.edu if (offset < PCI_DEVICE_SPECIFIC) 4747367Sgblack@eecs.umich.edu PciDev::writeConfig(pkt); 4757367Sgblack@eecs.umich.edu else 4767367Sgblack@eecs.umich.edu panic("Device specific PCI config space not implemented!\n"); 4777367Sgblack@eecs.umich.edu 4787378Sgblack@eecs.umich.edu switch (offset) { 4797367Sgblack@eecs.umich.edu // seems to work fine without all these PCI settings, but i 4807378Sgblack@eecs.umich.edu // put in the IO to double check, an assertion will fail if we 4817367Sgblack@eecs.umich.edu // need to properly implement it 4827367Sgblack@eecs.umich.edu case PCI_COMMAND: 4837367Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_IOSE) 4847375Sgblack@eecs.umich.edu ioEnable = true; 4857367Sgblack@eecs.umich.edu else 4867367Sgblack@eecs.umich.edu ioEnable = false; 4877375Sgblack@eecs.umich.edu break; 4887375Sgblack@eecs.umich.edu } 4897367Sgblack@eecs.umich.edu pkt->result = Packet::Success; 4907368Sgblack@eecs.umich.edu return configDelay; 4917368Sgblack@eecs.umich.edu} 4927378Sgblack@eecs.umich.edu 4937368Sgblack@eecs.umich.edu/** 4947378Sgblack@eecs.umich.edu * This reads the device registers, which are detailed in the NS83820 4957368Sgblack@eecs.umich.edu * spec sheet 4967375Sgblack@eecs.umich.edu */ 4977368Sgblack@eecs.umich.eduTick 4987368Sgblack@eecs.umich.eduNSGigE::read(PacketPtr pkt) 4997375Sgblack@eecs.umich.edu{ 5007375Sgblack@eecs.umich.edu assert(ioEnable); 5017368Sgblack@eecs.umich.edu 5027368Sgblack@eecs.umich.edu pkt->allocate(); 5037368Sgblack@eecs.umich.edu 5047368Sgblack@eecs.umich.edu //The mask is to give you only the offset into the device register file 5057368Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() & 0xfff; 5067368Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 5077378Sgblack@eecs.umich.edu daddr, pkt->getAddr(), pkt->getSize()); 5087368Sgblack@eecs.umich.edu 5097378Sgblack@eecs.umich.edu 5107368Sgblack@eecs.umich.edu // there are some reserved registers, you can see ns_gige_reg.h and 5117368Sgblack@eecs.umich.edu // the spec sheet for details 5127368Sgblack@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 5137375Sgblack@eecs.umich.edu panic("Accessing reserved register"); 5147368Sgblack@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 5157368Sgblack@eecs.umich.edu return readConfig(pkt); 5167375Sgblack@eecs.umich.edu } else if (daddr >= MIB_START && daddr <= MIB_END) { 5177375Sgblack@eecs.umich.edu // don't implement all the MIB's. hopefully the kernel 5187368Sgblack@eecs.umich.edu // doesn't actually DEPEND upon their values 5197369Sgblack@eecs.umich.edu // MIB are just hardware stats keepers 5207369Sgblack@eecs.umich.edu pkt->set<uint32_t>(0); 5217378Sgblack@eecs.umich.edu pkt->result = Packet::Success; 5227369Sgblack@eecs.umich.edu return pioDelay; 5237378Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 5247369Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 5257375Sgblack@eecs.umich.edu 5267369Sgblack@eecs.umich.edu assert(pkt->getSize() == sizeof(uint32_t)); 5277369Sgblack@eecs.umich.edu uint32_t ® = *pkt->getPtr<uint32_t>(); 5287375Sgblack@eecs.umich.edu uint16_t rfaddr; 5297375Sgblack@eecs.umich.edu 5307369Sgblack@eecs.umich.edu switch (daddr) { 5317369Sgblack@eecs.umich.edu case CR: 5327369Sgblack@eecs.umich.edu reg = regs.command; 5337369Sgblack@eecs.umich.edu //these are supposed to be cleared on a read 5347369Sgblack@eecs.umich.edu reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 5357369Sgblack@eecs.umich.edu break; 5367378Sgblack@eecs.umich.edu 5377369Sgblack@eecs.umich.edu case CFGR: 5387378Sgblack@eecs.umich.edu reg = regs.config; 5397369Sgblack@eecs.umich.edu break; 5407369Sgblack@eecs.umich.edu 5417369Sgblack@eecs.umich.edu case MEAR: 5427375Sgblack@eecs.umich.edu reg = regs.mear; 5437369Sgblack@eecs.umich.edu break; 5447369Sgblack@eecs.umich.edu 5457375Sgblack@eecs.umich.edu case PTSCR: 5467375Sgblack@eecs.umich.edu reg = regs.ptscr; 5477369Sgblack@eecs.umich.edu break; 5487369Sgblack@eecs.umich.edu 5497369Sgblack@eecs.umich.edu case ISR: 5507378Sgblack@eecs.umich.edu reg = regs.isr; 5517369Sgblack@eecs.umich.edu devIntrClear(ISR_ALL); 5527378Sgblack@eecs.umich.edu break; 5537369Sgblack@eecs.umich.edu 5547369Sgblack@eecs.umich.edu case IMR: 5557369Sgblack@eecs.umich.edu reg = regs.imr; 5567369Sgblack@eecs.umich.edu break; 5577375Sgblack@eecs.umich.edu 5587369Sgblack@eecs.umich.edu case IER: 5597369Sgblack@eecs.umich.edu reg = regs.ier; 5607375Sgblack@eecs.umich.edu break; 5617375Sgblack@eecs.umich.edu 5627369Sgblack@eecs.umich.edu case IHR: 5637369Sgblack@eecs.umich.edu reg = regs.ihr; 5647369Sgblack@eecs.umich.edu break; 5657369Sgblack@eecs.umich.edu 5667369Sgblack@eecs.umich.edu case TXDP: 5677378Sgblack@eecs.umich.edu reg = regs.txdp; 5687369Sgblack@eecs.umich.edu break; 5697378Sgblack@eecs.umich.edu 5707369Sgblack@eecs.umich.edu case TXDP_HI: 5717369Sgblack@eecs.umich.edu reg = regs.txdp_hi; 5727369Sgblack@eecs.umich.edu break; 5737369Sgblack@eecs.umich.edu 5747369Sgblack@eecs.umich.edu case TX_CFG: 5757369Sgblack@eecs.umich.edu reg = regs.txcfg; 5767375Sgblack@eecs.umich.edu break; 5777369Sgblack@eecs.umich.edu 5787369Sgblack@eecs.umich.edu case GPIOR: 5797375Sgblack@eecs.umich.edu reg = regs.gpior; 5807375Sgblack@eecs.umich.edu break; 5817369Sgblack@eecs.umich.edu 5827370Sgblack@eecs.umich.edu case RXDP: 5837370Sgblack@eecs.umich.edu reg = regs.rxdp; 5847378Sgblack@eecs.umich.edu break; 5857370Sgblack@eecs.umich.edu 5867370Sgblack@eecs.umich.edu case RXDP_HI: 5877370Sgblack@eecs.umich.edu reg = regs.rxdp_hi; 5887370Sgblack@eecs.umich.edu break; 5897370Sgblack@eecs.umich.edu 5907378Sgblack@eecs.umich.edu case RX_CFG: 5917370Sgblack@eecs.umich.edu reg = regs.rxcfg; 5927375Sgblack@eecs.umich.edu break; 5937370Sgblack@eecs.umich.edu 5947370Sgblack@eecs.umich.edu case PQCR: 5957375Sgblack@eecs.umich.edu reg = regs.pqcr; 5967375Sgblack@eecs.umich.edu break; 5977370Sgblack@eecs.umich.edu 5987370Sgblack@eecs.umich.edu case WCSR: 5997370Sgblack@eecs.umich.edu reg = regs.wcsr; 6007370Sgblack@eecs.umich.edu break; 6017370Sgblack@eecs.umich.edu 6027370Sgblack@eecs.umich.edu case PCR: 6037370Sgblack@eecs.umich.edu reg = regs.pcr; 6047378Sgblack@eecs.umich.edu break; 6057370Sgblack@eecs.umich.edu 6067370Sgblack@eecs.umich.edu // see the spec sheet for how RFCR and RFDR work 6077370Sgblack@eecs.umich.edu // basically, you write to RFCR to tell the machine 6087370Sgblack@eecs.umich.edu // what you want to do next, then you act upon RFDR, 6097370Sgblack@eecs.umich.edu // and the device will be prepared b/c of what you 6107370Sgblack@eecs.umich.edu // wrote to RFCR 6117378Sgblack@eecs.umich.edu case RFCR: 6127370Sgblack@eecs.umich.edu reg = regs.rfcr; 6137370Sgblack@eecs.umich.edu break; 6147370Sgblack@eecs.umich.edu 6157375Sgblack@eecs.umich.edu case RFDR: 6167370Sgblack@eecs.umich.edu rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 6177370Sgblack@eecs.umich.edu switch (rfaddr) { 6187375Sgblack@eecs.umich.edu // Read from perfect match ROM octets 6197375Sgblack@eecs.umich.edu case 0x000: 6207370Sgblack@eecs.umich.edu reg = rom.perfectMatch[1]; 6217370Sgblack@eecs.umich.edu reg = reg << 8; 6227370Sgblack@eecs.umich.edu reg += rom.perfectMatch[0]; 6237378Sgblack@eecs.umich.edu break; 6247370Sgblack@eecs.umich.edu case 0x002: 6257370Sgblack@eecs.umich.edu reg = rom.perfectMatch[3] << 8; 6267370Sgblack@eecs.umich.edu reg += rom.perfectMatch[2]; 6277370Sgblack@eecs.umich.edu break; 6287370Sgblack@eecs.umich.edu case 0x004: 6297378Sgblack@eecs.umich.edu reg = rom.perfectMatch[5] << 8; 6307370Sgblack@eecs.umich.edu reg += rom.perfectMatch[4]; 6317375Sgblack@eecs.umich.edu break; 6327370Sgblack@eecs.umich.edu default: 6337370Sgblack@eecs.umich.edu // Read filter hash table 6347375Sgblack@eecs.umich.edu if (rfaddr >= FHASH_ADDR && 6357375Sgblack@eecs.umich.edu rfaddr < FHASH_ADDR + FHASH_SIZE) { 6367370Sgblack@eecs.umich.edu 6377370Sgblack@eecs.umich.edu // Only word-aligned reads supported 6387370Sgblack@eecs.umich.edu if (rfaddr % 2) 6397370Sgblack@eecs.umich.edu panic("unaligned read from filter hash table!"); 6407370Sgblack@eecs.umich.edu 6417370Sgblack@eecs.umich.edu reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 6427370Sgblack@eecs.umich.edu reg += rom.filterHash[rfaddr - FHASH_ADDR]; 6437378Sgblack@eecs.umich.edu break; 6447370Sgblack@eecs.umich.edu } 6457370Sgblack@eecs.umich.edu 6467370Sgblack@eecs.umich.edu panic("reading RFDR for something other than pattern" 6477370Sgblack@eecs.umich.edu " matching or hashing! %#x\n", rfaddr); 6487370Sgblack@eecs.umich.edu } 6497370Sgblack@eecs.umich.edu break; 6507378Sgblack@eecs.umich.edu 6517370Sgblack@eecs.umich.edu case SRR: 6527370Sgblack@eecs.umich.edu reg = regs.srr; 6537370Sgblack@eecs.umich.edu break; 6547375Sgblack@eecs.umich.edu 6557370Sgblack@eecs.umich.edu case MIBC: 6567370Sgblack@eecs.umich.edu reg = regs.mibc; 6577375Sgblack@eecs.umich.edu reg &= ~(MIBC_MIBS | MIBC_ACLR); 6587375Sgblack@eecs.umich.edu break; 6597370Sgblack@eecs.umich.edu 6607371Sgblack@eecs.umich.edu case VRCR: 6617371Sgblack@eecs.umich.edu reg = regs.vrcr; 6627378Sgblack@eecs.umich.edu break; 6637371Sgblack@eecs.umich.edu 6647371Sgblack@eecs.umich.edu case VTCR: 6657371Sgblack@eecs.umich.edu reg = regs.vtcr; 6667371Sgblack@eecs.umich.edu break; 6677371Sgblack@eecs.umich.edu 6687378Sgblack@eecs.umich.edu case VDR: 6697371Sgblack@eecs.umich.edu reg = regs.vdr; 6707375Sgblack@eecs.umich.edu break; 6717371Sgblack@eecs.umich.edu 6727371Sgblack@eecs.umich.edu case CCSR: 6737375Sgblack@eecs.umich.edu reg = regs.ccsr; 6747375Sgblack@eecs.umich.edu break; 6757371Sgblack@eecs.umich.edu 6767371Sgblack@eecs.umich.edu case TBICR: 6777371Sgblack@eecs.umich.edu reg = regs.tbicr; 6787371Sgblack@eecs.umich.edu break; 6797371Sgblack@eecs.umich.edu 6807371Sgblack@eecs.umich.edu case TBISR: 6817371Sgblack@eecs.umich.edu reg = regs.tbisr; 6827378Sgblack@eecs.umich.edu break; 6837371Sgblack@eecs.umich.edu 6847371Sgblack@eecs.umich.edu case TANAR: 6857371Sgblack@eecs.umich.edu reg = regs.tanar; 6867371Sgblack@eecs.umich.edu break; 6877371Sgblack@eecs.umich.edu 6887371Sgblack@eecs.umich.edu case TANLPAR: 6897378Sgblack@eecs.umich.edu reg = regs.tanlpar; 6907371Sgblack@eecs.umich.edu break; 6917371Sgblack@eecs.umich.edu 6927371Sgblack@eecs.umich.edu case TANER: 6937375Sgblack@eecs.umich.edu reg = regs.taner; 6947371Sgblack@eecs.umich.edu break; 6957371Sgblack@eecs.umich.edu 6967375Sgblack@eecs.umich.edu case TESR: 6977375Sgblack@eecs.umich.edu reg = regs.tesr; 6987371Sgblack@eecs.umich.edu break; 6997371Sgblack@eecs.umich.edu 7007371Sgblack@eecs.umich.edu case M5REG: 7017378Sgblack@eecs.umich.edu reg = 0; 7027371Sgblack@eecs.umich.edu if (params()->rx_thread) 7037371Sgblack@eecs.umich.edu reg |= M5REG_RX_THREAD; 7047371Sgblack@eecs.umich.edu if (params()->tx_thread) 7057371Sgblack@eecs.umich.edu reg |= M5REG_TX_THREAD; 7067371Sgblack@eecs.umich.edu if (params()->rss) 7077378Sgblack@eecs.umich.edu reg |= M5REG_RSS; 7087371Sgblack@eecs.umich.edu break; 7097375Sgblack@eecs.umich.edu 7107371Sgblack@eecs.umich.edu default: 7117371Sgblack@eecs.umich.edu panic("reading unimplemented register: addr=%#x", daddr); 7127375Sgblack@eecs.umich.edu } 7137375Sgblack@eecs.umich.edu 7147371Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 7157371Sgblack@eecs.umich.edu daddr, reg, reg); 7167371Sgblack@eecs.umich.edu 7177371Sgblack@eecs.umich.edu pkt->result = Packet::Success; 7187371Sgblack@eecs.umich.edu return pioDelay; 7197371Sgblack@eecs.umich.edu} 7207371Sgblack@eecs.umich.edu 7217378Sgblack@eecs.umich.eduTick 7227371Sgblack@eecs.umich.eduNSGigE::write(PacketPtr pkt) 7237371Sgblack@eecs.umich.edu{ 7247371Sgblack@eecs.umich.edu assert(ioEnable); 7257371Sgblack@eecs.umich.edu 7267371Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() & 0xfff; 7277371Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 7287378Sgblack@eecs.umich.edu daddr, pkt->getAddr(), pkt->getSize()); 7297371Sgblack@eecs.umich.edu 7307371Sgblack@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 7317371Sgblack@eecs.umich.edu panic("Accessing reserved register"); 7327375Sgblack@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 7337371Sgblack@eecs.umich.edu return writeConfig(pkt); 7347371Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 7357375Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 7367375Sgblack@eecs.umich.edu 7377371Sgblack@eecs.umich.edu if (pkt->getSize() == sizeof(uint32_t)) { 7387371Sgblack@eecs.umich.edu uint32_t reg = pkt->get<uint32_t>(); 7397371Sgblack@eecs.umich.edu uint16_t rfaddr; 7407378Sgblack@eecs.umich.edu 7417371Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 7427371Sgblack@eecs.umich.edu 7437371Sgblack@eecs.umich.edu switch (daddr) { 7447371Sgblack@eecs.umich.edu case CR: 7457371Sgblack@eecs.umich.edu regs.command = reg; 7467378Sgblack@eecs.umich.edu if (reg & CR_TXD) { 7477371Sgblack@eecs.umich.edu txEnable = false; 7487375Sgblack@eecs.umich.edu } else if (reg & CR_TXE) { 7497371Sgblack@eecs.umich.edu txEnable = true; 7507371Sgblack@eecs.umich.edu 7517375Sgblack@eecs.umich.edu // the kernel is enabling the transmit machine 7527375Sgblack@eecs.umich.edu if (txState == txIdle) 7537371Sgblack@eecs.umich.edu txKick(); 7547371Sgblack@eecs.umich.edu } 7557371Sgblack@eecs.umich.edu 7567371Sgblack@eecs.umich.edu if (reg & CR_RXD) { 7577371Sgblack@eecs.umich.edu rxEnable = false; 7587371Sgblack@eecs.umich.edu } else if (reg & CR_RXE) { 7597371Sgblack@eecs.umich.edu rxEnable = true; 7607378Sgblack@eecs.umich.edu 7617371Sgblack@eecs.umich.edu if (rxState == rxIdle) 7627371Sgblack@eecs.umich.edu rxKick(); 7637371Sgblack@eecs.umich.edu } 7647371Sgblack@eecs.umich.edu 7657371Sgblack@eecs.umich.edu if (reg & CR_TXR) 7667371Sgblack@eecs.umich.edu txReset(); 7677378Sgblack@eecs.umich.edu 7687371Sgblack@eecs.umich.edu if (reg & CR_RXR) 7697371Sgblack@eecs.umich.edu rxReset(); 7707371Sgblack@eecs.umich.edu 7717375Sgblack@eecs.umich.edu if (reg & CR_SWI) 7727371Sgblack@eecs.umich.edu devIntrPost(ISR_SWI); 7737371Sgblack@eecs.umich.edu 7747375Sgblack@eecs.umich.edu if (reg & CR_RST) { 7757375Sgblack@eecs.umich.edu txReset(); 7767371Sgblack@eecs.umich.edu rxReset(); 7777373Sgblack@eecs.umich.edu 7787373Sgblack@eecs.umich.edu regsReset(); 7797378Sgblack@eecs.umich.edu } 7807373Sgblack@eecs.umich.edu break; 7817378Sgblack@eecs.umich.edu 7827373Sgblack@eecs.umich.edu case CFGR: 7837375Sgblack@eecs.umich.edu if (reg & CFGR_LNKSTS || 7847373Sgblack@eecs.umich.edu reg & CFGR_SPDSTS || 7857373Sgblack@eecs.umich.edu reg & CFGR_DUPSTS || 7867375Sgblack@eecs.umich.edu reg & CFGR_RESERVED || 7877375Sgblack@eecs.umich.edu reg & CFGR_T64ADDR || 7887373Sgblack@eecs.umich.edu reg & CFGR_PCI64_DET) 7897373Sgblack@eecs.umich.edu 7907373Sgblack@eecs.umich.edu // First clear all writable bits 7917373Sgblack@eecs.umich.edu regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 7927378Sgblack@eecs.umich.edu CFGR_RESERVED | CFGR_T64ADDR | 7937373Sgblack@eecs.umich.edu CFGR_PCI64_DET; 7947378Sgblack@eecs.umich.edu // Now set the appropriate writable bits 7957373Sgblack@eecs.umich.edu regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 7967373Sgblack@eecs.umich.edu CFGR_RESERVED | CFGR_T64ADDR | 7977373Sgblack@eecs.umich.edu CFGR_PCI64_DET); 7987375Sgblack@eecs.umich.edu 7997373Sgblack@eecs.umich.edu// all these #if 0's are because i don't THINK the kernel needs to 8007373Sgblack@eecs.umich.edu// have these implemented. if there is a problem relating to one of 8017375Sgblack@eecs.umich.edu// these, you may need to add functionality in. 8027375Sgblack@eecs.umich.edu if (reg & CFGR_TBI_EN) ; 8037373Sgblack@eecs.umich.edu if (reg & CFGR_MODE_1000) ; 8047373Sgblack@eecs.umich.edu 8057373Sgblack@eecs.umich.edu if (reg & CFGR_AUTO_1000) 8067378Sgblack@eecs.umich.edu panic("CFGR_AUTO_1000 not implemented!\n"); 8077373Sgblack@eecs.umich.edu 8087378Sgblack@eecs.umich.edu if (reg & CFGR_PINT_DUPSTS || 8097373Sgblack@eecs.umich.edu reg & CFGR_PINT_LNKSTS || 8107375Sgblack@eecs.umich.edu reg & CFGR_PINT_SPDSTS) 8117373Sgblack@eecs.umich.edu ; 8127373Sgblack@eecs.umich.edu 8137375Sgblack@eecs.umich.edu if (reg & CFGR_TMRTEST) ; 8147375Sgblack@eecs.umich.edu if (reg & CFGR_MRM_DIS) ; 8157373Sgblack@eecs.umich.edu if (reg & CFGR_MWI_DIS) ; 8167373Sgblack@eecs.umich.edu 8177373Sgblack@eecs.umich.edu if (reg & CFGR_T64ADDR) ; 8187373Sgblack@eecs.umich.edu // panic("CFGR_T64ADDR is read only register!\n"); 8197378Sgblack@eecs.umich.edu 8207373Sgblack@eecs.umich.edu if (reg & CFGR_PCI64_DET) 8217378Sgblack@eecs.umich.edu panic("CFGR_PCI64_DET is read only register!\n"); 8227373Sgblack@eecs.umich.edu 8237373Sgblack@eecs.umich.edu if (reg & CFGR_DATA64_EN) ; 8247373Sgblack@eecs.umich.edu if (reg & CFGR_M64ADDR) ; 8257375Sgblack@eecs.umich.edu if (reg & CFGR_PHY_RST) ; 8267373Sgblack@eecs.umich.edu if (reg & CFGR_PHY_DIS) ; 8277373Sgblack@eecs.umich.edu 8287375Sgblack@eecs.umich.edu if (reg & CFGR_EXTSTS_EN) 8297375Sgblack@eecs.umich.edu extstsEnable = true; 8307373Sgblack@eecs.umich.edu else 8317373Sgblack@eecs.umich.edu extstsEnable = false; 8327380Sgblack@eecs.umich.edu 8337380Sgblack@eecs.umich.edu if (reg & CFGR_REQALG) ; 8347380Sgblack@eecs.umich.edu if (reg & CFGR_SB) ; 8357380Sgblack@eecs.umich.edu if (reg & CFGR_POW) ; 8367380Sgblack@eecs.umich.edu if (reg & CFGR_EXD) ; 8377380Sgblack@eecs.umich.edu if (reg & CFGR_PESEL) ; 8387380Sgblack@eecs.umich.edu if (reg & CFGR_BROM_DIS) ; 8397380Sgblack@eecs.umich.edu if (reg & CFGR_EXT_125) ; 8407380Sgblack@eecs.umich.edu if (reg & CFGR_BEM) ; 8417380Sgblack@eecs.umich.edu break; 8427380Sgblack@eecs.umich.edu 8437380Sgblack@eecs.umich.edu case MEAR: 8447380Sgblack@eecs.umich.edu // Clear writable bits 8457380Sgblack@eecs.umich.edu regs.mear &= MEAR_EEDO; 8467380Sgblack@eecs.umich.edu // Set appropriate writable bits 8477380Sgblack@eecs.umich.edu regs.mear |= reg & ~MEAR_EEDO; 8487380Sgblack@eecs.umich.edu 8497380Sgblack@eecs.umich.edu // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 8507380Sgblack@eecs.umich.edu // even though it could get it through RFDR 8517380Sgblack@eecs.umich.edu if (reg & MEAR_EESEL) { 8527380Sgblack@eecs.umich.edu // Rising edge of clock 8537380Sgblack@eecs.umich.edu if (reg & MEAR_EECLK && !eepromClk) 8547380Sgblack@eecs.umich.edu eepromKick(); 8557380Sgblack@eecs.umich.edu } 8567380Sgblack@eecs.umich.edu else { 8577380Sgblack@eecs.umich.edu eepromState = eepromStart; 8587380Sgblack@eecs.umich.edu regs.mear &= ~MEAR_EEDI; 8597380Sgblack@eecs.umich.edu } 8607380Sgblack@eecs.umich.edu 8617380Sgblack@eecs.umich.edu eepromClk = reg & MEAR_EECLK; 8627380Sgblack@eecs.umich.edu 8637380Sgblack@eecs.umich.edu // since phy is completely faked, MEAR_MD* don't matter 8647380Sgblack@eecs.umich.edu if (reg & MEAR_MDIO) ; 8657380Sgblack@eecs.umich.edu if (reg & MEAR_MDDIR) ; 8667380Sgblack@eecs.umich.edu if (reg & MEAR_MDC) ; 8677380Sgblack@eecs.umich.edu break; 8687380Sgblack@eecs.umich.edu 8697380Sgblack@eecs.umich.edu case PTSCR: 8707380Sgblack@eecs.umich.edu regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 8717380Sgblack@eecs.umich.edu // these control BISTs for various parts of chip - we 8727380Sgblack@eecs.umich.edu // don't care or do just fake that the BIST is done 8737380Sgblack@eecs.umich.edu if (reg & PTSCR_RBIST_EN) 8747380Sgblack@eecs.umich.edu regs.ptscr |= PTSCR_RBIST_DONE; 8757380Sgblack@eecs.umich.edu if (reg & PTSCR_EEBIST_EN) 8767380Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EEBIST_EN; 8777380Sgblack@eecs.umich.edu if (reg & PTSCR_EELOAD_EN) 8787380Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EELOAD_EN; 8797380Sgblack@eecs.umich.edu break; 8807380Sgblack@eecs.umich.edu 8817380Sgblack@eecs.umich.edu case ISR: /* writing to the ISR has no effect */ 8827380Sgblack@eecs.umich.edu panic("ISR is a read only register!\n"); 8837380Sgblack@eecs.umich.edu 8847380Sgblack@eecs.umich.edu case IMR: 8857380Sgblack@eecs.umich.edu regs.imr = reg; 8867373Sgblack@eecs.umich.edu devIntrChangeMask(); 8877378Sgblack@eecs.umich.edu break; 8887380Sgblack@eecs.umich.edu 8897373Sgblack@eecs.umich.edu case IER: 8907378Sgblack@eecs.umich.edu regs.ier = reg; 8917373Sgblack@eecs.umich.edu break; 8927375Sgblack@eecs.umich.edu 8937373Sgblack@eecs.umich.edu case IHR: 8947373Sgblack@eecs.umich.edu regs.ihr = reg; 8957375Sgblack@eecs.umich.edu /* not going to implement real interrupt holdoff */ 8967375Sgblack@eecs.umich.edu break; 8977373Sgblack@eecs.umich.edu 8987373Sgblack@eecs.umich.edu case TXDP: 8997373Sgblack@eecs.umich.edu regs.txdp = (reg & 0xFFFFFFFC); 9007373Sgblack@eecs.umich.edu assert(txState == txIdle); 9017373Sgblack@eecs.umich.edu CTDD = false; 9027378Sgblack@eecs.umich.edu break; 9037380Sgblack@eecs.umich.edu 9047373Sgblack@eecs.umich.edu case TXDP_HI: 9057378Sgblack@eecs.umich.edu regs.txdp_hi = reg; 9067373Sgblack@eecs.umich.edu break; 9077373Sgblack@eecs.umich.edu 9087375Sgblack@eecs.umich.edu case TX_CFG: 9097373Sgblack@eecs.umich.edu regs.txcfg = reg; 9107373Sgblack@eecs.umich.edu#if 0 9117375Sgblack@eecs.umich.edu if (reg & TX_CFG_CSI) ; 9127375Sgblack@eecs.umich.edu if (reg & TX_CFG_HBI) ; 9137373Sgblack@eecs.umich.edu if (reg & TX_CFG_MLB) ; 9147373Sgblack@eecs.umich.edu if (reg & TX_CFG_ATP) ; 9157373Sgblack@eecs.umich.edu if (reg & TX_CFG_ECRETRY) { 9167378Sgblack@eecs.umich.edu /* 9177380Sgblack@eecs.umich.edu * this could easily be implemented, but considering 9187373Sgblack@eecs.umich.edu * the network is just a fake pipe, wouldn't make 9197378Sgblack@eecs.umich.edu * sense to do this 9207373Sgblack@eecs.umich.edu */ 9217375Sgblack@eecs.umich.edu } 9227373Sgblack@eecs.umich.edu 9237373Sgblack@eecs.umich.edu if (reg & TX_CFG_BRST_DIS) ; 9247375Sgblack@eecs.umich.edu#endif 9257375Sgblack@eecs.umich.edu 9267373Sgblack@eecs.umich.edu#if 0 9277373Sgblack@eecs.umich.edu /* we handle our own DMA, ignore the kernel's exhortations */ 9287373Sgblack@eecs.umich.edu if (reg & TX_CFG_MXDMA) ; 9297373Sgblack@eecs.umich.edu#endif 9307373Sgblack@eecs.umich.edu 9317378Sgblack@eecs.umich.edu // also, we currently don't care about fill/drain 9327380Sgblack@eecs.umich.edu // thresholds though this may change in the future with 9337373Sgblack@eecs.umich.edu // more realistic networks or a driver which changes it 9347378Sgblack@eecs.umich.edu // according to feedback 9357373Sgblack@eecs.umich.edu 9367373Sgblack@eecs.umich.edu break; 9377375Sgblack@eecs.umich.edu 9387373Sgblack@eecs.umich.edu case GPIOR: 9397373Sgblack@eecs.umich.edu // Only write writable bits 9407375Sgblack@eecs.umich.edu regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9417375Sgblack@eecs.umich.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 9427373Sgblack@eecs.umich.edu regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9437374Sgblack@eecs.umich.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 9447374Sgblack@eecs.umich.edu /* these just control general purpose i/o pins, don't matter */ 9457374Sgblack@eecs.umich.edu break; 9467378Sgblack@eecs.umich.edu 9477374Sgblack@eecs.umich.edu case RXDP: 9487378Sgblack@eecs.umich.edu regs.rxdp = reg; 9497374Sgblack@eecs.umich.edu CRDD = false; 9507374Sgblack@eecs.umich.edu break; 9517374Sgblack@eecs.umich.edu 9527375Sgblack@eecs.umich.edu case RXDP_HI: 9537374Sgblack@eecs.umich.edu regs.rxdp_hi = reg; 9547374Sgblack@eecs.umich.edu break; 9557375Sgblack@eecs.umich.edu 9567375Sgblack@eecs.umich.edu case RX_CFG: 9577374Sgblack@eecs.umich.edu regs.rxcfg = reg; 9587374Sgblack@eecs.umich.edu#if 0 9597374Sgblack@eecs.umich.edu if (reg & RX_CFG_AEP) ; 9607374Sgblack@eecs.umich.edu if (reg & RX_CFG_ARP) ; 9617374Sgblack@eecs.umich.edu if (reg & RX_CFG_STRIPCRC) ; 9627378Sgblack@eecs.umich.edu if (reg & RX_CFG_RX_RD) ; 9637374Sgblack@eecs.umich.edu if (reg & RX_CFG_ALP) ; 9647378Sgblack@eecs.umich.edu if (reg & RX_CFG_AIRL) ; 9657374Sgblack@eecs.umich.edu 9667375Sgblack@eecs.umich.edu /* we handle our own DMA, ignore what kernel says about it */ 9677374Sgblack@eecs.umich.edu if (reg & RX_CFG_MXDMA) ; 9687374Sgblack@eecs.umich.edu 9697375Sgblack@eecs.umich.edu //also, we currently don't care about fill/drain thresholds 9707375Sgblack@eecs.umich.edu //though this may change in the future with more realistic 9717374Sgblack@eecs.umich.edu //networks or a driver which changes it according to feedback 9727377Sgblack@eecs.umich.edu if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 9737377Sgblack@eecs.umich.edu#endif 9747377Sgblack@eecs.umich.edu break; 9757377Sgblack@eecs.umich.edu 9767377Sgblack@eecs.umich.edu case PQCR: 9777377Sgblack@eecs.umich.edu /* there is no priority queueing used in the linux 2.6 driver */ 9787377Sgblack@eecs.umich.edu regs.pqcr = reg; 9797377Sgblack@eecs.umich.edu break; 9807377Sgblack@eecs.umich.edu 9817377Sgblack@eecs.umich.edu case WCSR: 9827377Sgblack@eecs.umich.edu /* not going to implement wake on LAN */ 9837377Sgblack@eecs.umich.edu regs.wcsr = reg; 9847377Sgblack@eecs.umich.edu break; 9857377Sgblack@eecs.umich.edu 9867377Sgblack@eecs.umich.edu case PCR: 9877377Sgblack@eecs.umich.edu /* not going to implement pause control */ 9887377Sgblack@eecs.umich.edu regs.pcr = reg; 9897377Sgblack@eecs.umich.edu break; 9907377Sgblack@eecs.umich.edu 9917377Sgblack@eecs.umich.edu case RFCR: 9927377Sgblack@eecs.umich.edu regs.rfcr = reg; 9937377Sgblack@eecs.umich.edu 9947377Sgblack@eecs.umich.edu rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 9957377Sgblack@eecs.umich.edu acceptBroadcast = (reg & RFCR_AAB) ? true : false; 9967377Sgblack@eecs.umich.edu acceptMulticast = (reg & RFCR_AAM) ? true : false; 9977377Sgblack@eecs.umich.edu acceptUnicast = (reg & RFCR_AAU) ? true : false; 9987377Sgblack@eecs.umich.edu acceptPerfect = (reg & RFCR_APM) ? true : false; 9997377Sgblack@eecs.umich.edu acceptArp = (reg & RFCR_AARP) ? true : false; 10007377Sgblack@eecs.umich.edu multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 10017377Sgblack@eecs.umich.edu 10027377Sgblack@eecs.umich.edu#if 0 10037377Sgblack@eecs.umich.edu if (reg & RFCR_APAT) 10047377Sgblack@eecs.umich.edu panic("RFCR_APAT not implemented!\n"); 10057377Sgblack@eecs.umich.edu#endif 10067377Sgblack@eecs.umich.edu if (reg & RFCR_UHEN) 10077377Sgblack@eecs.umich.edu panic("Unicast hash filtering not used by drivers!\n"); 10087377Sgblack@eecs.umich.edu 10097377Sgblack@eecs.umich.edu if (reg & RFCR_ULM) 10107377Sgblack@eecs.umich.edu panic("RFCR_ULM not implemented!\n"); 10117377Sgblack@eecs.umich.edu 10127377Sgblack@eecs.umich.edu break; 10137377Sgblack@eecs.umich.edu 10147377Sgblack@eecs.umich.edu case RFDR: 10157377Sgblack@eecs.umich.edu rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 10167377Sgblack@eecs.umich.edu switch (rfaddr) { 10177377Sgblack@eecs.umich.edu case 0x000: 10187377Sgblack@eecs.umich.edu rom.perfectMatch[0] = (uint8_t)reg; 10197377Sgblack@eecs.umich.edu rom.perfectMatch[1] = (uint8_t)(reg >> 8); 10207377Sgblack@eecs.umich.edu break; 10217377Sgblack@eecs.umich.edu case 0x002: 10227377Sgblack@eecs.umich.edu rom.perfectMatch[2] = (uint8_t)reg; 10237377Sgblack@eecs.umich.edu rom.perfectMatch[3] = (uint8_t)(reg >> 8); 10247377Sgblack@eecs.umich.edu break; 10257377Sgblack@eecs.umich.edu case 0x004: 10267377Sgblack@eecs.umich.edu rom.perfectMatch[4] = (uint8_t)reg; 10277377Sgblack@eecs.umich.edu rom.perfectMatch[5] = (uint8_t)(reg >> 8); 10287377Sgblack@eecs.umich.edu break; 10297377Sgblack@eecs.umich.edu default: 10307377Sgblack@eecs.umich.edu 10317377Sgblack@eecs.umich.edu if (rfaddr >= FHASH_ADDR && 10327377Sgblack@eecs.umich.edu rfaddr < FHASH_ADDR + FHASH_SIZE) { 10337377Sgblack@eecs.umich.edu 10347377Sgblack@eecs.umich.edu // Only word-aligned writes supported 10357377Sgblack@eecs.umich.edu if (rfaddr % 2) 10367377Sgblack@eecs.umich.edu panic("unaligned write to filter hash table!"); 10377377Sgblack@eecs.umich.edu 10387377Sgblack@eecs.umich.edu rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 10397377Sgblack@eecs.umich.edu rom.filterHash[rfaddr - FHASH_ADDR + 1] 10407377Sgblack@eecs.umich.edu = (uint8_t)(reg >> 8); 10417377Sgblack@eecs.umich.edu break; 10427377Sgblack@eecs.umich.edu } 10437377Sgblack@eecs.umich.edu panic("writing RFDR for something other than pattern matching\ 10447377Sgblack@eecs.umich.edu or hashing! %#x\n", rfaddr); 10457377Sgblack@eecs.umich.edu } 10467377Sgblack@eecs.umich.edu 10477377Sgblack@eecs.umich.edu case BRAR: 10487377Sgblack@eecs.umich.edu regs.brar = reg; 10497377Sgblack@eecs.umich.edu break; 10507377Sgblack@eecs.umich.edu 10517377Sgblack@eecs.umich.edu case BRDR: 10527377Sgblack@eecs.umich.edu panic("the driver never uses BRDR, something is wrong!\n"); 10537377Sgblack@eecs.umich.edu 10547377Sgblack@eecs.umich.edu case SRR: 10557377Sgblack@eecs.umich.edu panic("SRR is read only register!\n"); 10567377Sgblack@eecs.umich.edu 10577322Sgblack@eecs.umich.edu case MIBC: 10587379Sgblack@eecs.umich.edu panic("the driver never uses MIBC, something is wrong!\n"); 10597379Sgblack@eecs.umich.edu 10607379Sgblack@eecs.umich.edu case VRCR: 10617379Sgblack@eecs.umich.edu regs.vrcr = reg; 10627379Sgblack@eecs.umich.edu break; 10637379Sgblack@eecs.umich.edu 10647379Sgblack@eecs.umich.edu case VTCR: 10657379Sgblack@eecs.umich.edu regs.vtcr = reg; 10667379Sgblack@eecs.umich.edu break; 10677379Sgblack@eecs.umich.edu 10687379Sgblack@eecs.umich.edu case VDR: 10697379Sgblack@eecs.umich.edu panic("the driver never uses VDR, something is wrong!\n"); 10707379Sgblack@eecs.umich.edu 10717379Sgblack@eecs.umich.edu case CCSR: 10727379Sgblack@eecs.umich.edu /* not going to implement clockrun stuff */ 10737379Sgblack@eecs.umich.edu regs.ccsr = reg; 10747379Sgblack@eecs.umich.edu break; 10757379Sgblack@eecs.umich.edu 10767379Sgblack@eecs.umich.edu case TBICR: 10777379Sgblack@eecs.umich.edu regs.tbicr = reg; 10787379Sgblack@eecs.umich.edu if (reg & TBICR_MR_LOOPBACK) 10797379Sgblack@eecs.umich.edu panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 10807379Sgblack@eecs.umich.edu 10817379Sgblack@eecs.umich.edu if (reg & TBICR_MR_AN_ENABLE) { 10827379Sgblack@eecs.umich.edu regs.tanlpar = regs.tanar; 10837379Sgblack@eecs.umich.edu regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 10847379Sgblack@eecs.umich.edu } 10857379Sgblack@eecs.umich.edu 10867379Sgblack@eecs.umich.edu#if 0 10877379Sgblack@eecs.umich.edu if (reg & TBICR_MR_RESTART_AN) ; 10887379Sgblack@eecs.umich.edu#endif 10897379Sgblack@eecs.umich.edu 10907379Sgblack@eecs.umich.edu break; 10917379Sgblack@eecs.umich.edu 10927379Sgblack@eecs.umich.edu case TBISR: 10937379Sgblack@eecs.umich.edu panic("TBISR is read only register!\n"); 10947379Sgblack@eecs.umich.edu 10957379Sgblack@eecs.umich.edu case TANAR: 10967379Sgblack@eecs.umich.edu // Only write the writable bits 10977379Sgblack@eecs.umich.edu regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 10987379Sgblack@eecs.umich.edu regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 10997379Sgblack@eecs.umich.edu 11007379Sgblack@eecs.umich.edu // Pause capability unimplemented 11017379Sgblack@eecs.umich.edu#if 0 11027379Sgblack@eecs.umich.edu if (reg & TANAR_PS2) ; 11037379Sgblack@eecs.umich.edu if (reg & TANAR_PS1) ; 11047379Sgblack@eecs.umich.edu#endif 11057379Sgblack@eecs.umich.edu 11067379Sgblack@eecs.umich.edu break; 11077379Sgblack@eecs.umich.edu 11087379Sgblack@eecs.umich.edu case TANLPAR: 11097379Sgblack@eecs.umich.edu panic("this should only be written to by the fake phy!\n"); 11107379Sgblack@eecs.umich.edu 11117379Sgblack@eecs.umich.edu case TANER: 11127379Sgblack@eecs.umich.edu panic("TANER is read only register!\n"); 11137379Sgblack@eecs.umich.edu 11147379Sgblack@eecs.umich.edu case TESR: 11157379Sgblack@eecs.umich.edu regs.tesr = reg; 11167379Sgblack@eecs.umich.edu break; 11177379Sgblack@eecs.umich.edu 11187379Sgblack@eecs.umich.edu default: 11197379Sgblack@eecs.umich.edu panic("invalid register access daddr=%#x", daddr); 11207379Sgblack@eecs.umich.edu } 11217379Sgblack@eecs.umich.edu } else { 11227379Sgblack@eecs.umich.edu panic("Invalid Request Size"); 11237380Sgblack@eecs.umich.edu } 11247379Sgblack@eecs.umich.edu pkt->result = Packet::Success; 11257379Sgblack@eecs.umich.edu return pioDelay; 11267379Sgblack@eecs.umich.edu} 11277379Sgblack@eecs.umich.edu 11287379Sgblack@eecs.umich.eduvoid 11297379Sgblack@eecs.umich.eduNSGigE::devIntrPost(uint32_t interrupts) 11307379Sgblack@eecs.umich.edu{ 11317379Sgblack@eecs.umich.edu if (interrupts & ISR_RESERVE) 11327379Sgblack@eecs.umich.edu panic("Cannot set a reserved interrupt"); 11337379Sgblack@eecs.umich.edu 11347379Sgblack@eecs.umich.edu if (interrupts & ISR_NOIMPL) 11357379Sgblack@eecs.umich.edu warn("interrupt not implemented %#x\n", interrupts); 11367379Sgblack@eecs.umich.edu 11377380Sgblack@eecs.umich.edu interrupts &= ISR_IMPL; 11387379Sgblack@eecs.umich.edu regs.isr |= interrupts; 11397379Sgblack@eecs.umich.edu 11407379Sgblack@eecs.umich.edu if (interrupts & regs.imr) { 11417379Sgblack@eecs.umich.edu if (interrupts & ISR_SWI) { 11427379Sgblack@eecs.umich.edu totalSwi++; 11437379Sgblack@eecs.umich.edu } 11447379Sgblack@eecs.umich.edu if (interrupts & ISR_RXIDLE) { 11457379Sgblack@eecs.umich.edu totalRxIdle++; 11467379Sgblack@eecs.umich.edu } 11477379Sgblack@eecs.umich.edu if (interrupts & ISR_RXOK) { 11487379Sgblack@eecs.umich.edu totalRxOk++; 11497379Sgblack@eecs.umich.edu } 11507379Sgblack@eecs.umich.edu if (interrupts & ISR_RXDESC) { 11517379Sgblack@eecs.umich.edu totalRxDesc++; 11527379Sgblack@eecs.umich.edu } 11537379Sgblack@eecs.umich.edu if (interrupts & ISR_TXOK) { 11547379Sgblack@eecs.umich.edu totalTxOk++; 11557379Sgblack@eecs.umich.edu } 11567379Sgblack@eecs.umich.edu if (interrupts & ISR_TXIDLE) { 11577379Sgblack@eecs.umich.edu totalTxIdle++; 11587379Sgblack@eecs.umich.edu } 11597379Sgblack@eecs.umich.edu if (interrupts & ISR_TXDESC) { 11607379Sgblack@eecs.umich.edu totalTxDesc++; 11617379Sgblack@eecs.umich.edu } 11627379Sgblack@eecs.umich.edu if (interrupts & ISR_RXORN) { 11637379Sgblack@eecs.umich.edu totalRxOrn++; 11647379Sgblack@eecs.umich.edu } 11657379Sgblack@eecs.umich.edu } 11667379Sgblack@eecs.umich.edu 11677379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 11687379Sgblack@eecs.umich.edu "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 11697379Sgblack@eecs.umich.edu interrupts, regs.isr, regs.imr); 11707379Sgblack@eecs.umich.edu 11717379Sgblack@eecs.umich.edu if ((regs.isr & regs.imr)) { 11727379Sgblack@eecs.umich.edu Tick when = curTick; 11737379Sgblack@eecs.umich.edu if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 11747379Sgblack@eecs.umich.edu when += intrDelay; 11757379Sgblack@eecs.umich.edu cpuIntrPost(when); 11767379Sgblack@eecs.umich.edu } 11777379Sgblack@eecs.umich.edu} 11787379Sgblack@eecs.umich.edu 11797379Sgblack@eecs.umich.edu/* writing this interrupt counting stats inside this means that this function 11807379Sgblack@eecs.umich.edu is now limited to being used to clear all interrupts upon the kernel 11817379Sgblack@eecs.umich.edu reading isr and servicing. just telling you in case you were thinking 11827379Sgblack@eecs.umich.edu of expanding use. 11837379Sgblack@eecs.umich.edu*/ 11847379Sgblack@eecs.umich.eduvoid 11857379Sgblack@eecs.umich.eduNSGigE::devIntrClear(uint32_t interrupts) 11867379Sgblack@eecs.umich.edu{ 11877379Sgblack@eecs.umich.edu if (interrupts & ISR_RESERVE) 11887379Sgblack@eecs.umich.edu panic("Cannot clear a reserved interrupt"); 11897379Sgblack@eecs.umich.edu 11907379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_SWI) { 11917379Sgblack@eecs.umich.edu postedSwi++; 11927379Sgblack@eecs.umich.edu } 11937379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXIDLE) { 11947379Sgblack@eecs.umich.edu postedRxIdle++; 11957379Sgblack@eecs.umich.edu } 11967379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXOK) { 11977379Sgblack@eecs.umich.edu postedRxOk++; 11987379Sgblack@eecs.umich.edu } 11997379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXDESC) { 12007379Sgblack@eecs.umich.edu postedRxDesc++; 12017379Sgblack@eecs.umich.edu } 12027379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXOK) { 12037379Sgblack@eecs.umich.edu postedTxOk++; 12047379Sgblack@eecs.umich.edu } 12057379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXIDLE) { 12067379Sgblack@eecs.umich.edu postedTxIdle++; 12077379Sgblack@eecs.umich.edu } 12087379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXDESC) { 12097379Sgblack@eecs.umich.edu postedTxDesc++; 12107379Sgblack@eecs.umich.edu } 12117379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXORN) { 12127379Sgblack@eecs.umich.edu postedRxOrn++; 12137379Sgblack@eecs.umich.edu } 12147379Sgblack@eecs.umich.edu 12157379Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_IMPL) 12167379Sgblack@eecs.umich.edu postedInterrupts++; 12177379Sgblack@eecs.umich.edu 12187379Sgblack@eecs.umich.edu interrupts &= ~ISR_NOIMPL; 12197379Sgblack@eecs.umich.edu regs.isr &= ~interrupts; 12207379Sgblack@eecs.umich.edu 12217379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 12227379Sgblack@eecs.umich.edu "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 12237379Sgblack@eecs.umich.edu interrupts, regs.isr, regs.imr); 12247379Sgblack@eecs.umich.edu 12257379Sgblack@eecs.umich.edu if (!(regs.isr & regs.imr)) 12267379Sgblack@eecs.umich.edu cpuIntrClear(); 12277379Sgblack@eecs.umich.edu} 12287379Sgblack@eecs.umich.edu 12297379Sgblack@eecs.umich.eduvoid 12307379Sgblack@eecs.umich.eduNSGigE::devIntrChangeMask() 12317379Sgblack@eecs.umich.edu{ 12327379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 12337379Sgblack@eecs.umich.edu regs.isr, regs.imr, regs.isr & regs.imr); 12347379Sgblack@eecs.umich.edu 12357379Sgblack@eecs.umich.edu if (regs.isr & regs.imr) 12367379Sgblack@eecs.umich.edu cpuIntrPost(curTick); 12377379Sgblack@eecs.umich.edu else 12387379Sgblack@eecs.umich.edu cpuIntrClear(); 12397379Sgblack@eecs.umich.edu} 12407379Sgblack@eecs.umich.edu 12417379Sgblack@eecs.umich.eduvoid 12427379Sgblack@eecs.umich.eduNSGigE::cpuIntrPost(Tick when) 12437379Sgblack@eecs.umich.edu{ 12447379Sgblack@eecs.umich.edu // If the interrupt you want to post is later than an interrupt 12457379Sgblack@eecs.umich.edu // already scheduled, just let it post in the coming one and don't 12467379Sgblack@eecs.umich.edu // schedule another. 12477379Sgblack@eecs.umich.edu // HOWEVER, must be sure that the scheduled intrTick is in the 12487379Sgblack@eecs.umich.edu // future (this was formerly the source of a bug) 12497379Sgblack@eecs.umich.edu /** 12507379Sgblack@eecs.umich.edu * @todo this warning should be removed and the intrTick code should 12517379Sgblack@eecs.umich.edu * be fixed. 12527379Sgblack@eecs.umich.edu */ 12537379Sgblack@eecs.umich.edu assert(when >= curTick); 12547379Sgblack@eecs.umich.edu assert(intrTick >= curTick || intrTick == 0); 12557379Sgblack@eecs.umich.edu if (when > intrTick && intrTick != 0) { 12567379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 12577379Sgblack@eecs.umich.edu intrTick); 12587379Sgblack@eecs.umich.edu return; 12597379Sgblack@eecs.umich.edu } 12607379Sgblack@eecs.umich.edu 12617379Sgblack@eecs.umich.edu intrTick = when; 12627379Sgblack@eecs.umich.edu if (intrTick < curTick) { 12637379Sgblack@eecs.umich.edu debug_break(); 12647379Sgblack@eecs.umich.edu intrTick = curTick; 12657379Sgblack@eecs.umich.edu } 12667379Sgblack@eecs.umich.edu 12677379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 12687379Sgblack@eecs.umich.edu intrTick); 12697379Sgblack@eecs.umich.edu 12707379Sgblack@eecs.umich.edu if (intrEvent) 12717379Sgblack@eecs.umich.edu intrEvent->squash(); 12727379Sgblack@eecs.umich.edu intrEvent = new IntrEvent(this, true); 12737379Sgblack@eecs.umich.edu intrEvent->schedule(intrTick); 12747379Sgblack@eecs.umich.edu} 12757379Sgblack@eecs.umich.edu 12767379Sgblack@eecs.umich.eduvoid 12777379Sgblack@eecs.umich.eduNSGigE::cpuInterrupt() 12787379Sgblack@eecs.umich.edu{ 12797379Sgblack@eecs.umich.edu assert(intrTick == curTick); 12807379Sgblack@eecs.umich.edu 12817379Sgblack@eecs.umich.edu // Whether or not there's a pending interrupt, we don't care about 12827379Sgblack@eecs.umich.edu // it anymore 12837379Sgblack@eecs.umich.edu intrEvent = 0; 12847379Sgblack@eecs.umich.edu intrTick = 0; 12857379Sgblack@eecs.umich.edu 12867379Sgblack@eecs.umich.edu // Don't send an interrupt if there's already one 12877379Sgblack@eecs.umich.edu if (cpuPendingIntr) { 12887379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 12897379Sgblack@eecs.umich.edu "would send an interrupt now, but there's already pending\n"); 12907379Sgblack@eecs.umich.edu } else { 12917379Sgblack@eecs.umich.edu // Send interrupt 12927379Sgblack@eecs.umich.edu cpuPendingIntr = true; 12937379Sgblack@eecs.umich.edu 12947379Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "posting interrupt\n"); 12957379Sgblack@eecs.umich.edu intrPost(); 12967379Sgblack@eecs.umich.edu } 1297} 1298 1299void 1300NSGigE::cpuIntrClear() 1301{ 1302 if (!cpuPendingIntr) 1303 return; 1304 1305 if (intrEvent) { 1306 intrEvent->squash(); 1307 intrEvent = 0; 1308 } 1309 1310 intrTick = 0; 1311 1312 cpuPendingIntr = false; 1313 1314 DPRINTF(EthernetIntr, "clearing interrupt\n"); 1315 intrClear(); 1316} 1317 1318bool 1319NSGigE::cpuIntrPending() const 1320{ return cpuPendingIntr; } 1321 1322void 1323NSGigE::txReset() 1324{ 1325 1326 DPRINTF(Ethernet, "transmit reset\n"); 1327 1328 CTDD = false; 1329 txEnable = false;; 1330 txFragPtr = 0; 1331 assert(txDescCnt == 0); 1332 txFifo.clear(); 1333 txState = txIdle; 1334 assert(txDmaState == dmaIdle); 1335} 1336 1337void 1338NSGigE::rxReset() 1339{ 1340 DPRINTF(Ethernet, "receive reset\n"); 1341 1342 CRDD = false; 1343 assert(rxPktBytes == 0); 1344 rxEnable = false; 1345 rxFragPtr = 0; 1346 assert(rxDescCnt == 0); 1347 assert(rxDmaState == dmaIdle); 1348 rxFifo.clear(); 1349 rxState = rxIdle; 1350} 1351 1352void 1353NSGigE::regsReset() 1354{ 1355 memset(®s, 0, sizeof(regs)); 1356 regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 1357 regs.mear = 0x12; 1358 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1359 // fill threshold to 32 bytes 1360 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1361 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1362 regs.mibc = MIBC_FRZ; 1363 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1364 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1365 regs.brar = 0xffffffff; 1366 1367 extstsEnable = false; 1368 acceptBroadcast = false; 1369 acceptMulticast = false; 1370 acceptUnicast = false; 1371 acceptPerfect = false; 1372 acceptArp = false; 1373} 1374 1375bool 1376NSGigE::doRxDmaRead() 1377{ 1378 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1379 rxDmaState = dmaReading; 1380 1381 if (dmaPending() || getState() != Running) 1382 rxDmaState = dmaReadWaiting; 1383 else 1384 dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 1385 1386 return true; 1387} 1388 1389void 1390NSGigE::rxDmaReadDone() 1391{ 1392 assert(rxDmaState == dmaReading); 1393 rxDmaState = dmaIdle; 1394 1395 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1396 rxDmaAddr, rxDmaLen); 1397 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1398 1399 // If the transmit state machine has a pending DMA, let it go first 1400 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1401 txKick(); 1402 1403 rxKick(); 1404} 1405 1406bool 1407NSGigE::doRxDmaWrite() 1408{ 1409 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1410 rxDmaState = dmaWriting; 1411 1412 if (dmaPending() || getState() != Running) 1413 rxDmaState = dmaWriteWaiting; 1414 else 1415 dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 1416 return true; 1417} 1418 1419void 1420NSGigE::rxDmaWriteDone() 1421{ 1422 assert(rxDmaState == dmaWriting); 1423 rxDmaState = dmaIdle; 1424 1425 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1426 rxDmaAddr, rxDmaLen); 1427 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1428 1429 // If the transmit state machine has a pending DMA, let it go first 1430 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1431 txKick(); 1432 1433 rxKick(); 1434} 1435 1436void 1437NSGigE::rxKick() 1438{ 1439 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1440 1441 DPRINTF(EthernetSM, 1442 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 1443 NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 1444 1445 Addr link, bufptr; 1446 uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 1447 uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1448 1449 next: 1450 if (clock) { 1451 if (rxKickTick > curTick) { 1452 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1453 rxKickTick); 1454 1455 goto exit; 1456 } 1457 1458 // Go to the next state machine clock tick. 1459 rxKickTick = curTick + cycles(1); 1460 } 1461 1462 switch(rxDmaState) { 1463 case dmaReadWaiting: 1464 if (doRxDmaRead()) 1465 goto exit; 1466 break; 1467 case dmaWriteWaiting: 1468 if (doRxDmaWrite()) 1469 goto exit; 1470 break; 1471 default: 1472 break; 1473 } 1474 1475 link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 1476 bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 1477 1478 // see state machine from spec for details 1479 // the way this works is, if you finish work on one state and can 1480 // go directly to another, you do that through jumping to the 1481 // label "next". however, if you have intermediate work, like DMA 1482 // so that you can't go to the next state yet, you go to exit and 1483 // exit the loop. however, when the DMA is done it will trigger 1484 // an event and come back to this loop. 1485 switch (rxState) { 1486 case rxIdle: 1487 if (!rxEnable) { 1488 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1489 goto exit; 1490 } 1491 1492 if (CRDD) { 1493 rxState = rxDescRefr; 1494 1495 rxDmaAddr = regs.rxdp & 0x3fffffff; 1496 rxDmaData = 1497 is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 1498 rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1499 rxDmaFree = dmaDescFree; 1500 1501 descDmaReads++; 1502 descDmaRdBytes += rxDmaLen; 1503 1504 if (doRxDmaRead()) 1505 goto exit; 1506 } else { 1507 rxState = rxDescRead; 1508 1509 rxDmaAddr = regs.rxdp & 0x3fffffff; 1510 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1511 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1512 rxDmaFree = dmaDescFree; 1513 1514 descDmaReads++; 1515 descDmaRdBytes += rxDmaLen; 1516 1517 if (doRxDmaRead()) 1518 goto exit; 1519 } 1520 break; 1521 1522 case rxDescRefr: 1523 if (rxDmaState != dmaIdle) 1524 goto exit; 1525 1526 rxState = rxAdvance; 1527 break; 1528 1529 case rxDescRead: 1530 if (rxDmaState != dmaIdle) 1531 goto exit; 1532 1533 DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 1534 regs.rxdp & 0x3fffffff); 1535 DPRINTF(EthernetDesc, 1536 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 1537 link, bufptr, cmdsts, extsts); 1538 1539 if (cmdsts & CMDSTS_OWN) { 1540 devIntrPost(ISR_RXIDLE); 1541 rxState = rxIdle; 1542 goto exit; 1543 } else { 1544 rxState = rxFifoBlock; 1545 rxFragPtr = bufptr; 1546 rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1547 } 1548 break; 1549 1550 case rxFifoBlock: 1551 if (!rxPacket) { 1552 /** 1553 * @todo in reality, we should be able to start processing 1554 * the packet as it arrives, and not have to wait for the 1555 * full packet ot be in the receive fifo. 1556 */ 1557 if (rxFifo.empty()) 1558 goto exit; 1559 1560 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1561 1562 // If we don't have a packet, grab a new one from the fifo. 1563 rxPacket = rxFifo.front(); 1564 rxPktBytes = rxPacket->length; 1565 rxPacketBufPtr = rxPacket->data; 1566 1567#if TRACING_ON 1568 if (DTRACE(Ethernet)) { 1569 IpPtr ip(rxPacket); 1570 if (ip) { 1571 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1572 TcpPtr tcp(ip); 1573 if (tcp) { 1574 DPRINTF(Ethernet, 1575 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1576 tcp->sport(), tcp->dport(), tcp->seq(), 1577 tcp->ack()); 1578 } 1579 } 1580 } 1581#endif 1582 1583 // sanity check - i think the driver behaves like this 1584 assert(rxDescCnt >= rxPktBytes); 1585 rxFifo.pop(); 1586 } 1587 1588 1589 // dont' need the && rxDescCnt > 0 if driver sanity check 1590 // above holds 1591 if (rxPktBytes > 0) { 1592 rxState = rxFragWrite; 1593 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1594 // check holds 1595 rxXferLen = rxPktBytes; 1596 1597 rxDmaAddr = rxFragPtr & 0x3fffffff; 1598 rxDmaData = rxPacketBufPtr; 1599 rxDmaLen = rxXferLen; 1600 rxDmaFree = dmaDataFree; 1601 1602 if (doRxDmaWrite()) 1603 goto exit; 1604 1605 } else { 1606 rxState = rxDescWrite; 1607 1608 //if (rxPktBytes == 0) { /* packet is done */ 1609 assert(rxPktBytes == 0); 1610 DPRINTF(EthernetSM, "done with receiving packet\n"); 1611 1612 cmdsts |= CMDSTS_OWN; 1613 cmdsts &= ~CMDSTS_MORE; 1614 cmdsts |= CMDSTS_OK; 1615 cmdsts &= 0xffff0000; 1616 cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1617 1618#if 0 1619 /* 1620 * all the driver uses these are for its own stats keeping 1621 * which we don't care about, aren't necessary for 1622 * functionality and doing this would just slow us down. 1623 * if they end up using this in a later version for 1624 * functional purposes, just undef 1625 */ 1626 if (rxFilterEnable) { 1627 cmdsts &= ~CMDSTS_DEST_MASK; 1628 const EthAddr &dst = rxFifoFront()->dst(); 1629 if (dst->unicast()) 1630 cmdsts |= CMDSTS_DEST_SELF; 1631 if (dst->multicast()) 1632 cmdsts |= CMDSTS_DEST_MULTI; 1633 if (dst->broadcast()) 1634 cmdsts |= CMDSTS_DEST_MASK; 1635 } 1636#endif 1637 1638 IpPtr ip(rxPacket); 1639 if (extstsEnable && ip) { 1640 extsts |= EXTSTS_IPPKT; 1641 rxIpChecksums++; 1642 if (cksum(ip) != 0) { 1643 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1644 extsts |= EXTSTS_IPERR; 1645 } 1646 TcpPtr tcp(ip); 1647 UdpPtr udp(ip); 1648 if (tcp) { 1649 extsts |= EXTSTS_TCPPKT; 1650 rxTcpChecksums++; 1651 if (cksum(tcp) != 0) { 1652 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1653 extsts |= EXTSTS_TCPERR; 1654 1655 } 1656 } else if (udp) { 1657 extsts |= EXTSTS_UDPPKT; 1658 rxUdpChecksums++; 1659 if (cksum(udp) != 0) { 1660 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1661 extsts |= EXTSTS_UDPERR; 1662 } 1663 } 1664 } 1665 rxPacket = 0; 1666 1667 /* 1668 * the driver seems to always receive into desc buffers 1669 * of size 1514, so you never have a pkt that is split 1670 * into multiple descriptors on the receive side, so 1671 * i don't implement that case, hence the assert above. 1672 */ 1673 1674 DPRINTF(EthernetDesc, 1675 "rxDesc: addr=%08x writeback cmdsts extsts\n", 1676 regs.rxdp & 0x3fffffff); 1677 DPRINTF(EthernetDesc, 1678 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 1679 link, bufptr, cmdsts, extsts); 1680 1681 rxDmaAddr = regs.rxdp & 0x3fffffff; 1682 rxDmaData = &cmdsts; 1683 if (is64bit) { 1684 rxDmaAddr += offsetof(ns_desc64, cmdsts); 1685 rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 1686 } else { 1687 rxDmaAddr += offsetof(ns_desc32, cmdsts); 1688 rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 1689 } 1690 rxDmaFree = dmaDescFree; 1691 1692 descDmaWrites++; 1693 descDmaWrBytes += rxDmaLen; 1694 1695 if (doRxDmaWrite()) 1696 goto exit; 1697 } 1698 break; 1699 1700 case rxFragWrite: 1701 if (rxDmaState != dmaIdle) 1702 goto exit; 1703 1704 rxPacketBufPtr += rxXferLen; 1705 rxFragPtr += rxXferLen; 1706 rxPktBytes -= rxXferLen; 1707 1708 rxState = rxFifoBlock; 1709 break; 1710 1711 case rxDescWrite: 1712 if (rxDmaState != dmaIdle) 1713 goto exit; 1714 1715 assert(cmdsts & CMDSTS_OWN); 1716 1717 assert(rxPacket == 0); 1718 devIntrPost(ISR_RXOK); 1719 1720 if (cmdsts & CMDSTS_INTR) 1721 devIntrPost(ISR_RXDESC); 1722 1723 if (!rxEnable) { 1724 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1725 rxState = rxIdle; 1726 goto exit; 1727 } else 1728 rxState = rxAdvance; 1729 break; 1730 1731 case rxAdvance: 1732 if (link == 0) { 1733 devIntrPost(ISR_RXIDLE); 1734 rxState = rxIdle; 1735 CRDD = true; 1736 goto exit; 1737 } else { 1738 if (rxDmaState != dmaIdle) 1739 goto exit; 1740 rxState = rxDescRead; 1741 regs.rxdp = link; 1742 CRDD = false; 1743 1744 rxDmaAddr = regs.rxdp & 0x3fffffff; 1745 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1746 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1747 rxDmaFree = dmaDescFree; 1748 1749 if (doRxDmaRead()) 1750 goto exit; 1751 } 1752 break; 1753 1754 default: 1755 panic("Invalid rxState!"); 1756 } 1757 1758 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1759 NsRxStateStrings[rxState]); 1760 goto next; 1761 1762 exit: 1763 /** 1764 * @todo do we want to schedule a future kick? 1765 */ 1766 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1767 NsRxStateStrings[rxState]); 1768 1769 if (clock && !rxKickEvent.scheduled()) 1770 rxKickEvent.schedule(rxKickTick); 1771} 1772 1773void 1774NSGigE::transmit() 1775{ 1776 if (txFifo.empty()) { 1777 DPRINTF(Ethernet, "nothing to transmit\n"); 1778 return; 1779 } 1780 1781 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1782 txFifo.size()); 1783 if (interface->sendPacket(txFifo.front())) { 1784#if TRACING_ON 1785 if (DTRACE(Ethernet)) { 1786 IpPtr ip(txFifo.front()); 1787 if (ip) { 1788 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1789 TcpPtr tcp(ip); 1790 if (tcp) { 1791 DPRINTF(Ethernet, 1792 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1793 tcp->sport(), tcp->dport(), tcp->seq(), 1794 tcp->ack()); 1795 } 1796 } 1797 } 1798#endif 1799 1800 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1801 txBytes += txFifo.front()->length; 1802 txPackets++; 1803 1804 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1805 txFifo.avail()); 1806 txFifo.pop(); 1807 1808 /* 1809 * normally do a writeback of the descriptor here, and ONLY 1810 * after that is done, send this interrupt. but since our 1811 * stuff never actually fails, just do this interrupt here, 1812 * otherwise the code has to stray from this nice format. 1813 * besides, it's functionally the same. 1814 */ 1815 devIntrPost(ISR_TXOK); 1816 } 1817 1818 if (!txFifo.empty() && !txEvent.scheduled()) { 1819 DPRINTF(Ethernet, "reschedule transmit\n"); 1820 txEvent.schedule(curTick + retryTime); 1821 } 1822} 1823 1824bool 1825NSGigE::doTxDmaRead() 1826{ 1827 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1828 txDmaState = dmaReading; 1829 1830 if (dmaPending() || getState() != Running) 1831 txDmaState = dmaReadWaiting; 1832 else 1833 dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 1834 1835 return true; 1836} 1837 1838void 1839NSGigE::txDmaReadDone() 1840{ 1841 assert(txDmaState == dmaReading); 1842 txDmaState = dmaIdle; 1843 1844 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1845 txDmaAddr, txDmaLen); 1846 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1847 1848 // If the receive state machine has a pending DMA, let it go first 1849 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1850 rxKick(); 1851 1852 txKick(); 1853} 1854 1855bool 1856NSGigE::doTxDmaWrite() 1857{ 1858 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1859 txDmaState = dmaWriting; 1860 1861 if (dmaPending() || getState() != Running) 1862 txDmaState = dmaWriteWaiting; 1863 else 1864 dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1865 return true; 1866} 1867 1868void 1869NSGigE::txDmaWriteDone() 1870{ 1871 assert(txDmaState == dmaWriting); 1872 txDmaState = dmaIdle; 1873 1874 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1875 txDmaAddr, txDmaLen); 1876 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1877 1878 // If the receive state machine has a pending DMA, let it go first 1879 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1880 rxKick(); 1881 1882 txKick(); 1883} 1884 1885void 1886NSGigE::txKick() 1887{ 1888 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1889 1890 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 1891 NsTxStateStrings[txState], is64bit ? 64 : 32); 1892 1893 Addr link, bufptr; 1894 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 1895 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1896 1897 next: 1898 if (clock) { 1899 if (txKickTick > curTick) { 1900 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1901 txKickTick); 1902 goto exit; 1903 } 1904 1905 // Go to the next state machine clock tick. 1906 txKickTick = curTick + cycles(1); 1907 } 1908 1909 switch(txDmaState) { 1910 case dmaReadWaiting: 1911 if (doTxDmaRead()) 1912 goto exit; 1913 break; 1914 case dmaWriteWaiting: 1915 if (doTxDmaWrite()) 1916 goto exit; 1917 break; 1918 default: 1919 break; 1920 } 1921 1922 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 1923 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1924 switch (txState) { 1925 case txIdle: 1926 if (!txEnable) { 1927 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1928 goto exit; 1929 } 1930 1931 if (CTDD) { 1932 txState = txDescRefr; 1933 1934 txDmaAddr = regs.txdp & 0x3fffffff; 1935 txDmaData = 1936 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 1937 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1938 txDmaFree = dmaDescFree; 1939 1940 descDmaReads++; 1941 descDmaRdBytes += txDmaLen; 1942 1943 if (doTxDmaRead()) 1944 goto exit; 1945 1946 } else { 1947 txState = txDescRead; 1948 1949 txDmaAddr = regs.txdp & 0x3fffffff; 1950 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 1951 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1952 txDmaFree = dmaDescFree; 1953 1954 descDmaReads++; 1955 descDmaRdBytes += txDmaLen; 1956 1957 if (doTxDmaRead()) 1958 goto exit; 1959 } 1960 break; 1961 1962 case txDescRefr: 1963 if (txDmaState != dmaIdle) 1964 goto exit; 1965 1966 txState = txAdvance; 1967 break; 1968 1969 case txDescRead: 1970 if (txDmaState != dmaIdle) 1971 goto exit; 1972 1973 DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 1974 regs.txdp & 0x3fffffff); 1975 DPRINTF(EthernetDesc, 1976 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 1977 link, bufptr, cmdsts, extsts); 1978 1979 if (cmdsts & CMDSTS_OWN) { 1980 txState = txFifoBlock; 1981 txFragPtr = bufptr; 1982 txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1983 } else { 1984 devIntrPost(ISR_TXIDLE); 1985 txState = txIdle; 1986 goto exit; 1987 } 1988 break; 1989 1990 case txFifoBlock: 1991 if (!txPacket) { 1992 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 1993 txPacket = new EthPacketData(16384); 1994 txPacketBufPtr = txPacket->data; 1995 } 1996 1997 if (txDescCnt == 0) { 1998 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 1999 if (cmdsts & CMDSTS_MORE) { 2000 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2001 txState = txDescWrite; 2002 2003 cmdsts &= ~CMDSTS_OWN; 2004 2005 txDmaAddr = regs.txdp & 0x3fffffff; 2006 txDmaData = &cmdsts; 2007 if (is64bit) { 2008 txDmaAddr += offsetof(ns_desc64, cmdsts); 2009 txDmaLen = sizeof(txDesc64.cmdsts); 2010 } else { 2011 txDmaAddr += offsetof(ns_desc32, cmdsts); 2012 txDmaLen = sizeof(txDesc32.cmdsts); 2013 } 2014 txDmaFree = dmaDescFree; 2015 2016 if (doTxDmaWrite()) 2017 goto exit; 2018 2019 } else { /* this packet is totally done */ 2020 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2021 /* deal with the the packet that just finished */ 2022 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2023 IpPtr ip(txPacket); 2024 if (extsts & EXTSTS_UDPPKT) { 2025 UdpPtr udp(ip); 2026 udp->sum(0); 2027 udp->sum(cksum(udp)); 2028 txUdpChecksums++; 2029 } else if (extsts & EXTSTS_TCPPKT) { 2030 TcpPtr tcp(ip); 2031 tcp->sum(0); 2032 tcp->sum(cksum(tcp)); 2033 txTcpChecksums++; 2034 } 2035 if (extsts & EXTSTS_IPPKT) { 2036 ip->sum(0); 2037 ip->sum(cksum(ip)); 2038 txIpChecksums++; 2039 } 2040 } 2041 2042 txPacket->length = txPacketBufPtr - txPacket->data; 2043 // this is just because the receive can't handle a 2044 // packet bigger want to make sure 2045 if (txPacket->length > 1514) 2046 panic("transmit packet too large, %s > 1514\n", 2047 txPacket->length); 2048 2049#ifndef NDEBUG 2050 bool success = 2051#endif 2052 txFifo.push(txPacket); 2053 assert(success); 2054 2055 /* 2056 * this following section is not tqo spec, but 2057 * functionally shouldn't be any different. normally, 2058 * the chip will wait til the transmit has occurred 2059 * before writing back the descriptor because it has 2060 * to wait to see that it was successfully transmitted 2061 * to decide whether to set CMDSTS_OK or not. 2062 * however, in the simulator since it is always 2063 * successfully transmitted, and writing it exactly to 2064 * spec would complicate the code, we just do it here 2065 */ 2066 2067 cmdsts &= ~CMDSTS_OWN; 2068 cmdsts |= CMDSTS_OK; 2069 2070 DPRINTF(EthernetDesc, 2071 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2072 cmdsts, extsts); 2073 2074 txDmaFree = dmaDescFree; 2075 txDmaAddr = regs.txdp & 0x3fffffff; 2076 txDmaData = &cmdsts; 2077 if (is64bit) { 2078 txDmaAddr += offsetof(ns_desc64, cmdsts); 2079 txDmaLen = 2080 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 2081 } else { 2082 txDmaAddr += offsetof(ns_desc32, cmdsts); 2083 txDmaLen = 2084 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 2085 } 2086 2087 descDmaWrites++; 2088 descDmaWrBytes += txDmaLen; 2089 2090 transmit(); 2091 txPacket = 0; 2092 2093 if (!txEnable) { 2094 DPRINTF(EthernetSM, "halting TX state machine\n"); 2095 txState = txIdle; 2096 goto exit; 2097 } else 2098 txState = txAdvance; 2099 2100 if (doTxDmaWrite()) 2101 goto exit; 2102 } 2103 } else { 2104 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2105 if (!txFifo.full()) { 2106 txState = txFragRead; 2107 2108 /* 2109 * The number of bytes transferred is either whatever 2110 * is left in the descriptor (txDescCnt), or if there 2111 * is not enough room in the fifo, just whatever room 2112 * is left in the fifo 2113 */ 2114 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2115 2116 txDmaAddr = txFragPtr & 0x3fffffff; 2117 txDmaData = txPacketBufPtr; 2118 txDmaLen = txXferLen; 2119 txDmaFree = dmaDataFree; 2120 2121 if (doTxDmaRead()) 2122 goto exit; 2123 } else { 2124 txState = txFifoBlock; 2125 transmit(); 2126 2127 goto exit; 2128 } 2129 2130 } 2131 break; 2132 2133 case txFragRead: 2134 if (txDmaState != dmaIdle) 2135 goto exit; 2136 2137 txPacketBufPtr += txXferLen; 2138 txFragPtr += txXferLen; 2139 txDescCnt -= txXferLen; 2140 txFifo.reserve(txXferLen); 2141 2142 txState = txFifoBlock; 2143 break; 2144 2145 case txDescWrite: 2146 if (txDmaState != dmaIdle) 2147 goto exit; 2148 2149 if (cmdsts & CMDSTS_INTR) 2150 devIntrPost(ISR_TXDESC); 2151 2152 if (!txEnable) { 2153 DPRINTF(EthernetSM, "halting TX state machine\n"); 2154 txState = txIdle; 2155 goto exit; 2156 } else 2157 txState = txAdvance; 2158 break; 2159 2160 case txAdvance: 2161 if (link == 0) { 2162 devIntrPost(ISR_TXIDLE); 2163 txState = txIdle; 2164 goto exit; 2165 } else { 2166 if (txDmaState != dmaIdle) 2167 goto exit; 2168 txState = txDescRead; 2169 regs.txdp = link; 2170 CTDD = false; 2171 2172 txDmaAddr = link & 0x3fffffff; 2173 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 2174 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 2175 txDmaFree = dmaDescFree; 2176 2177 if (doTxDmaRead()) 2178 goto exit; 2179 } 2180 break; 2181 2182 default: 2183 panic("invalid state"); 2184 } 2185 2186 DPRINTF(EthernetSM, "entering next txState=%s\n", 2187 NsTxStateStrings[txState]); 2188 goto next; 2189 2190 exit: 2191 /** 2192 * @todo do we want to schedule a future kick? 2193 */ 2194 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2195 NsTxStateStrings[txState]); 2196 2197 if (clock && !txKickEvent.scheduled()) 2198 txKickEvent.schedule(txKickTick); 2199} 2200 2201/** 2202 * Advance the EEPROM state machine 2203 * Called on rising edge of EEPROM clock bit in MEAR 2204 */ 2205void 2206NSGigE::eepromKick() 2207{ 2208 switch (eepromState) { 2209 2210 case eepromStart: 2211 2212 // Wait for start bit 2213 if (regs.mear & MEAR_EEDI) { 2214 // Set up to get 2 opcode bits 2215 eepromState = eepromGetOpcode; 2216 eepromBitsToRx = 2; 2217 eepromOpcode = 0; 2218 } 2219 break; 2220 2221 case eepromGetOpcode: 2222 eepromOpcode <<= 1; 2223 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 2224 --eepromBitsToRx; 2225 2226 // Done getting opcode 2227 if (eepromBitsToRx == 0) { 2228 if (eepromOpcode != EEPROM_READ) 2229 panic("only EEPROM reads are implemented!"); 2230 2231 // Set up to get address 2232 eepromState = eepromGetAddress; 2233 eepromBitsToRx = 6; 2234 eepromAddress = 0; 2235 } 2236 break; 2237 2238 case eepromGetAddress: 2239 eepromAddress <<= 1; 2240 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 2241 --eepromBitsToRx; 2242 2243 // Done getting address 2244 if (eepromBitsToRx == 0) { 2245 2246 if (eepromAddress >= EEPROM_SIZE) 2247 panic("EEPROM read access out of range!"); 2248 2249 switch (eepromAddress) { 2250 2251 case EEPROM_PMATCH2_ADDR: 2252 eepromData = rom.perfectMatch[5]; 2253 eepromData <<= 8; 2254 eepromData += rom.perfectMatch[4]; 2255 break; 2256 2257 case EEPROM_PMATCH1_ADDR: 2258 eepromData = rom.perfectMatch[3]; 2259 eepromData <<= 8; 2260 eepromData += rom.perfectMatch[2]; 2261 break; 2262 2263 case EEPROM_PMATCH0_ADDR: 2264 eepromData = rom.perfectMatch[1]; 2265 eepromData <<= 8; 2266 eepromData += rom.perfectMatch[0]; 2267 break; 2268 2269 default: 2270 panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 2271 } 2272 // Set up to read data 2273 eepromState = eepromRead; 2274 eepromBitsToRx = 16; 2275 2276 // Clear data in bit 2277 regs.mear &= ~MEAR_EEDI; 2278 } 2279 break; 2280 2281 case eepromRead: 2282 // Clear Data Out bit 2283 regs.mear &= ~MEAR_EEDO; 2284 // Set bit to value of current EEPROM bit 2285 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 2286 2287 eepromData <<= 1; 2288 --eepromBitsToRx; 2289 2290 // All done 2291 if (eepromBitsToRx == 0) { 2292 eepromState = eepromStart; 2293 } 2294 break; 2295 2296 default: 2297 panic("invalid EEPROM state"); 2298 } 2299 2300} 2301 2302void 2303NSGigE::transferDone() 2304{ 2305 if (txFifo.empty()) { 2306 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2307 return; 2308 } 2309 2310 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2311 2312 if (txEvent.scheduled()) 2313 txEvent.reschedule(curTick + cycles(1)); 2314 else 2315 txEvent.schedule(curTick + cycles(1)); 2316} 2317 2318bool 2319NSGigE::rxFilter(const EthPacketPtr &packet) 2320{ 2321 EthPtr eth = packet; 2322 bool drop = true; 2323 string type; 2324 2325 const EthAddr &dst = eth->dst(); 2326 if (dst.unicast()) { 2327 // If we're accepting all unicast addresses 2328 if (acceptUnicast) 2329 drop = false; 2330 2331 // If we make a perfect match 2332 if (acceptPerfect && dst == rom.perfectMatch) 2333 drop = false; 2334 2335 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2336 drop = false; 2337 2338 } else if (dst.broadcast()) { 2339 // if we're accepting broadcasts 2340 if (acceptBroadcast) 2341 drop = false; 2342 2343 } else if (dst.multicast()) { 2344 // if we're accepting all multicasts 2345 if (acceptMulticast) 2346 drop = false; 2347 2348 // Multicast hashing faked - all packets accepted 2349 if (multicastHashEnable) 2350 drop = false; 2351 } 2352 2353 if (drop) { 2354 DPRINTF(Ethernet, "rxFilter drop\n"); 2355 DDUMP(EthernetData, packet->data, packet->length); 2356 } 2357 2358 return drop; 2359} 2360 2361bool 2362NSGigE::recvPacket(EthPacketPtr packet) 2363{ 2364 rxBytes += packet->length; 2365 rxPackets++; 2366 2367 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2368 rxFifo.avail()); 2369 2370 if (!rxEnable) { 2371 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2372 return true; 2373 } 2374 2375 if (!rxFilterEnable) { 2376 DPRINTF(Ethernet, 2377 "receive packet filtering disabled . . . packet dropped\n"); 2378 return true; 2379 } 2380 2381 if (rxFilter(packet)) { 2382 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2383 return true; 2384 } 2385 2386 if (rxFifo.avail() < packet->length) { 2387#if TRACING_ON 2388 IpPtr ip(packet); 2389 TcpPtr tcp(ip); 2390 if (ip) { 2391 DPRINTF(Ethernet, 2392 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2393 ip->id()); 2394 if (tcp) { 2395 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2396 } 2397 } 2398#endif 2399 droppedPackets++; 2400 devIntrPost(ISR_RXORN); 2401 return false; 2402 } 2403 2404 rxFifo.push(packet); 2405 2406 rxKick(); 2407 return true; 2408} 2409 2410 2411void 2412NSGigE::resume() 2413{ 2414 SimObject::resume(); 2415 2416 // During drain we could have left the state machines in a waiting state and 2417 // they wouldn't get out until some other event occured to kick them. 2418 // This way they'll get out immediately 2419 txKick(); 2420 rxKick(); 2421} 2422 2423 2424//===================================================================== 2425// 2426// 2427void 2428NSGigE::serialize(ostream &os) 2429{ 2430 // Serialize the PciDev base class 2431 PciDev::serialize(os); 2432 2433 /* 2434 * Finalize any DMA events now. 2435 */ 2436 // @todo will mem system save pending dma? 2437 2438 /* 2439 * Serialize the device registers 2440 */ 2441 SERIALIZE_SCALAR(regs.command); 2442 SERIALIZE_SCALAR(regs.config); 2443 SERIALIZE_SCALAR(regs.mear); 2444 SERIALIZE_SCALAR(regs.ptscr); 2445 SERIALIZE_SCALAR(regs.isr); 2446 SERIALIZE_SCALAR(regs.imr); 2447 SERIALIZE_SCALAR(regs.ier); 2448 SERIALIZE_SCALAR(regs.ihr); 2449 SERIALIZE_SCALAR(regs.txdp); 2450 SERIALIZE_SCALAR(regs.txdp_hi); 2451 SERIALIZE_SCALAR(regs.txcfg); 2452 SERIALIZE_SCALAR(regs.gpior); 2453 SERIALIZE_SCALAR(regs.rxdp); 2454 SERIALIZE_SCALAR(regs.rxdp_hi); 2455 SERIALIZE_SCALAR(regs.rxcfg); 2456 SERIALIZE_SCALAR(regs.pqcr); 2457 SERIALIZE_SCALAR(regs.wcsr); 2458 SERIALIZE_SCALAR(regs.pcr); 2459 SERIALIZE_SCALAR(regs.rfcr); 2460 SERIALIZE_SCALAR(regs.rfdr); 2461 SERIALIZE_SCALAR(regs.brar); 2462 SERIALIZE_SCALAR(regs.brdr); 2463 SERIALIZE_SCALAR(regs.srr); 2464 SERIALIZE_SCALAR(regs.mibc); 2465 SERIALIZE_SCALAR(regs.vrcr); 2466 SERIALIZE_SCALAR(regs.vtcr); 2467 SERIALIZE_SCALAR(regs.vdr); 2468 SERIALIZE_SCALAR(regs.ccsr); 2469 SERIALIZE_SCALAR(regs.tbicr); 2470 SERIALIZE_SCALAR(regs.tbisr); 2471 SERIALIZE_SCALAR(regs.tanar); 2472 SERIALIZE_SCALAR(regs.tanlpar); 2473 SERIALIZE_SCALAR(regs.taner); 2474 SERIALIZE_SCALAR(regs.tesr); 2475 2476 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2477 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2478 2479 SERIALIZE_SCALAR(ioEnable); 2480 2481 /* 2482 * Serialize the data Fifos 2483 */ 2484 rxFifo.serialize("rxFifo", os); 2485 txFifo.serialize("txFifo", os); 2486 2487 /* 2488 * Serialize the various helper variables 2489 */ 2490 bool txPacketExists = txPacket; 2491 SERIALIZE_SCALAR(txPacketExists); 2492 if (txPacketExists) { 2493 txPacket->length = txPacketBufPtr - txPacket->data; 2494 txPacket->serialize("txPacket", os); 2495 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2496 SERIALIZE_SCALAR(txPktBufPtr); 2497 } 2498 2499 bool rxPacketExists = rxPacket; 2500 SERIALIZE_SCALAR(rxPacketExists); 2501 if (rxPacketExists) { 2502 rxPacket->serialize("rxPacket", os); 2503 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2504 SERIALIZE_SCALAR(rxPktBufPtr); 2505 } 2506 2507 SERIALIZE_SCALAR(txXferLen); 2508 SERIALIZE_SCALAR(rxXferLen); 2509 2510 /* 2511 * Serialize Cached Descriptors 2512 */ 2513 SERIALIZE_SCALAR(rxDesc64.link); 2514 SERIALIZE_SCALAR(rxDesc64.bufptr); 2515 SERIALIZE_SCALAR(rxDesc64.cmdsts); 2516 SERIALIZE_SCALAR(rxDesc64.extsts); 2517 SERIALIZE_SCALAR(txDesc64.link); 2518 SERIALIZE_SCALAR(txDesc64.bufptr); 2519 SERIALIZE_SCALAR(txDesc64.cmdsts); 2520 SERIALIZE_SCALAR(txDesc64.extsts); 2521 SERIALIZE_SCALAR(rxDesc32.link); 2522 SERIALIZE_SCALAR(rxDesc32.bufptr); 2523 SERIALIZE_SCALAR(rxDesc32.cmdsts); 2524 SERIALIZE_SCALAR(rxDesc32.extsts); 2525 SERIALIZE_SCALAR(txDesc32.link); 2526 SERIALIZE_SCALAR(txDesc32.bufptr); 2527 SERIALIZE_SCALAR(txDesc32.cmdsts); 2528 SERIALIZE_SCALAR(txDesc32.extsts); 2529 SERIALIZE_SCALAR(extstsEnable); 2530 2531 /* 2532 * Serialize tx state machine 2533 */ 2534 int txState = this->txState; 2535 SERIALIZE_SCALAR(txState); 2536 SERIALIZE_SCALAR(txEnable); 2537 SERIALIZE_SCALAR(CTDD); 2538 SERIALIZE_SCALAR(txFragPtr); 2539 SERIALIZE_SCALAR(txDescCnt); 2540 int txDmaState = this->txDmaState; 2541 SERIALIZE_SCALAR(txDmaState); 2542 SERIALIZE_SCALAR(txKickTick); 2543 2544 /* 2545 * Serialize rx state machine 2546 */ 2547 int rxState = this->rxState; 2548 SERIALIZE_SCALAR(rxState); 2549 SERIALIZE_SCALAR(rxEnable); 2550 SERIALIZE_SCALAR(CRDD); 2551 SERIALIZE_SCALAR(rxPktBytes); 2552 SERIALIZE_SCALAR(rxFragPtr); 2553 SERIALIZE_SCALAR(rxDescCnt); 2554 int rxDmaState = this->rxDmaState; 2555 SERIALIZE_SCALAR(rxDmaState); 2556 SERIALIZE_SCALAR(rxKickTick); 2557 2558 /* 2559 * Serialize EEPROM state machine 2560 */ 2561 int eepromState = this->eepromState; 2562 SERIALIZE_SCALAR(eepromState); 2563 SERIALIZE_SCALAR(eepromClk); 2564 SERIALIZE_SCALAR(eepromBitsToRx); 2565 SERIALIZE_SCALAR(eepromOpcode); 2566 SERIALIZE_SCALAR(eepromAddress); 2567 SERIALIZE_SCALAR(eepromData); 2568 2569 /* 2570 * If there's a pending transmit, store the time so we can 2571 * reschedule it later 2572 */ 2573 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2574 SERIALIZE_SCALAR(transmitTick); 2575 2576 /* 2577 * receive address filter settings 2578 */ 2579 SERIALIZE_SCALAR(rxFilterEnable); 2580 SERIALIZE_SCALAR(acceptBroadcast); 2581 SERIALIZE_SCALAR(acceptMulticast); 2582 SERIALIZE_SCALAR(acceptUnicast); 2583 SERIALIZE_SCALAR(acceptPerfect); 2584 SERIALIZE_SCALAR(acceptArp); 2585 SERIALIZE_SCALAR(multicastHashEnable); 2586 2587 /* 2588 * Keep track of pending interrupt status. 2589 */ 2590 SERIALIZE_SCALAR(intrTick); 2591 SERIALIZE_SCALAR(cpuPendingIntr); 2592 Tick intrEventTick = 0; 2593 if (intrEvent) 2594 intrEventTick = intrEvent->when(); 2595 SERIALIZE_SCALAR(intrEventTick); 2596 2597} 2598 2599void 2600NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2601{ 2602 // Unserialize the PciDev base class 2603 PciDev::unserialize(cp, section); 2604 2605 UNSERIALIZE_SCALAR(regs.command); 2606 UNSERIALIZE_SCALAR(regs.config); 2607 UNSERIALIZE_SCALAR(regs.mear); 2608 UNSERIALIZE_SCALAR(regs.ptscr); 2609 UNSERIALIZE_SCALAR(regs.isr); 2610 UNSERIALIZE_SCALAR(regs.imr); 2611 UNSERIALIZE_SCALAR(regs.ier); 2612 UNSERIALIZE_SCALAR(regs.ihr); 2613 UNSERIALIZE_SCALAR(regs.txdp); 2614 UNSERIALIZE_SCALAR(regs.txdp_hi); 2615 UNSERIALIZE_SCALAR(regs.txcfg); 2616 UNSERIALIZE_SCALAR(regs.gpior); 2617 UNSERIALIZE_SCALAR(regs.rxdp); 2618 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2619 UNSERIALIZE_SCALAR(regs.rxcfg); 2620 UNSERIALIZE_SCALAR(regs.pqcr); 2621 UNSERIALIZE_SCALAR(regs.wcsr); 2622 UNSERIALIZE_SCALAR(regs.pcr); 2623 UNSERIALIZE_SCALAR(regs.rfcr); 2624 UNSERIALIZE_SCALAR(regs.rfdr); 2625 UNSERIALIZE_SCALAR(regs.brar); 2626 UNSERIALIZE_SCALAR(regs.brdr); 2627 UNSERIALIZE_SCALAR(regs.srr); 2628 UNSERIALIZE_SCALAR(regs.mibc); 2629 UNSERIALIZE_SCALAR(regs.vrcr); 2630 UNSERIALIZE_SCALAR(regs.vtcr); 2631 UNSERIALIZE_SCALAR(regs.vdr); 2632 UNSERIALIZE_SCALAR(regs.ccsr); 2633 UNSERIALIZE_SCALAR(regs.tbicr); 2634 UNSERIALIZE_SCALAR(regs.tbisr); 2635 UNSERIALIZE_SCALAR(regs.tanar); 2636 UNSERIALIZE_SCALAR(regs.tanlpar); 2637 UNSERIALIZE_SCALAR(regs.taner); 2638 UNSERIALIZE_SCALAR(regs.tesr); 2639 2640 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2641 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2642 2643 UNSERIALIZE_SCALAR(ioEnable); 2644 2645 /* 2646 * unserialize the data fifos 2647 */ 2648 rxFifo.unserialize("rxFifo", cp, section); 2649 txFifo.unserialize("txFifo", cp, section); 2650 2651 /* 2652 * unserialize the various helper variables 2653 */ 2654 bool txPacketExists; 2655 UNSERIALIZE_SCALAR(txPacketExists); 2656 if (txPacketExists) { 2657 txPacket = new EthPacketData(16384); 2658 txPacket->unserialize("txPacket", cp, section); 2659 uint32_t txPktBufPtr; 2660 UNSERIALIZE_SCALAR(txPktBufPtr); 2661 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2662 } else 2663 txPacket = 0; 2664 2665 bool rxPacketExists; 2666 UNSERIALIZE_SCALAR(rxPacketExists); 2667 rxPacket = 0; 2668 if (rxPacketExists) { 2669 rxPacket = new EthPacketData(16384); 2670 rxPacket->unserialize("rxPacket", cp, section); 2671 uint32_t rxPktBufPtr; 2672 UNSERIALIZE_SCALAR(rxPktBufPtr); 2673 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2674 } else 2675 rxPacket = 0; 2676 2677 UNSERIALIZE_SCALAR(txXferLen); 2678 UNSERIALIZE_SCALAR(rxXferLen); 2679 2680 /* 2681 * Unserialize Cached Descriptors 2682 */ 2683 UNSERIALIZE_SCALAR(rxDesc64.link); 2684 UNSERIALIZE_SCALAR(rxDesc64.bufptr); 2685 UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 2686 UNSERIALIZE_SCALAR(rxDesc64.extsts); 2687 UNSERIALIZE_SCALAR(txDesc64.link); 2688 UNSERIALIZE_SCALAR(txDesc64.bufptr); 2689 UNSERIALIZE_SCALAR(txDesc64.cmdsts); 2690 UNSERIALIZE_SCALAR(txDesc64.extsts); 2691 UNSERIALIZE_SCALAR(rxDesc32.link); 2692 UNSERIALIZE_SCALAR(rxDesc32.bufptr); 2693 UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 2694 UNSERIALIZE_SCALAR(rxDesc32.extsts); 2695 UNSERIALIZE_SCALAR(txDesc32.link); 2696 UNSERIALIZE_SCALAR(txDesc32.bufptr); 2697 UNSERIALIZE_SCALAR(txDesc32.cmdsts); 2698 UNSERIALIZE_SCALAR(txDesc32.extsts); 2699 UNSERIALIZE_SCALAR(extstsEnable); 2700 2701 /* 2702 * unserialize tx state machine 2703 */ 2704 int txState; 2705 UNSERIALIZE_SCALAR(txState); 2706 this->txState = (TxState) txState; 2707 UNSERIALIZE_SCALAR(txEnable); 2708 UNSERIALIZE_SCALAR(CTDD); 2709 UNSERIALIZE_SCALAR(txFragPtr); 2710 UNSERIALIZE_SCALAR(txDescCnt); 2711 int txDmaState; 2712 UNSERIALIZE_SCALAR(txDmaState); 2713 this->txDmaState = (DmaState) txDmaState; 2714 UNSERIALIZE_SCALAR(txKickTick); 2715 if (txKickTick) 2716 txKickEvent.schedule(txKickTick); 2717 2718 /* 2719 * unserialize rx state machine 2720 */ 2721 int rxState; 2722 UNSERIALIZE_SCALAR(rxState); 2723 this->rxState = (RxState) rxState; 2724 UNSERIALIZE_SCALAR(rxEnable); 2725 UNSERIALIZE_SCALAR(CRDD); 2726 UNSERIALIZE_SCALAR(rxPktBytes); 2727 UNSERIALIZE_SCALAR(rxFragPtr); 2728 UNSERIALIZE_SCALAR(rxDescCnt); 2729 int rxDmaState; 2730 UNSERIALIZE_SCALAR(rxDmaState); 2731 this->rxDmaState = (DmaState) rxDmaState; 2732 UNSERIALIZE_SCALAR(rxKickTick); 2733 if (rxKickTick) 2734 rxKickEvent.schedule(rxKickTick); 2735 2736 /* 2737 * Unserialize EEPROM state machine 2738 */ 2739 int eepromState; 2740 UNSERIALIZE_SCALAR(eepromState); 2741 this->eepromState = (EEPROMState) eepromState; 2742 UNSERIALIZE_SCALAR(eepromClk); 2743 UNSERIALIZE_SCALAR(eepromBitsToRx); 2744 UNSERIALIZE_SCALAR(eepromOpcode); 2745 UNSERIALIZE_SCALAR(eepromAddress); 2746 UNSERIALIZE_SCALAR(eepromData); 2747 2748 /* 2749 * If there's a pending transmit, reschedule it now 2750 */ 2751 Tick transmitTick; 2752 UNSERIALIZE_SCALAR(transmitTick); 2753 if (transmitTick) 2754 txEvent.schedule(curTick + transmitTick); 2755 2756 /* 2757 * unserialize receive address filter settings 2758 */ 2759 UNSERIALIZE_SCALAR(rxFilterEnable); 2760 UNSERIALIZE_SCALAR(acceptBroadcast); 2761 UNSERIALIZE_SCALAR(acceptMulticast); 2762 UNSERIALIZE_SCALAR(acceptUnicast); 2763 UNSERIALIZE_SCALAR(acceptPerfect); 2764 UNSERIALIZE_SCALAR(acceptArp); 2765 UNSERIALIZE_SCALAR(multicastHashEnable); 2766 2767 /* 2768 * Keep track of pending interrupt status. 2769 */ 2770 UNSERIALIZE_SCALAR(intrTick); 2771 UNSERIALIZE_SCALAR(cpuPendingIntr); 2772 Tick intrEventTick; 2773 UNSERIALIZE_SCALAR(intrEventTick); 2774 if (intrEventTick) { 2775 intrEvent = new IntrEvent(this, true); 2776 intrEvent->schedule(intrEventTick); 2777 } 2778} 2779 2780BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2781 2782 SimObjectParam<EtherInt *> peer; 2783 SimObjectParam<NSGigE *> device; 2784 2785END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2786 2787BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2788 2789 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2790 INIT_PARAM(device, "Ethernet device of this interface") 2791 2792END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2793 2794CREATE_SIM_OBJECT(NSGigEInt) 2795{ 2796 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2797 2798 EtherInt *p = (EtherInt *)peer; 2799 if (p) { 2800 dev_int->setPeer(p); 2801 p->setPeer(dev_int); 2802 } 2803 2804 return dev_int; 2805} 2806 2807REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2808 2809 2810BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2811 2812 SimObjectParam<System *> system; 2813 SimObjectParam<Platform *> platform; 2814 SimObjectParam<PciConfigData *> configdata; 2815 Param<uint32_t> pci_bus; 2816 Param<uint32_t> pci_dev; 2817 Param<uint32_t> pci_func; 2818 Param<Tick> pio_latency; 2819 Param<Tick> config_latency; 2820 2821 Param<Tick> clock; 2822 Param<bool> dma_desc_free; 2823 Param<bool> dma_data_free; 2824 Param<Tick> dma_read_delay; 2825 Param<Tick> dma_write_delay; 2826 Param<Tick> dma_read_factor; 2827 Param<Tick> dma_write_factor; 2828 Param<bool> dma_no_allocate; 2829 Param<Tick> intr_delay; 2830 2831 Param<Tick> rx_delay; 2832 Param<Tick> tx_delay; 2833 Param<uint32_t> rx_fifo_size; 2834 Param<uint32_t> tx_fifo_size; 2835 2836 Param<bool> rx_filter; 2837 Param<string> hardware_address; 2838 Param<bool> rx_thread; 2839 Param<bool> tx_thread; 2840 Param<bool> rss; 2841 2842END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2843 2844BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2845 2846 INIT_PARAM(system, "System pointer"), 2847 INIT_PARAM(platform, "Platform pointer"), 2848 INIT_PARAM(configdata, "PCI Config data"), 2849 INIT_PARAM(pci_bus, "PCI bus ID"), 2850 INIT_PARAM(pci_dev, "PCI device number"), 2851 INIT_PARAM(pci_func, "PCI function code"), 2852 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2853 INIT_PARAM(config_latency, "Number of cycles for a config read or write"), 2854 INIT_PARAM(clock, "State machine cycle time"), 2855 2856 INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), 2857 INIT_PARAM(dma_data_free, "DMA of Data is free"), 2858 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 2859 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 2860 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 2861 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 2862 INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), 2863 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2864 2865 INIT_PARAM(rx_delay, "Receive Delay"), 2866 INIT_PARAM(tx_delay, "Transmit Delay"), 2867 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 2868 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 2869 2870 INIT_PARAM(rx_filter, "Enable Receive Filter"), 2871 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 2872 INIT_PARAM(rx_thread, ""), 2873 INIT_PARAM(tx_thread, ""), 2874 INIT_PARAM(rss, "") 2875 2876END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2877 2878 2879CREATE_SIM_OBJECT(NSGigE) 2880{ 2881 NSGigE::Params *params = new NSGigE::Params; 2882 2883 params->name = getInstanceName(); 2884 params->platform = platform; 2885 params->system = system; 2886 params->configData = configdata; 2887 params->busNum = pci_bus; 2888 params->deviceNum = pci_dev; 2889 params->functionNum = pci_func; 2890 params->pio_delay = pio_latency; 2891 params->config_delay = config_latency; 2892 2893 params->clock = clock; 2894 params->dma_desc_free = dma_desc_free; 2895 params->dma_data_free = dma_data_free; 2896 params->dma_read_delay = dma_read_delay; 2897 params->dma_write_delay = dma_write_delay; 2898 params->dma_read_factor = dma_read_factor; 2899 params->dma_write_factor = dma_write_factor; 2900 params->dma_no_allocate = dma_no_allocate; 2901 params->pio_delay = pio_latency; 2902 params->intr_delay = intr_delay; 2903 2904 params->rx_delay = rx_delay; 2905 params->tx_delay = tx_delay; 2906 params->rx_fifo_size = rx_fifo_size; 2907 params->tx_fifo_size = tx_fifo_size; 2908 2909 params->rx_filter = rx_filter; 2910 params->eaddr = hardware_address; 2911 params->rx_thread = rx_thread; 2912 params->tx_thread = tx_thread; 2913 params->rss = rss; 2914 2915 return new NSGigE(params); 2916} 2917 2918REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2919