ns_gige.cc revision 2846
16019Shines@cs.fsu.edu/* 26019Shines@cs.fsu.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 37178Sgblack@eecs.umich.edu * All rights reserved. 47178Sgblack@eecs.umich.edu * 57178Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67178Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77178Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97178Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117178Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127178Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137178Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147178Sgblack@eecs.umich.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Nathan Binkert 296019Shines@cs.fsu.edu * Lisa Hsu 306019Shines@cs.fsu.edu */ 316019Shines@cs.fsu.edu 326019Shines@cs.fsu.edu/** @file 336019Shines@cs.fsu.edu * Device module for modelling the National Semiconductor 346019Shines@cs.fsu.edu * DP83820 ethernet controller. Does not support priority queueing 356019Shines@cs.fsu.edu */ 366019Shines@cs.fsu.edu#include <deque> 376019Shines@cs.fsu.edu#include <string> 386019Shines@cs.fsu.edu 396019Shines@cs.fsu.edu#include "arch/alpha/ev5.hh" 406019Shines@cs.fsu.edu#include "base/inet.hh" 416019Shines@cs.fsu.edu#include "cpu/thread_context.hh" 426019Shines@cs.fsu.edu#include "dev/etherlink.hh" 436019Shines@cs.fsu.edu#include "dev/ns_gige.hh" 446019Shines@cs.fsu.edu#include "dev/pciconfigall.hh" 456019Shines@cs.fsu.edu#include "mem/packet.hh" 466019Shines@cs.fsu.edu#include "sim/builder.hh" 476019Shines@cs.fsu.edu#include "sim/debug.hh" 487639Sgblack@eecs.umich.edu#include "sim/host.hh" 497639Sgblack@eecs.umich.edu#include "sim/stats.hh" 507639Sgblack@eecs.umich.edu#include "sim/system.hh" 517639Sgblack@eecs.umich.edu 527639Sgblack@eecs.umich.educonst char *NsRxStateStrings[] = 537639Sgblack@eecs.umich.edu{ 547639Sgblack@eecs.umich.edu "rxIdle", 557639Sgblack@eecs.umich.edu "rxDescRefr", 567639Sgblack@eecs.umich.edu "rxDescRead", 577639Sgblack@eecs.umich.edu "rxFifoBlock", 587639Sgblack@eecs.umich.edu "rxFragWrite", 597639Sgblack@eecs.umich.edu "rxDescWrite", 607639Sgblack@eecs.umich.edu "rxAdvance" 617639Sgblack@eecs.umich.edu}; 627639Sgblack@eecs.umich.edu 637639Sgblack@eecs.umich.educonst char *NsTxStateStrings[] = 647639Sgblack@eecs.umich.edu{ 657639Sgblack@eecs.umich.edu "txIdle", 667639Sgblack@eecs.umich.edu "txDescRefr", 677639Sgblack@eecs.umich.edu "txDescRead", 687639Sgblack@eecs.umich.edu "txFifoBlock", 697639Sgblack@eecs.umich.edu "txFragRead", 707639Sgblack@eecs.umich.edu "txDescWrite", 717639Sgblack@eecs.umich.edu "txAdvance" 727639Sgblack@eecs.umich.edu}; 737639Sgblack@eecs.umich.edu 747639Sgblack@eecs.umich.educonst char *NsDmaState[] = 757639Sgblack@eecs.umich.edu{ 767639Sgblack@eecs.umich.edu "dmaIdle", 777639Sgblack@eecs.umich.edu "dmaReading", 787639Sgblack@eecs.umich.edu "dmaWriting", 797639Sgblack@eecs.umich.edu "dmaReadWaiting", 807639Sgblack@eecs.umich.edu "dmaWriteWaiting" 817639Sgblack@eecs.umich.edu}; 827639Sgblack@eecs.umich.edu 837639Sgblack@eecs.umich.eduusing namespace std; 847639Sgblack@eecs.umich.eduusing namespace Net; 857639Sgblack@eecs.umich.eduusing namespace TheISA; 867639Sgblack@eecs.umich.edu 877639Sgblack@eecs.umich.edu/////////////////////////////////////////////////////////////////////// 887639Sgblack@eecs.umich.edu// 897639Sgblack@eecs.umich.edu// NSGigE PCI Device 907639Sgblack@eecs.umich.edu// 917639Sgblack@eecs.umich.eduNSGigE::NSGigE(Params *p) 927639Sgblack@eecs.umich.edu : PciDev(p), ioEnable(false), 937639Sgblack@eecs.umich.edu txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 947356Sgblack@eecs.umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 957356Sgblack@eecs.umich.edu txXferLen(0), rxXferLen(0), clock(p->clock), 967356Sgblack@eecs.umich.edu txState(txIdle), txEnable(false), CTDD(false), 977435Sgblack@eecs.umich.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 987435Sgblack@eecs.umich.edu rxEnable(false), CRDD(false), rxPktBytes(0), 997435Sgblack@eecs.umich.edu rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1007435Sgblack@eecs.umich.edu eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), 1017435Sgblack@eecs.umich.edu txDmaReadEvent(this), txDmaWriteEvent(this), 1027435Sgblack@eecs.umich.edu dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1037435Sgblack@eecs.umich.edu txDelay(p->tx_delay), rxDelay(p->rx_delay), 1047435Sgblack@eecs.umich.edu rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1057435Sgblack@eecs.umich.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1067435Sgblack@eecs.umich.edu acceptMulticast(false), acceptUnicast(false), 1077435Sgblack@eecs.umich.edu acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1087639Sgblack@eecs.umich.edu intrTick(0), cpuPendingIntr(false), 1097639Sgblack@eecs.umich.edu intrEvent(0), interface(0) 1107639Sgblack@eecs.umich.edu{ 1117435Sgblack@eecs.umich.edu 1127639Sgblack@eecs.umich.edu intrDelay = p->intr_delay; 1137639Sgblack@eecs.umich.edu dmaReadDelay = p->dma_read_delay; 1147639Sgblack@eecs.umich.edu dmaWriteDelay = p->dma_write_delay; 1157639Sgblack@eecs.umich.edu dmaReadFactor = p->dma_read_factor; 1167639Sgblack@eecs.umich.edu dmaWriteFactor = p->dma_write_factor; 1177639Sgblack@eecs.umich.edu 1187639Sgblack@eecs.umich.edu regsReset(); 1197639Sgblack@eecs.umich.edu memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1207639Sgblack@eecs.umich.edu 1217639Sgblack@eecs.umich.edu memset(&rxDesc32, 0, sizeof(rxDesc32)); 1227639Sgblack@eecs.umich.edu memset(&txDesc32, 0, sizeof(txDesc32)); 1237639Sgblack@eecs.umich.edu memset(&rxDesc64, 0, sizeof(rxDesc64)); 1247639Sgblack@eecs.umich.edu memset(&txDesc64, 0, sizeof(txDesc64)); 1257639Sgblack@eecs.umich.edu} 1267639Sgblack@eecs.umich.edu 1277639Sgblack@eecs.umich.eduNSGigE::~NSGigE() 1287639Sgblack@eecs.umich.edu{} 1297639Sgblack@eecs.umich.edu 1307639Sgblack@eecs.umich.eduvoid 1317639Sgblack@eecs.umich.eduNSGigE::regStats() 1327639Sgblack@eecs.umich.edu{ 1337639Sgblack@eecs.umich.edu txBytes 1347639Sgblack@eecs.umich.edu .name(name() + ".txBytes") 1357639Sgblack@eecs.umich.edu .desc("Bytes Transmitted") 1367639Sgblack@eecs.umich.edu .prereq(txBytes) 1377639Sgblack@eecs.umich.edu ; 1387639Sgblack@eecs.umich.edu 1397639Sgblack@eecs.umich.edu rxBytes 1407639Sgblack@eecs.umich.edu .name(name() + ".rxBytes") 1417639Sgblack@eecs.umich.edu .desc("Bytes Received") 1427639Sgblack@eecs.umich.edu .prereq(rxBytes) 1437639Sgblack@eecs.umich.edu ; 1447639Sgblack@eecs.umich.edu 1457639Sgblack@eecs.umich.edu txPackets 1468144SAli.Saidi@ARM.com .name(name() + ".txPackets") 1477639Sgblack@eecs.umich.edu .desc("Number of Packets Transmitted") 1487639Sgblack@eecs.umich.edu .prereq(txBytes) 1497639Sgblack@eecs.umich.edu ; 1507639Sgblack@eecs.umich.edu 1517639Sgblack@eecs.umich.edu rxPackets 1527639Sgblack@eecs.umich.edu .name(name() + ".rxPackets") 1537639Sgblack@eecs.umich.edu .desc("Number of Packets Received") 1547639Sgblack@eecs.umich.edu .prereq(rxBytes) 1557639Sgblack@eecs.umich.edu ; 1567639Sgblack@eecs.umich.edu 1577639Sgblack@eecs.umich.edu txIpChecksums 1587639Sgblack@eecs.umich.edu .name(name() + ".txIpChecksums") 1597639Sgblack@eecs.umich.edu .desc("Number of tx IP Checksums done by device") 1607639Sgblack@eecs.umich.edu .precision(0) 1617639Sgblack@eecs.umich.edu .prereq(txBytes) 1627639Sgblack@eecs.umich.edu ; 1637639Sgblack@eecs.umich.edu 1647639Sgblack@eecs.umich.edu rxIpChecksums 1657639Sgblack@eecs.umich.edu .name(name() + ".rxIpChecksums") 1667639Sgblack@eecs.umich.edu .desc("Number of rx IP Checksums done by device") 1677639Sgblack@eecs.umich.edu .precision(0) 1687639Sgblack@eecs.umich.edu .prereq(rxBytes) 1697639Sgblack@eecs.umich.edu ; 1707639Sgblack@eecs.umich.edu 1717639Sgblack@eecs.umich.edu txTcpChecksums 1727639Sgblack@eecs.umich.edu .name(name() + ".txTcpChecksums") 1737639Sgblack@eecs.umich.edu .desc("Number of tx TCP Checksums done by device") 1747639Sgblack@eecs.umich.edu .precision(0) 1757639Sgblack@eecs.umich.edu .prereq(txBytes) 1767639Sgblack@eecs.umich.edu ; 1777639Sgblack@eecs.umich.edu 1787639Sgblack@eecs.umich.edu rxTcpChecksums 1797639Sgblack@eecs.umich.edu .name(name() + ".rxTcpChecksums") 1807639Sgblack@eecs.umich.edu .desc("Number of rx TCP Checksums done by device") 1817639Sgblack@eecs.umich.edu .precision(0) 1827639Sgblack@eecs.umich.edu .prereq(rxBytes) 1837591SAli.Saidi@ARM.com ; 1847639Sgblack@eecs.umich.edu 1857435Sgblack@eecs.umich.edu txUdpChecksums 1867435Sgblack@eecs.umich.edu .name(name() + ".txUdpChecksums") 1877639Sgblack@eecs.umich.edu .desc("Number of tx UDP Checksums done by device") 1887639Sgblack@eecs.umich.edu .precision(0) 1897639Sgblack@eecs.umich.edu .prereq(txBytes) 1907639Sgblack@eecs.umich.edu ; 1917639Sgblack@eecs.umich.edu 1927639Sgblack@eecs.umich.edu rxUdpChecksums 1937639Sgblack@eecs.umich.edu .name(name() + ".rxUdpChecksums") 1947639Sgblack@eecs.umich.edu .desc("Number of rx UDP Checksums done by device") 1957639Sgblack@eecs.umich.edu .precision(0) 1967639Sgblack@eecs.umich.edu .prereq(rxBytes) 1977639Sgblack@eecs.umich.edu ; 1987639Sgblack@eecs.umich.edu 1997639Sgblack@eecs.umich.edu descDmaReads 2007639Sgblack@eecs.umich.edu .name(name() + ".descDMAReads") 2017639Sgblack@eecs.umich.edu .desc("Number of descriptors the device read w/ DMA") 2027639Sgblack@eecs.umich.edu .precision(0) 2037639Sgblack@eecs.umich.edu ; 2047639Sgblack@eecs.umich.edu 2057639Sgblack@eecs.umich.edu descDmaWrites 2067639Sgblack@eecs.umich.edu .name(name() + ".descDMAWrites") 2077639Sgblack@eecs.umich.edu .desc("Number of descriptors the device wrote w/ DMA") 2087639Sgblack@eecs.umich.edu .precision(0) 2097639Sgblack@eecs.umich.edu ; 2107639Sgblack@eecs.umich.edu 2117639Sgblack@eecs.umich.edu descDmaRdBytes 2127639Sgblack@eecs.umich.edu .name(name() + ".descDmaReadBytes") 2137639Sgblack@eecs.umich.edu .desc("number of descriptor bytes read w/ DMA") 2147639Sgblack@eecs.umich.edu .precision(0) 2157639Sgblack@eecs.umich.edu ; 2167639Sgblack@eecs.umich.edu 2177639Sgblack@eecs.umich.edu descDmaWrBytes 2187639Sgblack@eecs.umich.edu .name(name() + ".descDmaWriteBytes") 2197639Sgblack@eecs.umich.edu .desc("number of descriptor bytes write w/ DMA") 2207639Sgblack@eecs.umich.edu .precision(0) 2217639Sgblack@eecs.umich.edu ; 2227639Sgblack@eecs.umich.edu 2237591SAli.Saidi@ARM.com txBandwidth 2247591SAli.Saidi@ARM.com .name(name() + ".txBandwidth") 2257639Sgblack@eecs.umich.edu .desc("Transmit Bandwidth (bits/s)") 2267639Sgblack@eecs.umich.edu .precision(0) 2277639Sgblack@eecs.umich.edu .prereq(txBytes) 2287639Sgblack@eecs.umich.edu ; 2297639Sgblack@eecs.umich.edu 2307639Sgblack@eecs.umich.edu rxBandwidth 2317639Sgblack@eecs.umich.edu .name(name() + ".rxBandwidth") 2327639Sgblack@eecs.umich.edu .desc("Receive Bandwidth (bits/s)") 2337639Sgblack@eecs.umich.edu .precision(0) 2347639Sgblack@eecs.umich.edu .prereq(rxBytes) 2357639Sgblack@eecs.umich.edu ; 2367639Sgblack@eecs.umich.edu 2377639Sgblack@eecs.umich.edu totBandwidth 2387639Sgblack@eecs.umich.edu .name(name() + ".totBandwidth") 2397639Sgblack@eecs.umich.edu .desc("Total Bandwidth (bits/s)") 2407639Sgblack@eecs.umich.edu .precision(0) 2417639Sgblack@eecs.umich.edu .prereq(totBytes) 2427639Sgblack@eecs.umich.edu ; 2437639Sgblack@eecs.umich.edu 2447639Sgblack@eecs.umich.edu totPackets 2457435Sgblack@eecs.umich.edu .name(name() + ".totPackets") 2467435Sgblack@eecs.umich.edu .desc("Total Packets") 2477639Sgblack@eecs.umich.edu .precision(0) 2487639Sgblack@eecs.umich.edu .prereq(totBytes) 2497639Sgblack@eecs.umich.edu ; 2507639Sgblack@eecs.umich.edu 2517639Sgblack@eecs.umich.edu totBytes 2527639Sgblack@eecs.umich.edu .name(name() + ".totBytes") 2537639Sgblack@eecs.umich.edu .desc("Total Bytes") 2547639Sgblack@eecs.umich.edu .precision(0) 2557639Sgblack@eecs.umich.edu .prereq(totBytes) 2567639Sgblack@eecs.umich.edu ; 2577639Sgblack@eecs.umich.edu 2587639Sgblack@eecs.umich.edu totPacketRate 2597639Sgblack@eecs.umich.edu .name(name() + ".totPPS") 2607639Sgblack@eecs.umich.edu .desc("Total Tranmission Rate (packets/s)") 2617639Sgblack@eecs.umich.edu .precision(0) 2627639Sgblack@eecs.umich.edu .prereq(totBytes) 2637639Sgblack@eecs.umich.edu ; 2647639Sgblack@eecs.umich.edu 2657639Sgblack@eecs.umich.edu txPacketRate 2667639Sgblack@eecs.umich.edu .name(name() + ".txPPS") 2677639Sgblack@eecs.umich.edu .desc("Packet Tranmission Rate (packets/s)") 2687639Sgblack@eecs.umich.edu .precision(0) 2697639Sgblack@eecs.umich.edu .prereq(txBytes) 2707639Sgblack@eecs.umich.edu ; 2717639Sgblack@eecs.umich.edu 2727639Sgblack@eecs.umich.edu rxPacketRate 2737639Sgblack@eecs.umich.edu .name(name() + ".rxPPS") 2747639Sgblack@eecs.umich.edu .desc("Packet Reception Rate (packets/s)") 2757639Sgblack@eecs.umich.edu .precision(0) 2767639Sgblack@eecs.umich.edu .prereq(rxBytes) 2777639Sgblack@eecs.umich.edu ; 2787639Sgblack@eecs.umich.edu 2797639Sgblack@eecs.umich.edu postedSwi 2807639Sgblack@eecs.umich.edu .name(name() + ".postedSwi") 2817639Sgblack@eecs.umich.edu .desc("number of software interrupts posted to CPU") 2827639Sgblack@eecs.umich.edu .precision(0) 2837639Sgblack@eecs.umich.edu ; 2847639Sgblack@eecs.umich.edu 2857639Sgblack@eecs.umich.edu totalSwi 2867639Sgblack@eecs.umich.edu .name(name() + ".totalSwi") 2877639Sgblack@eecs.umich.edu .desc("total number of Swi written to ISR") 2887639Sgblack@eecs.umich.edu .precision(0) 2897639Sgblack@eecs.umich.edu ; 2907639Sgblack@eecs.umich.edu 2917639Sgblack@eecs.umich.edu coalescedSwi 2927639Sgblack@eecs.umich.edu .name(name() + ".coalescedSwi") 2937639Sgblack@eecs.umich.edu .desc("average number of Swi's coalesced into each post") 2947639Sgblack@eecs.umich.edu .precision(0) 2957639Sgblack@eecs.umich.edu ; 2967639Sgblack@eecs.umich.edu 2977639Sgblack@eecs.umich.edu postedRxIdle 2987639Sgblack@eecs.umich.edu .name(name() + ".postedRxIdle") 2997639Sgblack@eecs.umich.edu .desc("number of rxIdle interrupts posted to CPU") 3007639Sgblack@eecs.umich.edu .precision(0) 3017639Sgblack@eecs.umich.edu ; 3027639Sgblack@eecs.umich.edu 3037639Sgblack@eecs.umich.edu totalRxIdle 3047639Sgblack@eecs.umich.edu .name(name() + ".totalRxIdle") 3057639Sgblack@eecs.umich.edu .desc("total number of RxIdle written to ISR") 3067639Sgblack@eecs.umich.edu .precision(0) 3077639Sgblack@eecs.umich.edu ; 3087639Sgblack@eecs.umich.edu 3097639Sgblack@eecs.umich.edu coalescedRxIdle 3107639Sgblack@eecs.umich.edu .name(name() + ".coalescedRxIdle") 3117639Sgblack@eecs.umich.edu .desc("average number of RxIdle's coalesced into each post") 3127639Sgblack@eecs.umich.edu .precision(0) 3137639Sgblack@eecs.umich.edu ; 3147639Sgblack@eecs.umich.edu 3157639Sgblack@eecs.umich.edu postedRxOk 3167639Sgblack@eecs.umich.edu .name(name() + ".postedRxOk") 3177639Sgblack@eecs.umich.edu .desc("number of RxOk interrupts posted to CPU") 3187639Sgblack@eecs.umich.edu .precision(0) 3197639Sgblack@eecs.umich.edu ; 3207639Sgblack@eecs.umich.edu 3217639Sgblack@eecs.umich.edu totalRxOk 3227639Sgblack@eecs.umich.edu .name(name() + ".totalRxOk") 3237435Sgblack@eecs.umich.edu .desc("total number of RxOk written to ISR") 3247435Sgblack@eecs.umich.edu .precision(0) 3257639Sgblack@eecs.umich.edu ; 3267639Sgblack@eecs.umich.edu 3277639Sgblack@eecs.umich.edu coalescedRxOk 3287591SAli.Saidi@ARM.com .name(name() + ".coalescedRxOk") 3297639Sgblack@eecs.umich.edu .desc("average number of RxOk's coalesced into each post") 3307639Sgblack@eecs.umich.edu .precision(0) 3317435Sgblack@eecs.umich.edu ; 3327435Sgblack@eecs.umich.edu 3337639Sgblack@eecs.umich.edu postedRxDesc 3347639Sgblack@eecs.umich.edu .name(name() + ".postedRxDesc") 3357435Sgblack@eecs.umich.edu .desc("number of RxDesc interrupts posted to CPU") 3367435Sgblack@eecs.umich.edu .precision(0) 3377591SAli.Saidi@ARM.com ; 3387435Sgblack@eecs.umich.edu 3397435Sgblack@eecs.umich.edu totalRxDesc 3407435Sgblack@eecs.umich.edu .name(name() + ".totalRxDesc") 3417435Sgblack@eecs.umich.edu .desc("total number of RxDesc written to ISR") 3427435Sgblack@eecs.umich.edu .precision(0) 3437435Sgblack@eecs.umich.edu ; 3447435Sgblack@eecs.umich.edu 3457435Sgblack@eecs.umich.edu coalescedRxDesc 3467435Sgblack@eecs.umich.edu .name(name() + ".coalescedRxDesc") 3477435Sgblack@eecs.umich.edu .desc("average number of RxDesc's coalesced into each post") 3487435Sgblack@eecs.umich.edu .precision(0) 3497639Sgblack@eecs.umich.edu ; 3507639Sgblack@eecs.umich.edu 3517639Sgblack@eecs.umich.edu postedTxOk 3527639Sgblack@eecs.umich.edu .name(name() + ".postedTxOk") 3537639Sgblack@eecs.umich.edu .desc("number of TxOk interrupts posted to CPU") 3547639Sgblack@eecs.umich.edu .precision(0) 3557639Sgblack@eecs.umich.edu ; 3567639Sgblack@eecs.umich.edu 3577639Sgblack@eecs.umich.edu totalTxOk 3587639Sgblack@eecs.umich.edu .name(name() + ".totalTxOk") 3597639Sgblack@eecs.umich.edu .desc("total number of TxOk written to ISR") 3607639Sgblack@eecs.umich.edu .precision(0) 3617639Sgblack@eecs.umich.edu ; 3627435Sgblack@eecs.umich.edu 3637435Sgblack@eecs.umich.edu coalescedTxOk 3647435Sgblack@eecs.umich.edu .name(name() + ".coalescedTxOk") 3657639Sgblack@eecs.umich.edu .desc("average number of TxOk's coalesced into each post") 3667639Sgblack@eecs.umich.edu .precision(0) 3677639Sgblack@eecs.umich.edu ; 3687435Sgblack@eecs.umich.edu 3697639Sgblack@eecs.umich.edu postedTxIdle 3707639Sgblack@eecs.umich.edu .name(name() + ".postedTxIdle") 3717435Sgblack@eecs.umich.edu .desc("number of TxIdle interrupts posted to CPU") 3727435Sgblack@eecs.umich.edu .precision(0) 3737639Sgblack@eecs.umich.edu ; 3747639Sgblack@eecs.umich.edu 3757639Sgblack@eecs.umich.edu totalTxIdle 3767639Sgblack@eecs.umich.edu .name(name() + ".totalTxIdle") 3777435Sgblack@eecs.umich.edu .desc("total number of TxIdle written to ISR") 3787435Sgblack@eecs.umich.edu .precision(0) 3797435Sgblack@eecs.umich.edu ; 3807639Sgblack@eecs.umich.edu 3817639Sgblack@eecs.umich.edu coalescedTxIdle 3827435Sgblack@eecs.umich.edu .name(name() + ".coalescedTxIdle") 3837435Sgblack@eecs.umich.edu .desc("average number of TxIdle's coalesced into each post") 3847435Sgblack@eecs.umich.edu .precision(0) 3857435Sgblack@eecs.umich.edu ; 3867639Sgblack@eecs.umich.edu 3877639Sgblack@eecs.umich.edu postedTxDesc 3887639Sgblack@eecs.umich.edu .name(name() + ".postedTxDesc") 3897639Sgblack@eecs.umich.edu .desc("number of TxDesc interrupts posted to CPU") 3907639Sgblack@eecs.umich.edu .precision(0) 3917435Sgblack@eecs.umich.edu ; 3927639Sgblack@eecs.umich.edu 3937639Sgblack@eecs.umich.edu totalTxDesc 3947639Sgblack@eecs.umich.edu .name(name() + ".totalTxDesc") 3957639Sgblack@eecs.umich.edu .desc("total number of TxDesc written to ISR") 3967639Sgblack@eecs.umich.edu .precision(0) 3977435Sgblack@eecs.umich.edu ; 3987639Sgblack@eecs.umich.edu 3997639Sgblack@eecs.umich.edu coalescedTxDesc 4007639Sgblack@eecs.umich.edu .name(name() + ".coalescedTxDesc") 4017639Sgblack@eecs.umich.edu .desc("average number of TxDesc's coalesced into each post") 4027639Sgblack@eecs.umich.edu .precision(0) 4037435Sgblack@eecs.umich.edu ; 4047639Sgblack@eecs.umich.edu 4057639Sgblack@eecs.umich.edu postedRxOrn 4067639Sgblack@eecs.umich.edu .name(name() + ".postedRxOrn") 4077639Sgblack@eecs.umich.edu .desc("number of RxOrn posted to CPU") 4087639Sgblack@eecs.umich.edu .precision(0) 4097435Sgblack@eecs.umich.edu ; 4107435Sgblack@eecs.umich.edu 4117435Sgblack@eecs.umich.edu totalRxOrn 4127435Sgblack@eecs.umich.edu .name(name() + ".totalRxOrn") 4137639Sgblack@eecs.umich.edu .desc("total number of RxOrn written to ISR") 4147639Sgblack@eecs.umich.edu .precision(0) 4157639Sgblack@eecs.umich.edu ; 4167639Sgblack@eecs.umich.edu 4177639Sgblack@eecs.umich.edu coalescedRxOrn 4187435Sgblack@eecs.umich.edu .name(name() + ".coalescedRxOrn") 4197639Sgblack@eecs.umich.edu .desc("average number of RxOrn's coalesced into each post") 4207639Sgblack@eecs.umich.edu .precision(0) 4217639Sgblack@eecs.umich.edu ; 4227639Sgblack@eecs.umich.edu 4237639Sgblack@eecs.umich.edu coalescedTotal 4247435Sgblack@eecs.umich.edu .name(name() + ".coalescedTotal") 4257639Sgblack@eecs.umich.edu .desc("average number of interrupts coalesced into each post") 4267639Sgblack@eecs.umich.edu .precision(0) 4277639Sgblack@eecs.umich.edu ; 4287639Sgblack@eecs.umich.edu 4297435Sgblack@eecs.umich.edu postedInterrupts 4307639Sgblack@eecs.umich.edu .name(name() + ".postedInterrupts") 4317639Sgblack@eecs.umich.edu .desc("number of posts to CPU") 4327639Sgblack@eecs.umich.edu .precision(0) 4337639Sgblack@eecs.umich.edu ; 4347639Sgblack@eecs.umich.edu 4357639Sgblack@eecs.umich.edu droppedPackets 4367639Sgblack@eecs.umich.edu .name(name() + ".droppedPackets") 4377639Sgblack@eecs.umich.edu .desc("number of packets dropped") 4387639Sgblack@eecs.umich.edu .precision(0) 4397639Sgblack@eecs.umich.edu ; 4407435Sgblack@eecs.umich.edu 4417435Sgblack@eecs.umich.edu coalescedSwi = totalSwi / postedInterrupts; 4427435Sgblack@eecs.umich.edu coalescedRxIdle = totalRxIdle / postedInterrupts; 4437639Sgblack@eecs.umich.edu coalescedRxOk = totalRxOk / postedInterrupts; 4447639Sgblack@eecs.umich.edu coalescedRxDesc = totalRxDesc / postedInterrupts; 4457639Sgblack@eecs.umich.edu coalescedTxOk = totalTxOk / postedInterrupts; 4467639Sgblack@eecs.umich.edu coalescedTxIdle = totalTxIdle / postedInterrupts; 4477639Sgblack@eecs.umich.edu coalescedTxDesc = totalTxDesc / postedInterrupts; 4487639Sgblack@eecs.umich.edu coalescedRxOrn = totalRxOrn / postedInterrupts; 4497639Sgblack@eecs.umich.edu 4507435Sgblack@eecs.umich.edu coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 4517435Sgblack@eecs.umich.edu totalTxOk + totalTxIdle + totalTxDesc + 4527435Sgblack@eecs.umich.edu totalRxOrn) / postedInterrupts; 4537435Sgblack@eecs.umich.edu 4547435Sgblack@eecs.umich.edu txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4557639Sgblack@eecs.umich.edu rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4567639Sgblack@eecs.umich.edu totBandwidth = txBandwidth + rxBandwidth; 4577639Sgblack@eecs.umich.edu totBytes = txBytes + rxBytes; 4587639Sgblack@eecs.umich.edu totPackets = txPackets + rxPackets; 4597639Sgblack@eecs.umich.edu 4607639Sgblack@eecs.umich.edu txPacketRate = txPackets / simSeconds; 4617639Sgblack@eecs.umich.edu rxPacketRate = rxPackets / simSeconds; 4627435Sgblack@eecs.umich.edu} 4637639Sgblack@eecs.umich.edu 4647639Sgblack@eecs.umich.edu 4657639Sgblack@eecs.umich.edu/** 4667639Sgblack@eecs.umich.edu * This is to write to the PCI general configuration registers 4677435Sgblack@eecs.umich.edu */ 4687435Sgblack@eecs.umich.eduTick 4697435Sgblack@eecs.umich.eduNSGigE::writeConfig(Packet *pkt) 4707639Sgblack@eecs.umich.edu{ 4717639Sgblack@eecs.umich.edu int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 4727435Sgblack@eecs.umich.edu if (offset < PCI_DEVICE_SPECIFIC) 4737639Sgblack@eecs.umich.edu PciDev::writeConfig(pkt); 4747639Sgblack@eecs.umich.edu else 4757435Sgblack@eecs.umich.edu panic("Device specific PCI config space not implemented!\n"); 4767435Sgblack@eecs.umich.edu 4777435Sgblack@eecs.umich.edu switch (offset) { 4787639Sgblack@eecs.umich.edu // seems to work fine without all these PCI settings, but i 4797639Sgblack@eecs.umich.edu // put in the IO to double check, an assertion will fail if we 4807639Sgblack@eecs.umich.edu // need to properly implement it 4817639Sgblack@eecs.umich.edu case PCI_COMMAND: 4827639Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_IOSE) 4837639Sgblack@eecs.umich.edu ioEnable = true; 4847639Sgblack@eecs.umich.edu else 4857435Sgblack@eecs.umich.edu ioEnable = false; 4867639Sgblack@eecs.umich.edu break; 4877639Sgblack@eecs.umich.edu } 4887435Sgblack@eecs.umich.edu pkt->result = Packet::Success; 4897435Sgblack@eecs.umich.edu return configDelay; 4907435Sgblack@eecs.umich.edu} 4917639Sgblack@eecs.umich.edu 4927639Sgblack@eecs.umich.edu/** 4937639Sgblack@eecs.umich.edu * This reads the device registers, which are detailed in the NS83820 4947639Sgblack@eecs.umich.edu * spec sheet 4957639Sgblack@eecs.umich.edu */ 4967639Sgblack@eecs.umich.eduTick 4977639Sgblack@eecs.umich.eduNSGigE::read(Packet *pkt) 4987435Sgblack@eecs.umich.edu{ 4997639Sgblack@eecs.umich.edu assert(ioEnable); 5007639Sgblack@eecs.umich.edu 5017435Sgblack@eecs.umich.edu pkt->allocate(); 5027435Sgblack@eecs.umich.edu 5037435Sgblack@eecs.umich.edu //The mask is to give you only the offset into the device register file 5047639Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() & 0xfff; 5057639Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 5067435Sgblack@eecs.umich.edu daddr, pkt->getAddr(), pkt->getSize()); 5077639Sgblack@eecs.umich.edu 5087639Sgblack@eecs.umich.edu 5097435Sgblack@eecs.umich.edu // there are some reserved registers, you can see ns_gige_reg.h and 5107435Sgblack@eecs.umich.edu // the spec sheet for details 5117435Sgblack@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 5127639Sgblack@eecs.umich.edu panic("Accessing reserved register"); 5137639Sgblack@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 5147435Sgblack@eecs.umich.edu return readConfig(pkt); 5157435Sgblack@eecs.umich.edu } else if (daddr >= MIB_START && daddr <= MIB_END) { 5167639Sgblack@eecs.umich.edu // don't implement all the MIB's. hopefully the kernel 5177435Sgblack@eecs.umich.edu // doesn't actually DEPEND upon their values 5187435Sgblack@eecs.umich.edu // MIB are just hardware stats keepers 5197639Sgblack@eecs.umich.edu pkt->set<uint32_t>(0); 5207639Sgblack@eecs.umich.edu pkt->result = Packet::Success; 5217435Sgblack@eecs.umich.edu return pioDelay; 5227435Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 5237639Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 5247639Sgblack@eecs.umich.edu 5257435Sgblack@eecs.umich.edu assert(pkt->getSize() == sizeof(uint32_t)); 5267435Sgblack@eecs.umich.edu uint32_t ® = *pkt->getPtr<uint32_t>(); 5277435Sgblack@eecs.umich.edu uint16_t rfaddr; 5287435Sgblack@eecs.umich.edu 5297435Sgblack@eecs.umich.edu switch (daddr) { 5307639Sgblack@eecs.umich.edu case CR: 5317639Sgblack@eecs.umich.edu reg = regs.command; 5327435Sgblack@eecs.umich.edu //these are supposed to be cleared on a read 5337639Sgblack@eecs.umich.edu reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 5347639Sgblack@eecs.umich.edu break; 5357435Sgblack@eecs.umich.edu 5367435Sgblack@eecs.umich.edu case CFGR: 5377435Sgblack@eecs.umich.edu reg = regs.config; 5387639Sgblack@eecs.umich.edu break; 5397639Sgblack@eecs.umich.edu 5407435Sgblack@eecs.umich.edu case MEAR: 5417639Sgblack@eecs.umich.edu reg = regs.mear; 5427639Sgblack@eecs.umich.edu break; 5437435Sgblack@eecs.umich.edu 5447435Sgblack@eecs.umich.edu case PTSCR: 5457435Sgblack@eecs.umich.edu reg = regs.ptscr; 5467435Sgblack@eecs.umich.edu break; 5477435Sgblack@eecs.umich.edu 5487639Sgblack@eecs.umich.edu case ISR: 5497639Sgblack@eecs.umich.edu reg = regs.isr; 5507435Sgblack@eecs.umich.edu devIntrClear(ISR_ALL); 5517639Sgblack@eecs.umich.edu break; 5527639Sgblack@eecs.umich.edu 5537435Sgblack@eecs.umich.edu case IMR: 5547435Sgblack@eecs.umich.edu reg = regs.imr; 5557435Sgblack@eecs.umich.edu break; 5567639Sgblack@eecs.umich.edu 5577639Sgblack@eecs.umich.edu case IER: 5587435Sgblack@eecs.umich.edu reg = regs.ier; 5597639Sgblack@eecs.umich.edu break; 5607639Sgblack@eecs.umich.edu 5617435Sgblack@eecs.umich.edu case IHR: 5627435Sgblack@eecs.umich.edu reg = regs.ihr; 5637435Sgblack@eecs.umich.edu break; 5647435Sgblack@eecs.umich.edu 5657639Sgblack@eecs.umich.edu case TXDP: 5667639Sgblack@eecs.umich.edu reg = regs.txdp; 5677435Sgblack@eecs.umich.edu break; 5687639Sgblack@eecs.umich.edu 5697639Sgblack@eecs.umich.edu case TXDP_HI: 5707435Sgblack@eecs.umich.edu reg = regs.txdp_hi; 5717435Sgblack@eecs.umich.edu break; 5727435Sgblack@eecs.umich.edu 5737435Sgblack@eecs.umich.edu case TX_CFG: 5747435Sgblack@eecs.umich.edu reg = regs.txcfg; 5757435Sgblack@eecs.umich.edu break; 5767639Sgblack@eecs.umich.edu 5777639Sgblack@eecs.umich.edu case GPIOR: 5787435Sgblack@eecs.umich.edu reg = regs.gpior; 5797435Sgblack@eecs.umich.edu break; 5807435Sgblack@eecs.umich.edu 5817639Sgblack@eecs.umich.edu case RXDP: 5827639Sgblack@eecs.umich.edu reg = regs.rxdp; 5837435Sgblack@eecs.umich.edu break; 5847639Sgblack@eecs.umich.edu 5857639Sgblack@eecs.umich.edu case RXDP_HI: 5867435Sgblack@eecs.umich.edu reg = regs.rxdp_hi; 5877435Sgblack@eecs.umich.edu break; 5887435Sgblack@eecs.umich.edu 5897435Sgblack@eecs.umich.edu case RX_CFG: 5907435Sgblack@eecs.umich.edu reg = regs.rxcfg; 5917435Sgblack@eecs.umich.edu break; 5927435Sgblack@eecs.umich.edu 5937435Sgblack@eecs.umich.edu case PQCR: 5947639Sgblack@eecs.umich.edu reg = regs.pqcr; 5957639Sgblack@eecs.umich.edu break; 5967639Sgblack@eecs.umich.edu 5977639Sgblack@eecs.umich.edu case WCSR: 5987639Sgblack@eecs.umich.edu reg = regs.wcsr; 5997435Sgblack@eecs.umich.edu break; 6007435Sgblack@eecs.umich.edu 6017435Sgblack@eecs.umich.edu case PCR: 6027435Sgblack@eecs.umich.edu reg = regs.pcr; 6037435Sgblack@eecs.umich.edu break; 6047639Sgblack@eecs.umich.edu 6057639Sgblack@eecs.umich.edu // see the spec sheet for how RFCR and RFDR work 6067639Sgblack@eecs.umich.edu // basically, you write to RFCR to tell the machine 6077639Sgblack@eecs.umich.edu // what you want to do next, then you act upon RFDR, 6087639Sgblack@eecs.umich.edu // and the device will be prepared b/c of what you 6097435Sgblack@eecs.umich.edu // wrote to RFCR 6107639Sgblack@eecs.umich.edu case RFCR: 6117639Sgblack@eecs.umich.edu reg = regs.rfcr; 6127639Sgblack@eecs.umich.edu break; 6137639Sgblack@eecs.umich.edu 6147639Sgblack@eecs.umich.edu case RFDR: 6157435Sgblack@eecs.umich.edu rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 6167435Sgblack@eecs.umich.edu switch (rfaddr) { 6177435Sgblack@eecs.umich.edu // Read from perfect match ROM octets 6187435Sgblack@eecs.umich.edu case 0x000: 6197435Sgblack@eecs.umich.edu reg = rom.perfectMatch[1]; 6207639Sgblack@eecs.umich.edu reg = reg << 8; 6217639Sgblack@eecs.umich.edu reg += rom.perfectMatch[0]; 6227639Sgblack@eecs.umich.edu break; 6237639Sgblack@eecs.umich.edu case 0x002: 6247639Sgblack@eecs.umich.edu reg = rom.perfectMatch[3] << 8; 6257435Sgblack@eecs.umich.edu reg += rom.perfectMatch[2]; 6267639Sgblack@eecs.umich.edu break; 6277639Sgblack@eecs.umich.edu case 0x004: 6287639Sgblack@eecs.umich.edu reg = rom.perfectMatch[5] << 8; 6297639Sgblack@eecs.umich.edu reg += rom.perfectMatch[4]; 6307639Sgblack@eecs.umich.edu break; 6317435Sgblack@eecs.umich.edu default: 6327435Sgblack@eecs.umich.edu // Read filter hash table 6337435Sgblack@eecs.umich.edu if (rfaddr >= FHASH_ADDR && 6347639Sgblack@eecs.umich.edu rfaddr < FHASH_ADDR + FHASH_SIZE) { 6357639Sgblack@eecs.umich.edu 6367639Sgblack@eecs.umich.edu // Only word-aligned reads supported 6377639Sgblack@eecs.umich.edu if (rfaddr % 2) 6387639Sgblack@eecs.umich.edu panic("unaligned read from filter hash table!"); 6397435Sgblack@eecs.umich.edu 6407639Sgblack@eecs.umich.edu reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 6417639Sgblack@eecs.umich.edu reg += rom.filterHash[rfaddr - FHASH_ADDR]; 6427639Sgblack@eecs.umich.edu break; 6437639Sgblack@eecs.umich.edu } 6447639Sgblack@eecs.umich.edu 6457435Sgblack@eecs.umich.edu panic("reading RFDR for something other than pattern" 6467435Sgblack@eecs.umich.edu " matching or hashing! %#x\n", rfaddr); 6477435Sgblack@eecs.umich.edu } 6487435Sgblack@eecs.umich.edu break; 6497435Sgblack@eecs.umich.edu 6507435Sgblack@eecs.umich.edu case SRR: 6517435Sgblack@eecs.umich.edu reg = regs.srr; 6527639Sgblack@eecs.umich.edu break; 6537639Sgblack@eecs.umich.edu 6547639Sgblack@eecs.umich.edu case MIBC: 6557639Sgblack@eecs.umich.edu reg = regs.mibc; 6567639Sgblack@eecs.umich.edu reg &= ~(MIBC_MIBS | MIBC_ACLR); 6577435Sgblack@eecs.umich.edu break; 6587639Sgblack@eecs.umich.edu 6597639Sgblack@eecs.umich.edu case VRCR: 6607639Sgblack@eecs.umich.edu reg = regs.vrcr; 6617639Sgblack@eecs.umich.edu break; 6627639Sgblack@eecs.umich.edu 6637435Sgblack@eecs.umich.edu case VTCR: 6647435Sgblack@eecs.umich.edu reg = regs.vtcr; 6657435Sgblack@eecs.umich.edu break; 6667435Sgblack@eecs.umich.edu 6677435Sgblack@eecs.umich.edu case VDR: 6687435Sgblack@eecs.umich.edu reg = regs.vdr; 6697435Sgblack@eecs.umich.edu break; 6707639Sgblack@eecs.umich.edu 6717639Sgblack@eecs.umich.edu case CCSR: 6727639Sgblack@eecs.umich.edu reg = regs.ccsr; 6737639Sgblack@eecs.umich.edu break; 6747639Sgblack@eecs.umich.edu 6757435Sgblack@eecs.umich.edu case TBICR: 6767639Sgblack@eecs.umich.edu reg = regs.tbicr; 6777639Sgblack@eecs.umich.edu break; 6787639Sgblack@eecs.umich.edu 6797639Sgblack@eecs.umich.edu case TBISR: 6807639Sgblack@eecs.umich.edu reg = regs.tbisr; 6817435Sgblack@eecs.umich.edu break; 6827435Sgblack@eecs.umich.edu 6837435Sgblack@eecs.umich.edu case TANAR: 6847639Sgblack@eecs.umich.edu reg = regs.tanar; 6857639Sgblack@eecs.umich.edu break; 6867639Sgblack@eecs.umich.edu 6877639Sgblack@eecs.umich.edu case TANLPAR: 6887639Sgblack@eecs.umich.edu reg = regs.tanlpar; 6897435Sgblack@eecs.umich.edu break; 6907435Sgblack@eecs.umich.edu 6917435Sgblack@eecs.umich.edu case TANER: 6927435Sgblack@eecs.umich.edu reg = regs.taner; 6937435Sgblack@eecs.umich.edu break; 6947435Sgblack@eecs.umich.edu 6957435Sgblack@eecs.umich.edu case TESR: 6967435Sgblack@eecs.umich.edu reg = regs.tesr; 6977435Sgblack@eecs.umich.edu break; 6987435Sgblack@eecs.umich.edu 6997435Sgblack@eecs.umich.edu case M5REG: 7007639Sgblack@eecs.umich.edu reg = 0; 7017639Sgblack@eecs.umich.edu if (params()->rx_thread) 7027639Sgblack@eecs.umich.edu reg |= M5REG_RX_THREAD; 7037639Sgblack@eecs.umich.edu if (params()->tx_thread) 7047639Sgblack@eecs.umich.edu reg |= M5REG_TX_THREAD; 7057435Sgblack@eecs.umich.edu if (params()->rss) 7067639Sgblack@eecs.umich.edu reg |= M5REG_RSS; 7077639Sgblack@eecs.umich.edu break; 7087639Sgblack@eecs.umich.edu 7097639Sgblack@eecs.umich.edu default: 7107639Sgblack@eecs.umich.edu panic("reading unimplemented register: addr=%#x", daddr); 7117435Sgblack@eecs.umich.edu } 7127435Sgblack@eecs.umich.edu 7137435Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 7147435Sgblack@eecs.umich.edu daddr, reg, reg); 7157435Sgblack@eecs.umich.edu 7167639Sgblack@eecs.umich.edu pkt->result = Packet::Success; 7177639Sgblack@eecs.umich.edu return pioDelay; 7187639Sgblack@eecs.umich.edu} 7197639Sgblack@eecs.umich.edu 7207639Sgblack@eecs.umich.eduTick 7217435Sgblack@eecs.umich.eduNSGigE::write(Packet *pkt) 7227639Sgblack@eecs.umich.edu{ 7237639Sgblack@eecs.umich.edu assert(ioEnable); 7247639Sgblack@eecs.umich.edu 7257639Sgblack@eecs.umich.edu Addr daddr = pkt->getAddr() & 0xfff; 7267639Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 7277435Sgblack@eecs.umich.edu daddr, pkt->getAddr(), pkt->getSize()); 7287435Sgblack@eecs.umich.edu 7297435Sgblack@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 7307639Sgblack@eecs.umich.edu panic("Accessing reserved register"); 7317639Sgblack@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 7327639Sgblack@eecs.umich.edu return writeConfig(pkt); 7337639Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 7347639Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 7357435Sgblack@eecs.umich.edu 7367639Sgblack@eecs.umich.edu if (pkt->getSize() == sizeof(uint32_t)) { 7377639Sgblack@eecs.umich.edu uint32_t reg = pkt->get<uint32_t>(); 7387639Sgblack@eecs.umich.edu uint16_t rfaddr; 7397639Sgblack@eecs.umich.edu 7407639Sgblack@eecs.umich.edu DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 7417435Sgblack@eecs.umich.edu 7427435Sgblack@eecs.umich.edu switch (daddr) { 7437435Sgblack@eecs.umich.edu case CR: 7447435Sgblack@eecs.umich.edu regs.command = reg; 7457435Sgblack@eecs.umich.edu if (reg & CR_TXD) { 7467435Sgblack@eecs.umich.edu txEnable = false; 7477435Sgblack@eecs.umich.edu } else if (reg & CR_TXE) { 7487435Sgblack@eecs.umich.edu txEnable = true; 7497435Sgblack@eecs.umich.edu 7507435Sgblack@eecs.umich.edu // the kernel is enabling the transmit machine 7517639Sgblack@eecs.umich.edu if (txState == txIdle) 7527639Sgblack@eecs.umich.edu txKick(); 7537639Sgblack@eecs.umich.edu } 7547639Sgblack@eecs.umich.edu 7557435Sgblack@eecs.umich.edu if (reg & CR_RXD) { 7567639Sgblack@eecs.umich.edu rxEnable = false; 7577639Sgblack@eecs.umich.edu } else if (reg & CR_RXE) { 7587639Sgblack@eecs.umich.edu rxEnable = true; 7597639Sgblack@eecs.umich.edu 7607639Sgblack@eecs.umich.edu if (rxState == rxIdle) 7617853SMatt.Horsnell@ARM.com rxKick(); 7627853SMatt.Horsnell@ARM.com } 7637853SMatt.Horsnell@ARM.com 7647853SMatt.Horsnell@ARM.com if (reg & CR_TXR) 7657853SMatt.Horsnell@ARM.com txReset(); 7667853SMatt.Horsnell@ARM.com 7677853SMatt.Horsnell@ARM.com if (reg & CR_RXR) 7687853SMatt.Horsnell@ARM.com rxReset(); 7697853SMatt.Horsnell@ARM.com 7707435Sgblack@eecs.umich.edu if (reg & CR_SWI) 7717435Sgblack@eecs.umich.edu devIntrPost(ISR_SWI); 7727435Sgblack@eecs.umich.edu 7737639Sgblack@eecs.umich.edu if (reg & CR_RST) { 7747639Sgblack@eecs.umich.edu txReset(); 7757639Sgblack@eecs.umich.edu rxReset(); 7767639Sgblack@eecs.umich.edu 7777435Sgblack@eecs.umich.edu regsReset(); 7787639Sgblack@eecs.umich.edu } 7797639Sgblack@eecs.umich.edu break; 7807639Sgblack@eecs.umich.edu 7817639Sgblack@eecs.umich.edu case CFGR: 7827435Sgblack@eecs.umich.edu if (reg & CFGR_LNKSTS || 7837435Sgblack@eecs.umich.edu reg & CFGR_SPDSTS || 7847435Sgblack@eecs.umich.edu reg & CFGR_DUPSTS || 7857639Sgblack@eecs.umich.edu reg & CFGR_RESERVED || 7867639Sgblack@eecs.umich.edu reg & CFGR_T64ADDR || 7877639Sgblack@eecs.umich.edu reg & CFGR_PCI64_DET) 7887639Sgblack@eecs.umich.edu 7897639Sgblack@eecs.umich.edu // First clear all writable bits 7907639Sgblack@eecs.umich.edu regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 7917639Sgblack@eecs.umich.edu CFGR_RESERVED | CFGR_T64ADDR | 7927639Sgblack@eecs.umich.edu CFGR_PCI64_DET; 7937639Sgblack@eecs.umich.edu // Now set the appropriate writable bits 7947639Sgblack@eecs.umich.edu regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 7957639Sgblack@eecs.umich.edu CFGR_RESERVED | CFGR_T64ADDR | 7967639Sgblack@eecs.umich.edu CFGR_PCI64_DET); 7977639Sgblack@eecs.umich.edu 7987639Sgblack@eecs.umich.edu// all these #if 0's are because i don't THINK the kernel needs to 7997639Sgblack@eecs.umich.edu// have these implemented. if there is a problem relating to one of 8007639Sgblack@eecs.umich.edu// these, you may need to add functionality in. 8017639Sgblack@eecs.umich.edu if (reg & CFGR_TBI_EN) ; 8027639Sgblack@eecs.umich.edu if (reg & CFGR_MODE_1000) ; 8037435Sgblack@eecs.umich.edu 8047435Sgblack@eecs.umich.edu if (reg & CFGR_AUTO_1000) 8057639Sgblack@eecs.umich.edu panic("CFGR_AUTO_1000 not implemented!\n"); 8067639Sgblack@eecs.umich.edu 8077639Sgblack@eecs.umich.edu if (reg & CFGR_PINT_DUPSTS || 8087639Sgblack@eecs.umich.edu reg & CFGR_PINT_LNKSTS || 8097435Sgblack@eecs.umich.edu reg & CFGR_PINT_SPDSTS) 8107639Sgblack@eecs.umich.edu ; 8117639Sgblack@eecs.umich.edu 8127639Sgblack@eecs.umich.edu if (reg & CFGR_TMRTEST) ; 8137639Sgblack@eecs.umich.edu if (reg & CFGR_MRM_DIS) ; 8147435Sgblack@eecs.umich.edu if (reg & CFGR_MWI_DIS) ; 8157435Sgblack@eecs.umich.edu 8167435Sgblack@eecs.umich.edu if (reg & CFGR_T64ADDR) ; 8177435Sgblack@eecs.umich.edu // panic("CFGR_T64ADDR is read only register!\n"); 8187435Sgblack@eecs.umich.edu 8197435Sgblack@eecs.umich.edu if (reg & CFGR_PCI64_DET) 8207639Sgblack@eecs.umich.edu panic("CFGR_PCI64_DET is read only register!\n"); 8217639Sgblack@eecs.umich.edu 8227639Sgblack@eecs.umich.edu if (reg & CFGR_DATA64_EN) ; 8237639Sgblack@eecs.umich.edu if (reg & CFGR_M64ADDR) ; 8247435Sgblack@eecs.umich.edu if (reg & CFGR_PHY_RST) ; 8257639Sgblack@eecs.umich.edu if (reg & CFGR_PHY_DIS) ; 8267639Sgblack@eecs.umich.edu 8277639Sgblack@eecs.umich.edu if (reg & CFGR_EXTSTS_EN) 8287639Sgblack@eecs.umich.edu extstsEnable = true; 8297435Sgblack@eecs.umich.edu else 8307435Sgblack@eecs.umich.edu extstsEnable = false; 8317435Sgblack@eecs.umich.edu 8327639Sgblack@eecs.umich.edu if (reg & CFGR_REQALG) ; 8337639Sgblack@eecs.umich.edu if (reg & CFGR_SB) ; 8347639Sgblack@eecs.umich.edu if (reg & CFGR_POW) ; 8357639Sgblack@eecs.umich.edu if (reg & CFGR_EXD) ; 8367435Sgblack@eecs.umich.edu if (reg & CFGR_PESEL) ; 8377435Sgblack@eecs.umich.edu if (reg & CFGR_BROM_DIS) ; 8387639Sgblack@eecs.umich.edu if (reg & CFGR_EXT_125) ; 8397639Sgblack@eecs.umich.edu if (reg & CFGR_BEM) ; 8407639Sgblack@eecs.umich.edu break; 8417639Sgblack@eecs.umich.edu 8427435Sgblack@eecs.umich.edu case MEAR: 8437639Sgblack@eecs.umich.edu // Clear writable bits 8447639Sgblack@eecs.umich.edu regs.mear &= MEAR_EEDO; 8457639Sgblack@eecs.umich.edu // Set appropriate writable bits 8467639Sgblack@eecs.umich.edu regs.mear |= reg & ~MEAR_EEDO; 8477435Sgblack@eecs.umich.edu 8487435Sgblack@eecs.umich.edu // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 8497435Sgblack@eecs.umich.edu // even though it could get it through RFDR 8507435Sgblack@eecs.umich.edu if (reg & MEAR_EESEL) { 8517435Sgblack@eecs.umich.edu // Rising edge of clock 8527435Sgblack@eecs.umich.edu if (reg & MEAR_EECLK && !eepromClk) 8537435Sgblack@eecs.umich.edu eepromKick(); 8547435Sgblack@eecs.umich.edu } 8557435Sgblack@eecs.umich.edu else { 8567435Sgblack@eecs.umich.edu eepromState = eepromStart; 8577435Sgblack@eecs.umich.edu regs.mear &= ~MEAR_EEDI; 8587435Sgblack@eecs.umich.edu } 8597435Sgblack@eecs.umich.edu 8607435Sgblack@eecs.umich.edu eepromClk = reg & MEAR_EECLK; 8617639Sgblack@eecs.umich.edu 8627639Sgblack@eecs.umich.edu // since phy is completely faked, MEAR_MD* don't matter 8637639Sgblack@eecs.umich.edu if (reg & MEAR_MDIO) ; 8647639Sgblack@eecs.umich.edu if (reg & MEAR_MDDIR) ; 8657639Sgblack@eecs.umich.edu if (reg & MEAR_MDC) ; 8667639Sgblack@eecs.umich.edu break; 8677639Sgblack@eecs.umich.edu 8687639Sgblack@eecs.umich.edu case PTSCR: 8697639Sgblack@eecs.umich.edu regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 8707639Sgblack@eecs.umich.edu // these control BISTs for various parts of chip - we 8717639Sgblack@eecs.umich.edu // don't care or do just fake that the BIST is done 8727639Sgblack@eecs.umich.edu if (reg & PTSCR_RBIST_EN) 8737639Sgblack@eecs.umich.edu regs.ptscr |= PTSCR_RBIST_DONE; 8747639Sgblack@eecs.umich.edu if (reg & PTSCR_EEBIST_EN) 8757639Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EEBIST_EN; 8767639Sgblack@eecs.umich.edu if (reg & PTSCR_EELOAD_EN) 8777639Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EELOAD_EN; 8787639Sgblack@eecs.umich.edu break; 8797639Sgblack@eecs.umich.edu 8807639Sgblack@eecs.umich.edu case ISR: /* writing to the ISR has no effect */ 8817639Sgblack@eecs.umich.edu panic("ISR is a read only register!\n"); 8827639Sgblack@eecs.umich.edu 8837639Sgblack@eecs.umich.edu case IMR: 8847639Sgblack@eecs.umich.edu regs.imr = reg; 8857639Sgblack@eecs.umich.edu devIntrChangeMask(); 8867639Sgblack@eecs.umich.edu break; 8877435Sgblack@eecs.umich.edu 8887435Sgblack@eecs.umich.edu case IER: 8897435Sgblack@eecs.umich.edu regs.ier = reg; 8907639Sgblack@eecs.umich.edu break; 8917639Sgblack@eecs.umich.edu 8927435Sgblack@eecs.umich.edu case IHR: 8937639Sgblack@eecs.umich.edu regs.ihr = reg; 8947639Sgblack@eecs.umich.edu /* not going to implement real interrupt holdoff */ 8957435Sgblack@eecs.umich.edu break; 8967639Sgblack@eecs.umich.edu 8977639Sgblack@eecs.umich.edu case TXDP: 8987435Sgblack@eecs.umich.edu regs.txdp = (reg & 0xFFFFFFFC); 8997639Sgblack@eecs.umich.edu assert(txState == txIdle); 9007639Sgblack@eecs.umich.edu CTDD = false; 9017435Sgblack@eecs.umich.edu break; 9027435Sgblack@eecs.umich.edu 9037639Sgblack@eecs.umich.edu case TXDP_HI: 9047639Sgblack@eecs.umich.edu regs.txdp_hi = reg; 9057435Sgblack@eecs.umich.edu break; 9067435Sgblack@eecs.umich.edu 9077435Sgblack@eecs.umich.edu case TX_CFG: 9087435Sgblack@eecs.umich.edu regs.txcfg = reg; 9097435Sgblack@eecs.umich.edu#if 0 9107639Sgblack@eecs.umich.edu if (reg & TX_CFG_CSI) ; 9117639Sgblack@eecs.umich.edu if (reg & TX_CFG_HBI) ; 9127435Sgblack@eecs.umich.edu if (reg & TX_CFG_MLB) ; 9137639Sgblack@eecs.umich.edu if (reg & TX_CFG_ATP) ; 9147639Sgblack@eecs.umich.edu if (reg & TX_CFG_ECRETRY) { 9157435Sgblack@eecs.umich.edu /* 9167435Sgblack@eecs.umich.edu * this could easily be implemented, but considering 9177435Sgblack@eecs.umich.edu * the network is just a fake pipe, wouldn't make 9187639Sgblack@eecs.umich.edu * sense to do this 9197639Sgblack@eecs.umich.edu */ 9207639Sgblack@eecs.umich.edu } 9217639Sgblack@eecs.umich.edu 9227639Sgblack@eecs.umich.edu if (reg & TX_CFG_BRST_DIS) ; 9237639Sgblack@eecs.umich.edu#endif 9247639Sgblack@eecs.umich.edu 9257639Sgblack@eecs.umich.edu#if 0 9267639Sgblack@eecs.umich.edu /* we handle our own DMA, ignore the kernel's exhortations */ 9277639Sgblack@eecs.umich.edu if (reg & TX_CFG_MXDMA) ; 9287639Sgblack@eecs.umich.edu#endif 9297639Sgblack@eecs.umich.edu 9307435Sgblack@eecs.umich.edu // also, we currently don't care about fill/drain 9317435Sgblack@eecs.umich.edu // thresholds though this may change in the future with 9327435Sgblack@eecs.umich.edu // more realistic networks or a driver which changes it 9337435Sgblack@eecs.umich.edu // according to feedback 9347639Sgblack@eecs.umich.edu 9357639Sgblack@eecs.umich.edu break; 9367435Sgblack@eecs.umich.edu 9377639Sgblack@eecs.umich.edu case GPIOR: 9387639Sgblack@eecs.umich.edu // Only write writable bits 9397435Sgblack@eecs.umich.edu regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9407435Sgblack@eecs.umich.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 9417435Sgblack@eecs.umich.edu regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9427435Sgblack@eecs.umich.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 9437639Sgblack@eecs.umich.edu /* these just control general purpose i/o pins, don't matter */ 9447639Sgblack@eecs.umich.edu break; 9457639Sgblack@eecs.umich.edu 9467435Sgblack@eecs.umich.edu case RXDP: 9477639Sgblack@eecs.umich.edu regs.rxdp = reg; 9487639Sgblack@eecs.umich.edu CRDD = false; 9497435Sgblack@eecs.umich.edu break; 9507435Sgblack@eecs.umich.edu 9517435Sgblack@eecs.umich.edu case RXDP_HI: 9527435Sgblack@eecs.umich.edu regs.rxdp_hi = reg; 9537435Sgblack@eecs.umich.edu break; 9547639Sgblack@eecs.umich.edu 9557639Sgblack@eecs.umich.edu case RX_CFG: 9567435Sgblack@eecs.umich.edu regs.rxcfg = reg; 9577435Sgblack@eecs.umich.edu#if 0 9587639Sgblack@eecs.umich.edu if (reg & RX_CFG_AEP) ; 9597639Sgblack@eecs.umich.edu if (reg & RX_CFG_ARP) ; 9607639Sgblack@eecs.umich.edu if (reg & RX_CFG_STRIPCRC) ; 9617639Sgblack@eecs.umich.edu if (reg & RX_CFG_RX_RD) ; 9627639Sgblack@eecs.umich.edu if (reg & RX_CFG_ALP) ; 9637639Sgblack@eecs.umich.edu if (reg & RX_CFG_AIRL) ; 9647639Sgblack@eecs.umich.edu 9657639Sgblack@eecs.umich.edu /* we handle our own DMA, ignore what kernel says about it */ 9667639Sgblack@eecs.umich.edu if (reg & RX_CFG_MXDMA) ; 9677639Sgblack@eecs.umich.edu 9687639Sgblack@eecs.umich.edu //also, we currently don't care about fill/drain thresholds 9697639Sgblack@eecs.umich.edu //though this may change in the future with more realistic 9707639Sgblack@eecs.umich.edu //networks or a driver which changes it according to feedback 9717639Sgblack@eecs.umich.edu if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 9727639Sgblack@eecs.umich.edu#endif 9737639Sgblack@eecs.umich.edu break; 9747639Sgblack@eecs.umich.edu 9757639Sgblack@eecs.umich.edu case PQCR: 9767639Sgblack@eecs.umich.edu /* there is no priority queueing used in the linux 2.6 driver */ 9777639Sgblack@eecs.umich.edu regs.pqcr = reg; 9787639Sgblack@eecs.umich.edu break; 9797639Sgblack@eecs.umich.edu 9807639Sgblack@eecs.umich.edu case WCSR: 9817435Sgblack@eecs.umich.edu /* not going to implement wake on LAN */ 9827435Sgblack@eecs.umich.edu regs.wcsr = reg; 9837435Sgblack@eecs.umich.edu break; 9847639Sgblack@eecs.umich.edu 9857639Sgblack@eecs.umich.edu case PCR: 9867639Sgblack@eecs.umich.edu /* not going to implement pause control */ 9877639Sgblack@eecs.umich.edu regs.pcr = reg; 9887639Sgblack@eecs.umich.edu break; 9897639Sgblack@eecs.umich.edu 9907639Sgblack@eecs.umich.edu case RFCR: 9917639Sgblack@eecs.umich.edu regs.rfcr = reg; 9927639Sgblack@eecs.umich.edu 9937639Sgblack@eecs.umich.edu rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 9947639Sgblack@eecs.umich.edu acceptBroadcast = (reg & RFCR_AAB) ? true : false; 9957639Sgblack@eecs.umich.edu acceptMulticast = (reg & RFCR_AAM) ? true : false; 9967639Sgblack@eecs.umich.edu acceptUnicast = (reg & RFCR_AAU) ? true : false; 9977639Sgblack@eecs.umich.edu acceptPerfect = (reg & RFCR_APM) ? true : false; 9987639Sgblack@eecs.umich.edu acceptArp = (reg & RFCR_AARP) ? true : false; 9997639Sgblack@eecs.umich.edu multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 10007639Sgblack@eecs.umich.edu 10017639Sgblack@eecs.umich.edu#if 0 10027639Sgblack@eecs.umich.edu if (reg & RFCR_APAT) 10037639Sgblack@eecs.umich.edu panic("RFCR_APAT not implemented!\n"); 10047435Sgblack@eecs.umich.edu#endif 10057435Sgblack@eecs.umich.edu if (reg & RFCR_UHEN) 10067435Sgblack@eecs.umich.edu panic("Unicast hash filtering not used by drivers!\n"); 10077435Sgblack@eecs.umich.edu 10087435Sgblack@eecs.umich.edu if (reg & RFCR_ULM) 10097435Sgblack@eecs.umich.edu panic("RFCR_ULM not implemented!\n"); 10107435Sgblack@eecs.umich.edu 10117435Sgblack@eecs.umich.edu break; 10127435Sgblack@eecs.umich.edu 10137435Sgblack@eecs.umich.edu case RFDR: 10147639Sgblack@eecs.umich.edu rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 10157639Sgblack@eecs.umich.edu switch (rfaddr) { 10167639Sgblack@eecs.umich.edu case 0x000: 10177639Sgblack@eecs.umich.edu rom.perfectMatch[0] = (uint8_t)reg; 10187639Sgblack@eecs.umich.edu rom.perfectMatch[1] = (uint8_t)(reg >> 8); 10197639Sgblack@eecs.umich.edu break; 10207639Sgblack@eecs.umich.edu case 0x002: 10217639Sgblack@eecs.umich.edu rom.perfectMatch[2] = (uint8_t)reg; 10227639Sgblack@eecs.umich.edu rom.perfectMatch[3] = (uint8_t)(reg >> 8); 10237639Sgblack@eecs.umich.edu break; 10247435Sgblack@eecs.umich.edu case 0x004: 10257435Sgblack@eecs.umich.edu rom.perfectMatch[4] = (uint8_t)reg; 10267639Sgblack@eecs.umich.edu rom.perfectMatch[5] = (uint8_t)(reg >> 8); 10277639Sgblack@eecs.umich.edu break; 10287435Sgblack@eecs.umich.edu default: 10297639Sgblack@eecs.umich.edu 10307639Sgblack@eecs.umich.edu if (rfaddr >= FHASH_ADDR && 10317435Sgblack@eecs.umich.edu rfaddr < FHASH_ADDR + FHASH_SIZE) { 10327639Sgblack@eecs.umich.edu 10337639Sgblack@eecs.umich.edu // Only word-aligned writes supported 10347435Sgblack@eecs.umich.edu if (rfaddr % 2) 10357639Sgblack@eecs.umich.edu panic("unaligned write to filter hash table!"); 10367639Sgblack@eecs.umich.edu 10377435Sgblack@eecs.umich.edu rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 10387435Sgblack@eecs.umich.edu rom.filterHash[rfaddr - FHASH_ADDR + 1] 10397639Sgblack@eecs.umich.edu = (uint8_t)(reg >> 8); 10407639Sgblack@eecs.umich.edu break; 10417435Sgblack@eecs.umich.edu } 10427639Sgblack@eecs.umich.edu panic("writing RFDR for something other than pattern matching\ 10437639Sgblack@eecs.umich.edu or hashing! %#x\n", rfaddr); 10447435Sgblack@eecs.umich.edu } 10457435Sgblack@eecs.umich.edu 10467639Sgblack@eecs.umich.edu case BRAR: 10477639Sgblack@eecs.umich.edu regs.brar = reg; 10487435Sgblack@eecs.umich.edu break; 10497435Sgblack@eecs.umich.edu 10507639Sgblack@eecs.umich.edu case BRDR: 10517639Sgblack@eecs.umich.edu panic("the driver never uses BRDR, something is wrong!\n"); 10527435Sgblack@eecs.umich.edu 10537639Sgblack@eecs.umich.edu case SRR: 10547639Sgblack@eecs.umich.edu panic("SRR is read only register!\n"); 10557435Sgblack@eecs.umich.edu 10567435Sgblack@eecs.umich.edu case MIBC: 10577435Sgblack@eecs.umich.edu panic("the driver never uses MIBC, something is wrong!\n"); 10587639Sgblack@eecs.umich.edu 10597639Sgblack@eecs.umich.edu case VRCR: 10607435Sgblack@eecs.umich.edu regs.vrcr = reg; 10617639Sgblack@eecs.umich.edu break; 10627639Sgblack@eecs.umich.edu 10637435Sgblack@eecs.umich.edu case VTCR: 10647435Sgblack@eecs.umich.edu regs.vtcr = reg; 10657639Sgblack@eecs.umich.edu break; 10667639Sgblack@eecs.umich.edu 10677435Sgblack@eecs.umich.edu case VDR: 10687639Sgblack@eecs.umich.edu panic("the driver never uses VDR, something is wrong!\n"); 10697639Sgblack@eecs.umich.edu 10707435Sgblack@eecs.umich.edu case CCSR: 10717639Sgblack@eecs.umich.edu /* not going to implement clockrun stuff */ 10727639Sgblack@eecs.umich.edu regs.ccsr = reg; 10737435Sgblack@eecs.umich.edu break; 10747639Sgblack@eecs.umich.edu 10757639Sgblack@eecs.umich.edu case TBICR: 10767435Sgblack@eecs.umich.edu regs.tbicr = reg; 10777435Sgblack@eecs.umich.edu if (reg & TBICR_MR_LOOPBACK) 10787639Sgblack@eecs.umich.edu panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 10797435Sgblack@eecs.umich.edu 10807435Sgblack@eecs.umich.edu if (reg & TBICR_MR_AN_ENABLE) { 10817639Sgblack@eecs.umich.edu regs.tanlpar = regs.tanar; 10827639Sgblack@eecs.umich.edu regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 10837435Sgblack@eecs.umich.edu } 10847435Sgblack@eecs.umich.edu 10857639Sgblack@eecs.umich.edu#if 0 10867639Sgblack@eecs.umich.edu if (reg & TBICR_MR_RESTART_AN) ; 10877435Sgblack@eecs.umich.edu#endif 10887639Sgblack@eecs.umich.edu 10897435Sgblack@eecs.umich.edu break; 10907435Sgblack@eecs.umich.edu 10917639Sgblack@eecs.umich.edu case TBISR: 10927639Sgblack@eecs.umich.edu panic("TBISR is read only register!\n"); 10937435Sgblack@eecs.umich.edu 10947435Sgblack@eecs.umich.edu case TANAR: 10957639Sgblack@eecs.umich.edu // Only write the writable bits 10967639Sgblack@eecs.umich.edu regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 10977435Sgblack@eecs.umich.edu regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 10987435Sgblack@eecs.umich.edu 10997435Sgblack@eecs.umich.edu // Pause capability unimplemented 11007435Sgblack@eecs.umich.edu#if 0 11017435Sgblack@eecs.umich.edu if (reg & TANAR_PS2) ; 11027435Sgblack@eecs.umich.edu if (reg & TANAR_PS1) ; 11037435Sgblack@eecs.umich.edu#endif 11047435Sgblack@eecs.umich.edu 11057435Sgblack@eecs.umich.edu break; 11067639Sgblack@eecs.umich.edu 11077639Sgblack@eecs.umich.edu case TANLPAR: 11087639Sgblack@eecs.umich.edu panic("this should only be written to by the fake phy!\n"); 11097639Sgblack@eecs.umich.edu 11107639Sgblack@eecs.umich.edu case TANER: 11117639Sgblack@eecs.umich.edu panic("TANER is read only register!\n"); 11127639Sgblack@eecs.umich.edu 11137639Sgblack@eecs.umich.edu case TESR: 11147639Sgblack@eecs.umich.edu regs.tesr = reg; 11157639Sgblack@eecs.umich.edu break; 11167639Sgblack@eecs.umich.edu 11177639Sgblack@eecs.umich.edu default: 11187435Sgblack@eecs.umich.edu panic("invalid register access daddr=%#x", daddr); 11197435Sgblack@eecs.umich.edu } 11207639Sgblack@eecs.umich.edu } else { 11217639Sgblack@eecs.umich.edu panic("Invalid Request Size"); 11227639Sgblack@eecs.umich.edu } 11237639Sgblack@eecs.umich.edu pkt->result = Packet::Success; 11247639Sgblack@eecs.umich.edu return pioDelay; 11257639Sgblack@eecs.umich.edu} 11267639Sgblack@eecs.umich.edu 11277639Sgblack@eecs.umich.eduvoid 11287639Sgblack@eecs.umich.eduNSGigE::devIntrPost(uint32_t interrupts) 11297639Sgblack@eecs.umich.edu{ 11307639Sgblack@eecs.umich.edu if (interrupts & ISR_RESERVE) 11317639Sgblack@eecs.umich.edu panic("Cannot set a reserved interrupt"); 11327639Sgblack@eecs.umich.edu 11337639Sgblack@eecs.umich.edu if (interrupts & ISR_NOIMPL) 11347639Sgblack@eecs.umich.edu warn("interrupt not implemented %#x\n", interrupts); 11357639Sgblack@eecs.umich.edu 11367639Sgblack@eecs.umich.edu interrupts &= ISR_IMPL; 11377639Sgblack@eecs.umich.edu regs.isr |= interrupts; 11387639Sgblack@eecs.umich.edu 11397435Sgblack@eecs.umich.edu if (interrupts & regs.imr) { 11407639Sgblack@eecs.umich.edu if (interrupts & ISR_SWI) { 11417639Sgblack@eecs.umich.edu totalSwi++; 11427639Sgblack@eecs.umich.edu } 11437639Sgblack@eecs.umich.edu if (interrupts & ISR_RXIDLE) { 11447435Sgblack@eecs.umich.edu totalRxIdle++; 11457639Sgblack@eecs.umich.edu } 11467639Sgblack@eecs.umich.edu if (interrupts & ISR_RXOK) { 11477639Sgblack@eecs.umich.edu totalRxOk++; 11487639Sgblack@eecs.umich.edu } 11497639Sgblack@eecs.umich.edu if (interrupts & ISR_RXDESC) { 11507639Sgblack@eecs.umich.edu totalRxDesc++; 11517639Sgblack@eecs.umich.edu } 11527639Sgblack@eecs.umich.edu if (interrupts & ISR_TXOK) { 11537639Sgblack@eecs.umich.edu totalTxOk++; 11547639Sgblack@eecs.umich.edu } 11557639Sgblack@eecs.umich.edu if (interrupts & ISR_TXIDLE) { 11567639Sgblack@eecs.umich.edu totalTxIdle++; 11577639Sgblack@eecs.umich.edu } 11587639Sgblack@eecs.umich.edu if (interrupts & ISR_TXDESC) { 11597639Sgblack@eecs.umich.edu totalTxDesc++; 11607639Sgblack@eecs.umich.edu } 11617639Sgblack@eecs.umich.edu if (interrupts & ISR_RXORN) { 11627639Sgblack@eecs.umich.edu totalRxOrn++; 11637639Sgblack@eecs.umich.edu } 11647435Sgblack@eecs.umich.edu } 11657639Sgblack@eecs.umich.edu 11667639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 11677639Sgblack@eecs.umich.edu "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 11687639Sgblack@eecs.umich.edu interrupts, regs.isr, regs.imr); 11697435Sgblack@eecs.umich.edu 11707639Sgblack@eecs.umich.edu if ((regs.isr & regs.imr)) { 11717639Sgblack@eecs.umich.edu Tick when = curTick; 11727639Sgblack@eecs.umich.edu if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 11737639Sgblack@eecs.umich.edu when += intrDelay; 11747639Sgblack@eecs.umich.edu cpuIntrPost(when); 11757639Sgblack@eecs.umich.edu } 11767639Sgblack@eecs.umich.edu} 11777639Sgblack@eecs.umich.edu 11787639Sgblack@eecs.umich.edu/* writing this interrupt counting stats inside this means that this function 11797639Sgblack@eecs.umich.edu is now limited to being used to clear all interrupts upon the kernel 11807639Sgblack@eecs.umich.edu reading isr and servicing. just telling you in case you were thinking 11817639Sgblack@eecs.umich.edu of expanding use. 11827639Sgblack@eecs.umich.edu*/ 11837639Sgblack@eecs.umich.eduvoid 11847639Sgblack@eecs.umich.eduNSGigE::devIntrClear(uint32_t interrupts) 11857639Sgblack@eecs.umich.edu{ 11867639Sgblack@eecs.umich.edu if (interrupts & ISR_RESERVE) 11877639Sgblack@eecs.umich.edu panic("Cannot clear a reserved interrupt"); 11887639Sgblack@eecs.umich.edu 11897435Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_SWI) { 11907639Sgblack@eecs.umich.edu postedSwi++; 11917639Sgblack@eecs.umich.edu } 11927639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXIDLE) { 11937639Sgblack@eecs.umich.edu postedRxIdle++; 11947639Sgblack@eecs.umich.edu } 11957639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXOK) { 11967639Sgblack@eecs.umich.edu postedRxOk++; 11977639Sgblack@eecs.umich.edu } 11987639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXDESC) { 11997639Sgblack@eecs.umich.edu postedRxDesc++; 12007639Sgblack@eecs.umich.edu } 12017639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXOK) { 12027639Sgblack@eecs.umich.edu postedTxOk++; 12037639Sgblack@eecs.umich.edu } 12047639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXIDLE) { 12057639Sgblack@eecs.umich.edu postedTxIdle++; 12067639Sgblack@eecs.umich.edu } 12077639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_TXDESC) { 12087639Sgblack@eecs.umich.edu postedTxDesc++; 12097435Sgblack@eecs.umich.edu } 12107435Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_RXORN) { 12117435Sgblack@eecs.umich.edu postedRxOrn++; 12127435Sgblack@eecs.umich.edu } 12137639Sgblack@eecs.umich.edu 12147639Sgblack@eecs.umich.edu if (regs.isr & regs.imr & ISR_IMPL) 12157639Sgblack@eecs.umich.edu postedInterrupts++; 12167639Sgblack@eecs.umich.edu 12177639Sgblack@eecs.umich.edu interrupts &= ~ISR_NOIMPL; 12187639Sgblack@eecs.umich.edu regs.isr &= ~interrupts; 12197639Sgblack@eecs.umich.edu 12207639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 12217435Sgblack@eecs.umich.edu "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 12227435Sgblack@eecs.umich.edu interrupts, regs.isr, regs.imr); 12237435Sgblack@eecs.umich.edu 12247435Sgblack@eecs.umich.edu if (!(regs.isr & regs.imr)) 12257435Sgblack@eecs.umich.edu cpuIntrClear(); 12267639Sgblack@eecs.umich.edu} 12277639Sgblack@eecs.umich.edu 12287639Sgblack@eecs.umich.eduvoid 12297639Sgblack@eecs.umich.eduNSGigE::devIntrChangeMask() 12307639Sgblack@eecs.umich.edu{ 12317639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 12327639Sgblack@eecs.umich.edu regs.isr, regs.imr, regs.isr & regs.imr); 12337639Sgblack@eecs.umich.edu 12347435Sgblack@eecs.umich.edu if (regs.isr & regs.imr) 12357435Sgblack@eecs.umich.edu cpuIntrPost(curTick); 12367639Sgblack@eecs.umich.edu else 12377639Sgblack@eecs.umich.edu cpuIntrClear(); 12387639Sgblack@eecs.umich.edu} 12397639Sgblack@eecs.umich.edu 12407639Sgblack@eecs.umich.eduvoid 12417639Sgblack@eecs.umich.eduNSGigE::cpuIntrPost(Tick when) 12427639Sgblack@eecs.umich.edu{ 12437639Sgblack@eecs.umich.edu // If the interrupt you want to post is later than an interrupt 12447639Sgblack@eecs.umich.edu // already scheduled, just let it post in the coming one and don't 12457639Sgblack@eecs.umich.edu // schedule another. 12467639Sgblack@eecs.umich.edu // HOWEVER, must be sure that the scheduled intrTick is in the 12477639Sgblack@eecs.umich.edu // future (this was formerly the source of a bug) 12487639Sgblack@eecs.umich.edu /** 12497639Sgblack@eecs.umich.edu * @todo this warning should be removed and the intrTick code should 12507639Sgblack@eecs.umich.edu * be fixed. 12517639Sgblack@eecs.umich.edu */ 12527639Sgblack@eecs.umich.edu assert(when >= curTick); 12537639Sgblack@eecs.umich.edu assert(intrTick >= curTick || intrTick == 0); 12547639Sgblack@eecs.umich.edu if (when > intrTick && intrTick != 0) { 12557435Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 12567639Sgblack@eecs.umich.edu intrTick); 12577639Sgblack@eecs.umich.edu return; 12587639Sgblack@eecs.umich.edu } 12597639Sgblack@eecs.umich.edu 12607435Sgblack@eecs.umich.edu intrTick = when; 12617639Sgblack@eecs.umich.edu if (intrTick < curTick) { 12627639Sgblack@eecs.umich.edu debug_break(); 12637639Sgblack@eecs.umich.edu intrTick = curTick; 12647639Sgblack@eecs.umich.edu } 12657639Sgblack@eecs.umich.edu 12667639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 12677639Sgblack@eecs.umich.edu intrTick); 12687639Sgblack@eecs.umich.edu 12697639Sgblack@eecs.umich.edu if (intrEvent) 12707639Sgblack@eecs.umich.edu intrEvent->squash(); 12717639Sgblack@eecs.umich.edu intrEvent = new IntrEvent(this, true); 12727639Sgblack@eecs.umich.edu intrEvent->schedule(intrTick); 12737639Sgblack@eecs.umich.edu} 12747639Sgblack@eecs.umich.edu 12757639Sgblack@eecs.umich.eduvoid 12767639Sgblack@eecs.umich.eduNSGigE::cpuInterrupt() 12777639Sgblack@eecs.umich.edu{ 12787639Sgblack@eecs.umich.edu assert(intrTick == curTick); 12797639Sgblack@eecs.umich.edu 12807435Sgblack@eecs.umich.edu // Whether or not there's a pending interrupt, we don't care about 12817435Sgblack@eecs.umich.edu // it anymore 12827435Sgblack@eecs.umich.edu intrEvent = 0; 12837435Sgblack@eecs.umich.edu intrTick = 0; 12847639Sgblack@eecs.umich.edu 12857639Sgblack@eecs.umich.edu // Don't send an interrupt if there's already one 12867639Sgblack@eecs.umich.edu if (cpuPendingIntr) { 12877639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 12887639Sgblack@eecs.umich.edu "would send an interrupt now, but there's already pending\n"); 12897639Sgblack@eecs.umich.edu } else { 12907639Sgblack@eecs.umich.edu // Send interrupt 12917639Sgblack@eecs.umich.edu cpuPendingIntr = true; 12927639Sgblack@eecs.umich.edu 12937639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "posting interrupt\n"); 12947639Sgblack@eecs.umich.edu intrPost(); 12957639Sgblack@eecs.umich.edu } 12967639Sgblack@eecs.umich.edu} 12977639Sgblack@eecs.umich.edu 12987639Sgblack@eecs.umich.eduvoid 12997639Sgblack@eecs.umich.eduNSGigE::cpuIntrClear() 13007639Sgblack@eecs.umich.edu{ 13017639Sgblack@eecs.umich.edu if (!cpuPendingIntr) 13027639Sgblack@eecs.umich.edu return; 13037639Sgblack@eecs.umich.edu 13047639Sgblack@eecs.umich.edu if (intrEvent) { 13057639Sgblack@eecs.umich.edu intrEvent->squash(); 13067639Sgblack@eecs.umich.edu intrEvent = 0; 13077435Sgblack@eecs.umich.edu } 13087435Sgblack@eecs.umich.edu 13097639Sgblack@eecs.umich.edu intrTick = 0; 13107639Sgblack@eecs.umich.edu 13117639Sgblack@eecs.umich.edu cpuPendingIntr = false; 13127639Sgblack@eecs.umich.edu 13137639Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, "clearing interrupt\n"); 13147639Sgblack@eecs.umich.edu intrClear(); 13157639Sgblack@eecs.umich.edu} 13167639Sgblack@eecs.umich.edu 13177639Sgblack@eecs.umich.edubool 13187639Sgblack@eecs.umich.eduNSGigE::cpuIntrPending() const 13197639Sgblack@eecs.umich.edu{ return cpuPendingIntr; } 13207639Sgblack@eecs.umich.edu 13217639Sgblack@eecs.umich.eduvoid 13227639Sgblack@eecs.umich.eduNSGigE::txReset() 13237639Sgblack@eecs.umich.edu{ 13247639Sgblack@eecs.umich.edu 13257639Sgblack@eecs.umich.edu DPRINTF(Ethernet, "transmit reset\n"); 13267639Sgblack@eecs.umich.edu 13277639Sgblack@eecs.umich.edu CTDD = false; 13287639Sgblack@eecs.umich.edu txEnable = false;; 13297639Sgblack@eecs.umich.edu txFragPtr = 0; 13307639Sgblack@eecs.umich.edu assert(txDescCnt == 0); 13317639Sgblack@eecs.umich.edu txFifo.clear(); 13327435Sgblack@eecs.umich.edu txState = txIdle; 13337639Sgblack@eecs.umich.edu assert(txDmaState == dmaIdle); 13347639Sgblack@eecs.umich.edu} 13357639Sgblack@eecs.umich.edu 13367639Sgblack@eecs.umich.eduvoid 13377639Sgblack@eecs.umich.eduNSGigE::rxReset() 13387639Sgblack@eecs.umich.edu{ 13397639Sgblack@eecs.umich.edu DPRINTF(Ethernet, "receive reset\n"); 13407639Sgblack@eecs.umich.edu 13417639Sgblack@eecs.umich.edu CRDD = false; 13427639Sgblack@eecs.umich.edu assert(rxPktBytes == 0); 13437639Sgblack@eecs.umich.edu rxEnable = false; 13447639Sgblack@eecs.umich.edu rxFragPtr = 0; 13457639Sgblack@eecs.umich.edu assert(rxDescCnt == 0); 13467639Sgblack@eecs.umich.edu assert(rxDmaState == dmaIdle); 13477639Sgblack@eecs.umich.edu rxFifo.clear(); 13487639Sgblack@eecs.umich.edu rxState = rxIdle; 13497639Sgblack@eecs.umich.edu} 13507639Sgblack@eecs.umich.edu 13517639Sgblack@eecs.umich.eduvoid 13527639Sgblack@eecs.umich.eduNSGigE::regsReset() 13537639Sgblack@eecs.umich.edu{ 13547639Sgblack@eecs.umich.edu memset(®s, 0, sizeof(regs)); 13557639Sgblack@eecs.umich.edu regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 13567435Sgblack@eecs.umich.edu regs.mear = 0x12; 13577435Sgblack@eecs.umich.edu regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 13587435Sgblack@eecs.umich.edu // fill threshold to 32 bytes 13597435Sgblack@eecs.umich.edu regs.rxcfg = 0x4; // set drain threshold to 16 bytes 13607435Sgblack@eecs.umich.edu regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 13617435Sgblack@eecs.umich.edu regs.mibc = MIBC_FRZ; 13627435Sgblack@eecs.umich.edu regs.vdr = 0x81; // set the vlan tag type to 802.1q 13637435Sgblack@eecs.umich.edu regs.tesr = 0xc000; // TBI capable of both full and half duplex 13647435Sgblack@eecs.umich.edu regs.brar = 0xffffffff; 13657639Sgblack@eecs.umich.edu 13667639Sgblack@eecs.umich.edu extstsEnable = false; 13677639Sgblack@eecs.umich.edu acceptBroadcast = false; 13687639Sgblack@eecs.umich.edu acceptMulticast = false; 13697639Sgblack@eecs.umich.edu acceptUnicast = false; 13707639Sgblack@eecs.umich.edu acceptPerfect = false; 13717639Sgblack@eecs.umich.edu acceptArp = false; 13727639Sgblack@eecs.umich.edu} 13737435Sgblack@eecs.umich.edu 13747435Sgblack@eecs.umich.edubool 13757435Sgblack@eecs.umich.eduNSGigE::doRxDmaRead() 13767435Sgblack@eecs.umich.edu{ 13777639Sgblack@eecs.umich.edu assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 13787639Sgblack@eecs.umich.edu rxDmaState = dmaReading; 13797639Sgblack@eecs.umich.edu 13807639Sgblack@eecs.umich.edu if (dmaPending()) 13817639Sgblack@eecs.umich.edu rxDmaState = dmaReadWaiting; 13827639Sgblack@eecs.umich.edu else 13837639Sgblack@eecs.umich.edu dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 13847639Sgblack@eecs.umich.edu 13857639Sgblack@eecs.umich.edu return true; 13867639Sgblack@eecs.umich.edu} 13877639Sgblack@eecs.umich.edu 13887639Sgblack@eecs.umich.eduvoid 13897639Sgblack@eecs.umich.eduNSGigE::rxDmaReadDone() 13907639Sgblack@eecs.umich.edu{ 13917639Sgblack@eecs.umich.edu assert(rxDmaState == dmaReading); 13927639Sgblack@eecs.umich.edu rxDmaState = dmaIdle; 13937639Sgblack@eecs.umich.edu 13947639Sgblack@eecs.umich.edu DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 13957639Sgblack@eecs.umich.edu rxDmaAddr, rxDmaLen); 13967639Sgblack@eecs.umich.edu DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 13977639Sgblack@eecs.umich.edu 13987639Sgblack@eecs.umich.edu // If the transmit state machine has a pending DMA, let it go first 13997435Sgblack@eecs.umich.edu if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 14007639Sgblack@eecs.umich.edu txKick(); 14017639Sgblack@eecs.umich.edu 14027639Sgblack@eecs.umich.edu rxKick(); 14037639Sgblack@eecs.umich.edu} 14047639Sgblack@eecs.umich.edu 14057639Sgblack@eecs.umich.edubool 14067639Sgblack@eecs.umich.eduNSGigE::doRxDmaWrite() 14077639Sgblack@eecs.umich.edu{ 14087639Sgblack@eecs.umich.edu assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 14097639Sgblack@eecs.umich.edu rxDmaState = dmaWriting; 14107639Sgblack@eecs.umich.edu 14117639Sgblack@eecs.umich.edu if (dmaPending()) 14127639Sgblack@eecs.umich.edu rxDmaState = dmaWriteWaiting; 14137639Sgblack@eecs.umich.edu else 14147639Sgblack@eecs.umich.edu dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 14157639Sgblack@eecs.umich.edu return true; 14167435Sgblack@eecs.umich.edu} 14177639Sgblack@eecs.umich.edu 14187639Sgblack@eecs.umich.eduvoid 14197639Sgblack@eecs.umich.eduNSGigE::rxDmaWriteDone() 14207639Sgblack@eecs.umich.edu{ 14217639Sgblack@eecs.umich.edu assert(rxDmaState == dmaWriting); 14227639Sgblack@eecs.umich.edu rxDmaState = dmaIdle; 14237639Sgblack@eecs.umich.edu 14247435Sgblack@eecs.umich.edu DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 14257639Sgblack@eecs.umich.edu rxDmaAddr, rxDmaLen); 14267639Sgblack@eecs.umich.edu DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 14277435Sgblack@eecs.umich.edu 14287639Sgblack@eecs.umich.edu // If the transmit state machine has a pending DMA, let it go first 14297639Sgblack@eecs.umich.edu if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 14307435Sgblack@eecs.umich.edu txKick(); 14317639Sgblack@eecs.umich.edu 14327639Sgblack@eecs.umich.edu rxKick(); 14337435Sgblack@eecs.umich.edu} 14347639Sgblack@eecs.umich.edu 14357639Sgblack@eecs.umich.eduvoid 14367435Sgblack@eecs.umich.eduNSGigE::rxKick() 14377639Sgblack@eecs.umich.edu{ 14387639Sgblack@eecs.umich.edu bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 14397435Sgblack@eecs.umich.edu 14407639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, 14417639Sgblack@eecs.umich.edu "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 14427639Sgblack@eecs.umich.edu NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 14437639Sgblack@eecs.umich.edu 14447435Sgblack@eecs.umich.edu Addr link, bufptr; 14457639Sgblack@eecs.umich.edu uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 14467639Sgblack@eecs.umich.edu uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 14477435Sgblack@eecs.umich.edu 14487639Sgblack@eecs.umich.edu next: 14497639Sgblack@eecs.umich.edu if (clock) { 14507435Sgblack@eecs.umich.edu if (rxKickTick > curTick) { 14517639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 14527639Sgblack@eecs.umich.edu rxKickTick); 14537435Sgblack@eecs.umich.edu 14547639Sgblack@eecs.umich.edu goto exit; 14557639Sgblack@eecs.umich.edu } 14567435Sgblack@eecs.umich.edu 14577435Sgblack@eecs.umich.edu // Go to the next state machine clock tick. 14587435Sgblack@eecs.umich.edu rxKickTick = curTick + cycles(1); 14597435Sgblack@eecs.umich.edu } 14607435Sgblack@eecs.umich.edu 14617435Sgblack@eecs.umich.edu switch(rxDmaState) { 14627639Sgblack@eecs.umich.edu case dmaReadWaiting: 14637639Sgblack@eecs.umich.edu if (doRxDmaRead()) 14647639Sgblack@eecs.umich.edu goto exit; 14657639Sgblack@eecs.umich.edu break; 14667639Sgblack@eecs.umich.edu case dmaWriteWaiting: 14677639Sgblack@eecs.umich.edu if (doRxDmaWrite()) 14687639Sgblack@eecs.umich.edu goto exit; 14697639Sgblack@eecs.umich.edu break; 14707639Sgblack@eecs.umich.edu default: 14717639Sgblack@eecs.umich.edu break; 14727435Sgblack@eecs.umich.edu } 14737639Sgblack@eecs.umich.edu 14747639Sgblack@eecs.umich.edu link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 14757639Sgblack@eecs.umich.edu bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 14767639Sgblack@eecs.umich.edu 14777639Sgblack@eecs.umich.edu // see state machine from spec for details 14787639Sgblack@eecs.umich.edu // the way this works is, if you finish work on one state and can 14797639Sgblack@eecs.umich.edu // go directly to another, you do that through jumping to the 14807639Sgblack@eecs.umich.edu // label "next". however, if you have intermediate work, like DMA 14817639Sgblack@eecs.umich.edu // so that you can't go to the next state yet, you go to exit and 14827639Sgblack@eecs.umich.edu // exit the loop. however, when the DMA is done it will trigger 14837435Sgblack@eecs.umich.edu // an event and come back to this loop. 14847639Sgblack@eecs.umich.edu switch (rxState) { 14857639Sgblack@eecs.umich.edu case rxIdle: 14867639Sgblack@eecs.umich.edu if (!rxEnable) { 14877639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 14887639Sgblack@eecs.umich.edu goto exit; 14897639Sgblack@eecs.umich.edu } 14907639Sgblack@eecs.umich.edu 14917639Sgblack@eecs.umich.edu if (CRDD) { 14927639Sgblack@eecs.umich.edu rxState = rxDescRefr; 14937639Sgblack@eecs.umich.edu 14947435Sgblack@eecs.umich.edu rxDmaAddr = regs.rxdp & 0x3fffffff; 14957639Sgblack@eecs.umich.edu rxDmaData = 14967639Sgblack@eecs.umich.edu is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 14977639Sgblack@eecs.umich.edu rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 14987639Sgblack@eecs.umich.edu rxDmaFree = dmaDescFree; 14997639Sgblack@eecs.umich.edu 15007639Sgblack@eecs.umich.edu descDmaReads++; 15017639Sgblack@eecs.umich.edu descDmaRdBytes += rxDmaLen; 15027639Sgblack@eecs.umich.edu 15037639Sgblack@eecs.umich.edu if (doRxDmaRead()) 15047639Sgblack@eecs.umich.edu goto exit; 15057435Sgblack@eecs.umich.edu } else { 15067639Sgblack@eecs.umich.edu rxState = rxDescRead; 15077639Sgblack@eecs.umich.edu 15087639Sgblack@eecs.umich.edu rxDmaAddr = regs.rxdp & 0x3fffffff; 15097639Sgblack@eecs.umich.edu rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 15107639Sgblack@eecs.umich.edu rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 15117639Sgblack@eecs.umich.edu rxDmaFree = dmaDescFree; 15127639Sgblack@eecs.umich.edu 15137639Sgblack@eecs.umich.edu descDmaReads++; 15147639Sgblack@eecs.umich.edu descDmaRdBytes += rxDmaLen; 15157639Sgblack@eecs.umich.edu 15167435Sgblack@eecs.umich.edu if (doRxDmaRead()) 15177639Sgblack@eecs.umich.edu goto exit; 15187639Sgblack@eecs.umich.edu } 15197639Sgblack@eecs.umich.edu break; 15207639Sgblack@eecs.umich.edu 15217639Sgblack@eecs.umich.edu case rxDescRefr: 15227639Sgblack@eecs.umich.edu if (rxDmaState != dmaIdle) 15237639Sgblack@eecs.umich.edu goto exit; 15247639Sgblack@eecs.umich.edu 15257639Sgblack@eecs.umich.edu rxState = rxAdvance; 15267435Sgblack@eecs.umich.edu break; 15277639Sgblack@eecs.umich.edu 15287639Sgblack@eecs.umich.edu case rxDescRead: 15297639Sgblack@eecs.umich.edu if (rxDmaState != dmaIdle) 15307639Sgblack@eecs.umich.edu goto exit; 15317639Sgblack@eecs.umich.edu 15327639Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 15337639Sgblack@eecs.umich.edu regs.rxdp & 0x3fffffff); 15347639Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 15357639Sgblack@eecs.umich.edu "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 15367435Sgblack@eecs.umich.edu link, bufptr, cmdsts, extsts); 15377435Sgblack@eecs.umich.edu 15387435Sgblack@eecs.umich.edu if (cmdsts & CMDSTS_OWN) { 15397435Sgblack@eecs.umich.edu devIntrPost(ISR_RXIDLE); 15407639Sgblack@eecs.umich.edu rxState = rxIdle; 15417639Sgblack@eecs.umich.edu goto exit; 15427639Sgblack@eecs.umich.edu } else { 15437639Sgblack@eecs.umich.edu rxState = rxFifoBlock; 15447435Sgblack@eecs.umich.edu rxFragPtr = bufptr; 15457639Sgblack@eecs.umich.edu rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 15467639Sgblack@eecs.umich.edu } 15477435Sgblack@eecs.umich.edu break; 15487639Sgblack@eecs.umich.edu 15497639Sgblack@eecs.umich.edu case rxFifoBlock: 15507435Sgblack@eecs.umich.edu if (!rxPacket) { 15517639Sgblack@eecs.umich.edu /** 15527639Sgblack@eecs.umich.edu * @todo in reality, we should be able to start processing 15537435Sgblack@eecs.umich.edu * the packet as it arrives, and not have to wait for the 15547435Sgblack@eecs.umich.edu * full packet ot be in the receive fifo. 15557639Sgblack@eecs.umich.edu */ 15567639Sgblack@eecs.umich.edu if (rxFifo.empty()) 15577435Sgblack@eecs.umich.edu goto exit; 15587639Sgblack@eecs.umich.edu 15597639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 15607435Sgblack@eecs.umich.edu 15617435Sgblack@eecs.umich.edu // If we don't have a packet, grab a new one from the fifo. 15627639Sgblack@eecs.umich.edu rxPacket = rxFifo.front(); 15637639Sgblack@eecs.umich.edu rxPktBytes = rxPacket->length; 15647639Sgblack@eecs.umich.edu rxPacketBufPtr = rxPacket->data; 15657639Sgblack@eecs.umich.edu 15667639Sgblack@eecs.umich.edu#if TRACING_ON 15677639Sgblack@eecs.umich.edu if (DTRACE(Ethernet)) { 15687639Sgblack@eecs.umich.edu IpPtr ip(rxPacket); 15697435Sgblack@eecs.umich.edu if (ip) { 15707435Sgblack@eecs.umich.edu DPRINTF(Ethernet, "ID is %d\n", ip->id()); 15717639Sgblack@eecs.umich.edu TcpPtr tcp(ip); 15727639Sgblack@eecs.umich.edu if (tcp) { 15737639Sgblack@eecs.umich.edu DPRINTF(Ethernet, 15747639Sgblack@eecs.umich.edu "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 15757639Sgblack@eecs.umich.edu tcp->sport(), tcp->dport(), tcp->seq(), 15767639Sgblack@eecs.umich.edu tcp->ack()); 15777639Sgblack@eecs.umich.edu } 15787639Sgblack@eecs.umich.edu } 15797639Sgblack@eecs.umich.edu } 15807435Sgblack@eecs.umich.edu#endif 15817435Sgblack@eecs.umich.edu 15827435Sgblack@eecs.umich.edu // sanity check - i think the driver behaves like this 15837435Sgblack@eecs.umich.edu assert(rxDescCnt >= rxPktBytes); 15847435Sgblack@eecs.umich.edu rxFifo.pop(); 15857435Sgblack@eecs.umich.edu } 15867639Sgblack@eecs.umich.edu 15877639Sgblack@eecs.umich.edu 15887639Sgblack@eecs.umich.edu // dont' need the && rxDescCnt > 0 if driver sanity check 15897435Sgblack@eecs.umich.edu // above holds 15907639Sgblack@eecs.umich.edu if (rxPktBytes > 0) { 15917639Sgblack@eecs.umich.edu rxState = rxFragWrite; 15927639Sgblack@eecs.umich.edu // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 15937435Sgblack@eecs.umich.edu // check holds 15947435Sgblack@eecs.umich.edu rxXferLen = rxPktBytes; 15957435Sgblack@eecs.umich.edu 15967435Sgblack@eecs.umich.edu rxDmaAddr = rxFragPtr & 0x3fffffff; 15977435Sgblack@eecs.umich.edu rxDmaData = rxPacketBufPtr; 15987435Sgblack@eecs.umich.edu rxDmaLen = rxXferLen; 15997435Sgblack@eecs.umich.edu rxDmaFree = dmaDataFree; 16007435Sgblack@eecs.umich.edu 16017639Sgblack@eecs.umich.edu if (doRxDmaWrite()) 16027639Sgblack@eecs.umich.edu goto exit; 16037639Sgblack@eecs.umich.edu 16047639Sgblack@eecs.umich.edu } else { 16057639Sgblack@eecs.umich.edu rxState = rxDescWrite; 16067639Sgblack@eecs.umich.edu 16077639Sgblack@eecs.umich.edu //if (rxPktBytes == 0) { /* packet is done */ 16087639Sgblack@eecs.umich.edu assert(rxPktBytes == 0); 16097639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "done with receiving packet\n"); 16107639Sgblack@eecs.umich.edu 16117639Sgblack@eecs.umich.edu cmdsts |= CMDSTS_OWN; 16127639Sgblack@eecs.umich.edu cmdsts &= ~CMDSTS_MORE; 16137639Sgblack@eecs.umich.edu cmdsts |= CMDSTS_OK; 16147639Sgblack@eecs.umich.edu cmdsts &= 0xffff0000; 16157639Sgblack@eecs.umich.edu cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 16167639Sgblack@eecs.umich.edu 16177639Sgblack@eecs.umich.edu#if 0 16187639Sgblack@eecs.umich.edu /* 16197639Sgblack@eecs.umich.edu * all the driver uses these are for its own stats keeping 16207639Sgblack@eecs.umich.edu * which we don't care about, aren't necessary for 16217639Sgblack@eecs.umich.edu * functionality and doing this would just slow us down. 16227639Sgblack@eecs.umich.edu * if they end up using this in a later version for 16237639Sgblack@eecs.umich.edu * functional purposes, just undef 16247639Sgblack@eecs.umich.edu */ 16257639Sgblack@eecs.umich.edu if (rxFilterEnable) { 16267639Sgblack@eecs.umich.edu cmdsts &= ~CMDSTS_DEST_MASK; 16277639Sgblack@eecs.umich.edu const EthAddr &dst = rxFifoFront()->dst(); 16287639Sgblack@eecs.umich.edu if (dst->unicast()) 16297639Sgblack@eecs.umich.edu cmdsts |= CMDSTS_DEST_SELF; 16307639Sgblack@eecs.umich.edu if (dst->multicast()) 16317639Sgblack@eecs.umich.edu cmdsts |= CMDSTS_DEST_MULTI; 16327639Sgblack@eecs.umich.edu if (dst->broadcast()) 16337639Sgblack@eecs.umich.edu cmdsts |= CMDSTS_DEST_MASK; 16347639Sgblack@eecs.umich.edu } 16357639Sgblack@eecs.umich.edu#endif 16367639Sgblack@eecs.umich.edu 16377639Sgblack@eecs.umich.edu IpPtr ip(rxPacket); 16387639Sgblack@eecs.umich.edu if (extstsEnable && ip) { 16397639Sgblack@eecs.umich.edu extsts |= EXTSTS_IPPKT; 16407639Sgblack@eecs.umich.edu rxIpChecksums++; 16417639Sgblack@eecs.umich.edu if (cksum(ip) != 0) { 16427435Sgblack@eecs.umich.edu DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 16437639Sgblack@eecs.umich.edu extsts |= EXTSTS_IPERR; 16447639Sgblack@eecs.umich.edu } 16457639Sgblack@eecs.umich.edu TcpPtr tcp(ip); 16467639Sgblack@eecs.umich.edu UdpPtr udp(ip); 16477639Sgblack@eecs.umich.edu if (tcp) { 16487639Sgblack@eecs.umich.edu extsts |= EXTSTS_TCPPKT; 16497639Sgblack@eecs.umich.edu rxTcpChecksums++; 16507639Sgblack@eecs.umich.edu if (cksum(tcp) != 0) { 16517639Sgblack@eecs.umich.edu DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 16527639Sgblack@eecs.umich.edu extsts |= EXTSTS_TCPERR; 16537639Sgblack@eecs.umich.edu 16547639Sgblack@eecs.umich.edu } 16557639Sgblack@eecs.umich.edu } else if (udp) { 16567435Sgblack@eecs.umich.edu extsts |= EXTSTS_UDPPKT; 16577639Sgblack@eecs.umich.edu rxUdpChecksums++; 16587639Sgblack@eecs.umich.edu if (cksum(udp) != 0) { 16597639Sgblack@eecs.umich.edu DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 16607639Sgblack@eecs.umich.edu extsts |= EXTSTS_UDPERR; 16617639Sgblack@eecs.umich.edu } 16627639Sgblack@eecs.umich.edu } 16637639Sgblack@eecs.umich.edu } 16647639Sgblack@eecs.umich.edu rxPacket = 0; 16657639Sgblack@eecs.umich.edu 16667639Sgblack@eecs.umich.edu /* 16677639Sgblack@eecs.umich.edu * the driver seems to always receive into desc buffers 16687639Sgblack@eecs.umich.edu * of size 1514, so you never have a pkt that is split 16697639Sgblack@eecs.umich.edu * into multiple descriptors on the receive side, so 16707435Sgblack@eecs.umich.edu * i don't implement that case, hence the assert above. 16717435Sgblack@eecs.umich.edu */ 16727435Sgblack@eecs.umich.edu 16737435Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 16747435Sgblack@eecs.umich.edu "rxDesc: addr=%08x writeback cmdsts extsts\n", 16757435Sgblack@eecs.umich.edu regs.rxdp & 0x3fffffff); 16767435Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 16777435Sgblack@eecs.umich.edu "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 16787435Sgblack@eecs.umich.edu link, bufptr, cmdsts, extsts); 16797435Sgblack@eecs.umich.edu 16807435Sgblack@eecs.umich.edu rxDmaAddr = regs.rxdp & 0x3fffffff; 16817435Sgblack@eecs.umich.edu rxDmaData = &cmdsts; 16827435Sgblack@eecs.umich.edu if (is64bit) { 16837435Sgblack@eecs.umich.edu rxDmaAddr += offsetof(ns_desc64, cmdsts); 16847435Sgblack@eecs.umich.edu rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 16857435Sgblack@eecs.umich.edu } else { 16867435Sgblack@eecs.umich.edu rxDmaAddr += offsetof(ns_desc32, cmdsts); 16877435Sgblack@eecs.umich.edu rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 16887435Sgblack@eecs.umich.edu } 16897435Sgblack@eecs.umich.edu rxDmaFree = dmaDescFree; 16907435Sgblack@eecs.umich.edu 16917435Sgblack@eecs.umich.edu descDmaWrites++; 16927435Sgblack@eecs.umich.edu descDmaWrBytes += rxDmaLen; 16937435Sgblack@eecs.umich.edu 16947639Sgblack@eecs.umich.edu if (doRxDmaWrite()) 16957639Sgblack@eecs.umich.edu goto exit; 16967435Sgblack@eecs.umich.edu } 16977639Sgblack@eecs.umich.edu break; 16987435Sgblack@eecs.umich.edu 16997435Sgblack@eecs.umich.edu case rxFragWrite: 17007435Sgblack@eecs.umich.edu if (rxDmaState != dmaIdle) 17017639Sgblack@eecs.umich.edu goto exit; 17027639Sgblack@eecs.umich.edu 17037639Sgblack@eecs.umich.edu rxPacketBufPtr += rxXferLen; 17047639Sgblack@eecs.umich.edu rxFragPtr += rxXferLen; 17057639Sgblack@eecs.umich.edu rxPktBytes -= rxXferLen; 17067639Sgblack@eecs.umich.edu 17077639Sgblack@eecs.umich.edu rxState = rxFifoBlock; 17087639Sgblack@eecs.umich.edu break; 17097639Sgblack@eecs.umich.edu 17107435Sgblack@eecs.umich.edu case rxDescWrite: 17117435Sgblack@eecs.umich.edu if (rxDmaState != dmaIdle) 17127639Sgblack@eecs.umich.edu goto exit; 17137639Sgblack@eecs.umich.edu 17147639Sgblack@eecs.umich.edu assert(cmdsts & CMDSTS_OWN); 17157639Sgblack@eecs.umich.edu 17167639Sgblack@eecs.umich.edu assert(rxPacket == 0); 17177639Sgblack@eecs.umich.edu devIntrPost(ISR_RXOK); 17187639Sgblack@eecs.umich.edu 17197639Sgblack@eecs.umich.edu if (cmdsts & CMDSTS_INTR) 17207639Sgblack@eecs.umich.edu devIntrPost(ISR_RXDESC); 17217435Sgblack@eecs.umich.edu 17227435Sgblack@eecs.umich.edu if (!rxEnable) { 17237435Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "Halting the RX state machine\n"); 17247435Sgblack@eecs.umich.edu rxState = rxIdle; 17257639Sgblack@eecs.umich.edu goto exit; 17267639Sgblack@eecs.umich.edu } else 17277639Sgblack@eecs.umich.edu rxState = rxAdvance; 17287435Sgblack@eecs.umich.edu break; 17297639Sgblack@eecs.umich.edu 17307639Sgblack@eecs.umich.edu case rxAdvance: 17317639Sgblack@eecs.umich.edu if (link == 0) { 17327639Sgblack@eecs.umich.edu devIntrPost(ISR_RXIDLE); 17337639Sgblack@eecs.umich.edu rxState = rxIdle; 17347639Sgblack@eecs.umich.edu CRDD = true; 17357639Sgblack@eecs.umich.edu goto exit; 17367639Sgblack@eecs.umich.edu } else { 17377639Sgblack@eecs.umich.edu if (rxDmaState != dmaIdle) 17387639Sgblack@eecs.umich.edu goto exit; 17397435Sgblack@eecs.umich.edu rxState = rxDescRead; 17407639Sgblack@eecs.umich.edu regs.rxdp = link; 17417639Sgblack@eecs.umich.edu CRDD = false; 17427639Sgblack@eecs.umich.edu 17437639Sgblack@eecs.umich.edu rxDmaAddr = regs.rxdp & 0x3fffffff; 17447639Sgblack@eecs.umich.edu rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 17457639Sgblack@eecs.umich.edu rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 17467639Sgblack@eecs.umich.edu rxDmaFree = dmaDescFree; 17477639Sgblack@eecs.umich.edu 17487639Sgblack@eecs.umich.edu if (doRxDmaRead()) 17497639Sgblack@eecs.umich.edu goto exit; 17507435Sgblack@eecs.umich.edu } 17517435Sgblack@eecs.umich.edu break; 17527639Sgblack@eecs.umich.edu 17537639Sgblack@eecs.umich.edu default: 17547639Sgblack@eecs.umich.edu panic("Invalid rxState!"); 17557639Sgblack@eecs.umich.edu } 17567639Sgblack@eecs.umich.edu 17577639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "entering next rxState=%s\n", 17587639Sgblack@eecs.umich.edu NsRxStateStrings[rxState]); 17597639Sgblack@eecs.umich.edu goto next; 17607639Sgblack@eecs.umich.edu 17617639Sgblack@eecs.umich.edu exit: 17627639Sgblack@eecs.umich.edu /** 17637639Sgblack@eecs.umich.edu * @todo do we want to schedule a future kick? 17647435Sgblack@eecs.umich.edu */ 17657435Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 17667435Sgblack@eecs.umich.edu NsRxStateStrings[rxState]); 17677435Sgblack@eecs.umich.edu 17687435Sgblack@eecs.umich.edu if (clock && !rxKickEvent.scheduled()) 17697435Sgblack@eecs.umich.edu rxKickEvent.schedule(rxKickTick); 17707435Sgblack@eecs.umich.edu} 17717435Sgblack@eecs.umich.edu 17727435Sgblack@eecs.umich.eduvoid 17737435Sgblack@eecs.umich.eduNSGigE::transmit() 17747435Sgblack@eecs.umich.edu{ 17757435Sgblack@eecs.umich.edu if (txFifo.empty()) { 17767435Sgblack@eecs.umich.edu DPRINTF(Ethernet, "nothing to transmit\n"); 17777435Sgblack@eecs.umich.edu return; 17787435Sgblack@eecs.umich.edu } 17797639Sgblack@eecs.umich.edu 17807435Sgblack@eecs.umich.edu DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 17817435Sgblack@eecs.umich.edu txFifo.size()); 17827435Sgblack@eecs.umich.edu if (interface->sendPacket(txFifo.front())) { 17837435Sgblack@eecs.umich.edu#if TRACING_ON 17847435Sgblack@eecs.umich.edu if (DTRACE(Ethernet)) { 17857435Sgblack@eecs.umich.edu IpPtr ip(txFifo.front()); 17867356Sgblack@eecs.umich.edu if (ip) { 17877356Sgblack@eecs.umich.edu DPRINTF(Ethernet, "ID is %d\n", ip->id()); 17887356Sgblack@eecs.umich.edu TcpPtr tcp(ip); 17897356Sgblack@eecs.umich.edu if (tcp) { 17907356Sgblack@eecs.umich.edu DPRINTF(Ethernet, 17917178Sgblack@eecs.umich.edu "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 17927178Sgblack@eecs.umich.edu tcp->sport(), tcp->dport(), tcp->seq(), 17937178Sgblack@eecs.umich.edu tcp->ack()); 17947337Sgblack@eecs.umich.edu } 17957178Sgblack@eecs.umich.edu } 17967178Sgblack@eecs.umich.edu } 17977178Sgblack@eecs.umich.edu#endif 17987178Sgblack@eecs.umich.edu 17997178Sgblack@eecs.umich.edu DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 18007178Sgblack@eecs.umich.edu txBytes += txFifo.front()->length; 18017178Sgblack@eecs.umich.edu txPackets++; 18027178Sgblack@eecs.umich.edu 18037178Sgblack@eecs.umich.edu DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 18047178Sgblack@eecs.umich.edu txFifo.avail()); 18057178Sgblack@eecs.umich.edu txFifo.pop(); 18067335Sgblack@eecs.umich.edu 18077335Sgblack@eecs.umich.edu /* 18087335Sgblack@eecs.umich.edu * normally do a writeback of the descriptor here, and ONLY 18097335Sgblack@eecs.umich.edu * after that is done, send this interrupt. but since our 18107335Sgblack@eecs.umich.edu * stuff never actually fails, just do this interrupt here, 18117335Sgblack@eecs.umich.edu * otherwise the code has to stray from this nice format. 18127335Sgblack@eecs.umich.edu * besides, it's functionally the same. 18137335Sgblack@eecs.umich.edu */ 18147335Sgblack@eecs.umich.edu devIntrPost(ISR_TXOK); 18157335Sgblack@eecs.umich.edu } 18167335Sgblack@eecs.umich.edu 18177335Sgblack@eecs.umich.edu if (!txFifo.empty() && !txEvent.scheduled()) { 18187337Sgblack@eecs.umich.edu DPRINTF(Ethernet, "reschedule transmit\n"); 18197335Sgblack@eecs.umich.edu txEvent.schedule(curTick + retryTime); 18207335Sgblack@eecs.umich.edu } 18217335Sgblack@eecs.umich.edu} 18227335Sgblack@eecs.umich.edu 18237335Sgblack@eecs.umich.edubool 18247335Sgblack@eecs.umich.eduNSGigE::doTxDmaRead() 18257335Sgblack@eecs.umich.edu{ 18267335Sgblack@eecs.umich.edu assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 18277335Sgblack@eecs.umich.edu txDmaState = dmaReading; 18287335Sgblack@eecs.umich.edu 18297335Sgblack@eecs.umich.edu if (dmaPending()) 18307335Sgblack@eecs.umich.edu txDmaState = dmaReadWaiting; 18317178Sgblack@eecs.umich.edu else 18327178Sgblack@eecs.umich.edu dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 18337178Sgblack@eecs.umich.edu 18347413Sgblack@eecs.umich.edu return true; 18357639Sgblack@eecs.umich.edu} 18367413Sgblack@eecs.umich.edu 18377413Sgblack@eecs.umich.eduvoid 18387413Sgblack@eecs.umich.eduNSGigE::txDmaReadDone() 18397413Sgblack@eecs.umich.edu{ 18407413Sgblack@eecs.umich.edu assert(txDmaState == dmaReading); 18417413Sgblack@eecs.umich.edu txDmaState = dmaIdle; 18427413Sgblack@eecs.umich.edu 18437413Sgblack@eecs.umich.edu DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 18447413Sgblack@eecs.umich.edu txDmaAddr, txDmaLen); 18457413Sgblack@eecs.umich.edu DDUMP(EthernetDMA, txDmaData, txDmaLen); 18467413Sgblack@eecs.umich.edu 18477413Sgblack@eecs.umich.edu // If the receive state machine has a pending DMA, let it go first 18487413Sgblack@eecs.umich.edu if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 18497413Sgblack@eecs.umich.edu rxKick(); 18507413Sgblack@eecs.umich.edu 18517413Sgblack@eecs.umich.edu txKick(); 18527413Sgblack@eecs.umich.edu} 18537178Sgblack@eecs.umich.edu 18547178Sgblack@eecs.umich.edubool 18557178Sgblack@eecs.umich.eduNSGigE::doTxDmaWrite() 18567178Sgblack@eecs.umich.edu{ 18577178Sgblack@eecs.umich.edu assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 18587178Sgblack@eecs.umich.edu txDmaState = dmaWriting; 18597178Sgblack@eecs.umich.edu 18607178Sgblack@eecs.umich.edu if (dmaPending()) 18617178Sgblack@eecs.umich.edu txDmaState = dmaWriteWaiting; 18627178Sgblack@eecs.umich.edu else 18637178Sgblack@eecs.umich.edu dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 18647178Sgblack@eecs.umich.edu return true; 18657346Sgblack@eecs.umich.edu} 18667346Sgblack@eecs.umich.edu 18677346Sgblack@eecs.umich.eduvoid 18687346Sgblack@eecs.umich.eduNSGigE::txDmaWriteDone() 18697346Sgblack@eecs.umich.edu{ 18707346Sgblack@eecs.umich.edu assert(txDmaState == dmaWriting); 18717346Sgblack@eecs.umich.edu txDmaState = dmaIdle; 18727346Sgblack@eecs.umich.edu 18737346Sgblack@eecs.umich.edu DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 18747346Sgblack@eecs.umich.edu txDmaAddr, txDmaLen); 18757178Sgblack@eecs.umich.edu DDUMP(EthernetDMA, txDmaData, txDmaLen); 18767346Sgblack@eecs.umich.edu 18777346Sgblack@eecs.umich.edu // If the receive state machine has a pending DMA, let it go first 18787346Sgblack@eecs.umich.edu if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 18797346Sgblack@eecs.umich.edu rxKick(); 18807346Sgblack@eecs.umich.edu 18817346Sgblack@eecs.umich.edu txKick(); 18827346Sgblack@eecs.umich.edu} 18837346Sgblack@eecs.umich.edu 18847346Sgblack@eecs.umich.eduvoid 18857346Sgblack@eecs.umich.eduNSGigE::txKick() 18867346Sgblack@eecs.umich.edu{ 18877346Sgblack@eecs.umich.edu bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 18887346Sgblack@eecs.umich.edu 18897346Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 18907346Sgblack@eecs.umich.edu NsTxStateStrings[txState], is64bit ? 64 : 32); 18917178Sgblack@eecs.umich.edu 18927337Sgblack@eecs.umich.edu Addr link, bufptr; 18937337Sgblack@eecs.umich.edu uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 18947337Sgblack@eecs.umich.edu uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 18957337Sgblack@eecs.umich.edu 18967337Sgblack@eecs.umich.edu next: 18977337Sgblack@eecs.umich.edu if (clock) { 18987337Sgblack@eecs.umich.edu if (txKickTick > curTick) { 18997337Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 19007337Sgblack@eecs.umich.edu txKickTick); 19017337Sgblack@eecs.umich.edu goto exit; 19027337Sgblack@eecs.umich.edu } 19037337Sgblack@eecs.umich.edu 19047337Sgblack@eecs.umich.edu // Go to the next state machine clock tick. 19057337Sgblack@eecs.umich.edu txKickTick = curTick + cycles(1); 19067337Sgblack@eecs.umich.edu } 19077178Sgblack@eecs.umich.edu 19087178Sgblack@eecs.umich.edu switch(txDmaState) { 19097178Sgblack@eecs.umich.edu case dmaReadWaiting: 19107178Sgblack@eecs.umich.edu if (doTxDmaRead()) 19117337Sgblack@eecs.umich.edu goto exit; 19127337Sgblack@eecs.umich.edu break; 19137337Sgblack@eecs.umich.edu case dmaWriteWaiting: 19147337Sgblack@eecs.umich.edu if (doTxDmaWrite()) 19157346Sgblack@eecs.umich.edu goto exit; 19167346Sgblack@eecs.umich.edu break; 19177346Sgblack@eecs.umich.edu default: 19187346Sgblack@eecs.umich.edu break; 19197346Sgblack@eecs.umich.edu } 19207337Sgblack@eecs.umich.edu 19217178Sgblack@eecs.umich.edu link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 19227321Sgblack@eecs.umich.edu bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 19237356Sgblack@eecs.umich.edu switch (txState) { 19247321Sgblack@eecs.umich.edu case txIdle: 19257356Sgblack@eecs.umich.edu if (!txEnable) { 19267356Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 19277356Sgblack@eecs.umich.edu goto exit; 19287356Sgblack@eecs.umich.edu } 19297356Sgblack@eecs.umich.edu 19307356Sgblack@eecs.umich.edu if (CTDD) { 19317356Sgblack@eecs.umich.edu txState = txDescRefr; 19327356Sgblack@eecs.umich.edu 19337356Sgblack@eecs.umich.edu txDmaAddr = regs.txdp & 0x3fffffff; 19347356Sgblack@eecs.umich.edu txDmaData = 19357356Sgblack@eecs.umich.edu is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 19367356Sgblack@eecs.umich.edu txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 19377321Sgblack@eecs.umich.edu txDmaFree = dmaDescFree; 19387321Sgblack@eecs.umich.edu 19397321Sgblack@eecs.umich.edu descDmaReads++; 19407321Sgblack@eecs.umich.edu descDmaRdBytes += txDmaLen; 19417321Sgblack@eecs.umich.edu 19427321Sgblack@eecs.umich.edu if (doTxDmaRead()) 19437321Sgblack@eecs.umich.edu goto exit; 19447321Sgblack@eecs.umich.edu 19457321Sgblack@eecs.umich.edu } else { 19467321Sgblack@eecs.umich.edu txState = txDescRead; 19477321Sgblack@eecs.umich.edu 19487335Sgblack@eecs.umich.edu txDmaAddr = regs.txdp & 0x3fffffff; 19497335Sgblack@eecs.umich.edu txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 19507335Sgblack@eecs.umich.edu txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 19517335Sgblack@eecs.umich.edu txDmaFree = dmaDescFree; 19527335Sgblack@eecs.umich.edu 19537335Sgblack@eecs.umich.edu descDmaReads++; 19547335Sgblack@eecs.umich.edu descDmaRdBytes += txDmaLen; 19557335Sgblack@eecs.umich.edu 19567335Sgblack@eecs.umich.edu if (doTxDmaRead()) 19577321Sgblack@eecs.umich.edu goto exit; 19587323Sgblack@eecs.umich.edu } 19597323Sgblack@eecs.umich.edu break; 19607323Sgblack@eecs.umich.edu 19617323Sgblack@eecs.umich.edu case txDescRefr: 19627323Sgblack@eecs.umich.edu if (txDmaState != dmaIdle) 19637323Sgblack@eecs.umich.edu goto exit; 19647323Sgblack@eecs.umich.edu 19657323Sgblack@eecs.umich.edu txState = txAdvance; 19667323Sgblack@eecs.umich.edu break; 19677323Sgblack@eecs.umich.edu 19687394Sgblack@eecs.umich.edu case txDescRead: 19697394Sgblack@eecs.umich.edu if (txDmaState != dmaIdle) 19707394Sgblack@eecs.umich.edu goto exit; 19717394Sgblack@eecs.umich.edu 19727394Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 19737394Sgblack@eecs.umich.edu regs.txdp & 0x3fffffff); 19747323Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 19757323Sgblack@eecs.umich.edu "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 19767323Sgblack@eecs.umich.edu link, bufptr, cmdsts, extsts); 19777323Sgblack@eecs.umich.edu 19787323Sgblack@eecs.umich.edu if (cmdsts & CMDSTS_OWN) { 19797323Sgblack@eecs.umich.edu txState = txFifoBlock; 19807643Sgblack@eecs.umich.edu txFragPtr = bufptr; 19817643Sgblack@eecs.umich.edu txDescCnt = cmdsts & CMDSTS_LEN_MASK; 19827643Sgblack@eecs.umich.edu } else { 19837643Sgblack@eecs.umich.edu devIntrPost(ISR_TXIDLE); 19847643Sgblack@eecs.umich.edu txState = txIdle; 19857321Sgblack@eecs.umich.edu goto exit; 19867321Sgblack@eecs.umich.edu } 19877321Sgblack@eecs.umich.edu break; 19887335Sgblack@eecs.umich.edu 19897335Sgblack@eecs.umich.edu case txFifoBlock: 19907639Sgblack@eecs.umich.edu if (!txPacket) { 19917639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 19927335Sgblack@eecs.umich.edu txPacket = new EthPacketData(16384); 19937335Sgblack@eecs.umich.edu txPacketBufPtr = txPacket->data; 19947335Sgblack@eecs.umich.edu } 19957639Sgblack@eecs.umich.edu 19967639Sgblack@eecs.umich.edu if (txDescCnt == 0) { 19977335Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 19987639Sgblack@eecs.umich.edu if (cmdsts & CMDSTS_MORE) { 19997639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "there are more descriptors to come\n"); 20007335Sgblack@eecs.umich.edu txState = txDescWrite; 20017639Sgblack@eecs.umich.edu 20027335Sgblack@eecs.umich.edu cmdsts &= ~CMDSTS_OWN; 20037335Sgblack@eecs.umich.edu 20047335Sgblack@eecs.umich.edu txDmaAddr = regs.txdp & 0x3fffffff; 20057639Sgblack@eecs.umich.edu txDmaData = &cmdsts; 20067639Sgblack@eecs.umich.edu if (is64bit) { 20077639Sgblack@eecs.umich.edu txDmaAddr += offsetof(ns_desc64, cmdsts); 20087639Sgblack@eecs.umich.edu txDmaLen = sizeof(txDesc64.cmdsts); 20097639Sgblack@eecs.umich.edu } else { 20107639Sgblack@eecs.umich.edu txDmaAddr += offsetof(ns_desc32, cmdsts); 20117639Sgblack@eecs.umich.edu txDmaLen = sizeof(txDesc32.cmdsts); 20127639Sgblack@eecs.umich.edu } 20137639Sgblack@eecs.umich.edu txDmaFree = dmaDescFree; 20147639Sgblack@eecs.umich.edu 20157639Sgblack@eecs.umich.edu if (doTxDmaWrite()) 20167639Sgblack@eecs.umich.edu goto exit; 20177639Sgblack@eecs.umich.edu 20187639Sgblack@eecs.umich.edu } else { /* this packet is totally done */ 20197639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 20207639Sgblack@eecs.umich.edu /* deal with the the packet that just finished */ 20217639Sgblack@eecs.umich.edu if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 20227639Sgblack@eecs.umich.edu IpPtr ip(txPacket); 20237639Sgblack@eecs.umich.edu if (extsts & EXTSTS_UDPPKT) { 20247639Sgblack@eecs.umich.edu UdpPtr udp(ip); 20257639Sgblack@eecs.umich.edu udp->sum(0); 20267639Sgblack@eecs.umich.edu udp->sum(cksum(udp)); 20277639Sgblack@eecs.umich.edu txUdpChecksums++; 20287639Sgblack@eecs.umich.edu } else if (extsts & EXTSTS_TCPPKT) { 20297639Sgblack@eecs.umich.edu TcpPtr tcp(ip); 20307639Sgblack@eecs.umich.edu tcp->sum(0); 20317639Sgblack@eecs.umich.edu tcp->sum(cksum(tcp)); 20327639Sgblack@eecs.umich.edu txTcpChecksums++; 20337639Sgblack@eecs.umich.edu } 20347335Sgblack@eecs.umich.edu if (extsts & EXTSTS_IPPKT) { 20357321Sgblack@eecs.umich.edu ip->sum(0); 20367321Sgblack@eecs.umich.edu ip->sum(cksum(ip)); 20377321Sgblack@eecs.umich.edu txIpChecksums++; 20387335Sgblack@eecs.umich.edu } 20397335Sgblack@eecs.umich.edu } 20407335Sgblack@eecs.umich.edu 20417335Sgblack@eecs.umich.edu txPacket->length = txPacketBufPtr - txPacket->data; 20427335Sgblack@eecs.umich.edu // this is just because the receive can't handle a 20437335Sgblack@eecs.umich.edu // packet bigger want to make sure 20447335Sgblack@eecs.umich.edu if (txPacket->length > 1514) 20457335Sgblack@eecs.umich.edu panic("transmit packet too large, %s > 1514\n", 20467335Sgblack@eecs.umich.edu txPacket->length); 20477321Sgblack@eecs.umich.edu 20487326Sgblack@eecs.umich.edu#ifndef NDEBUG 20497326Sgblack@eecs.umich.edu bool success = 20507326Sgblack@eecs.umich.edu#endif 20517326Sgblack@eecs.umich.edu txFifo.push(txPacket); 20527326Sgblack@eecs.umich.edu assert(success); 20537326Sgblack@eecs.umich.edu 20547326Sgblack@eecs.umich.edu /* 20557326Sgblack@eecs.umich.edu * this following section is not tqo spec, but 20567326Sgblack@eecs.umich.edu * functionally shouldn't be any different. normally, 20577326Sgblack@eecs.umich.edu * the chip will wait til the transmit has occurred 20587326Sgblack@eecs.umich.edu * before writing back the descriptor because it has 20597326Sgblack@eecs.umich.edu * to wait to see that it was successfully transmitted 20607326Sgblack@eecs.umich.edu * to decide whether to set CMDSTS_OK or not. 20617326Sgblack@eecs.umich.edu * however, in the simulator since it is always 20627326Sgblack@eecs.umich.edu * successfully transmitted, and writing it exactly to 20637326Sgblack@eecs.umich.edu * spec would complicate the code, we just do it here 20647326Sgblack@eecs.umich.edu */ 20657326Sgblack@eecs.umich.edu 20667326Sgblack@eecs.umich.edu cmdsts &= ~CMDSTS_OWN; 20677326Sgblack@eecs.umich.edu cmdsts |= CMDSTS_OK; 20687326Sgblack@eecs.umich.edu 20697326Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 20707392Sgblack@eecs.umich.edu "txDesc writeback: cmdsts=%08x extsts=%08x\n", 20717392Sgblack@eecs.umich.edu cmdsts, extsts); 20727392Sgblack@eecs.umich.edu 20737392Sgblack@eecs.umich.edu txDmaFree = dmaDescFree; 20747392Sgblack@eecs.umich.edu txDmaAddr = regs.txdp & 0x3fffffff; 20757392Sgblack@eecs.umich.edu txDmaData = &cmdsts; 20767643Sgblack@eecs.umich.edu if (is64bit) { 20777643Sgblack@eecs.umich.edu txDmaAddr += offsetof(ns_desc64, cmdsts); 20787643Sgblack@eecs.umich.edu txDmaLen = 20797643Sgblack@eecs.umich.edu sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 20807643Sgblack@eecs.umich.edu } else { 20817643Sgblack@eecs.umich.edu txDmaAddr += offsetof(ns_desc32, cmdsts); 20827643Sgblack@eecs.umich.edu txDmaLen = 20837643Sgblack@eecs.umich.edu sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 20847643Sgblack@eecs.umich.edu } 20857392Sgblack@eecs.umich.edu 20867392Sgblack@eecs.umich.edu descDmaWrites++; 20877392Sgblack@eecs.umich.edu descDmaWrBytes += txDmaLen; 20887321Sgblack@eecs.umich.edu 20897321Sgblack@eecs.umich.edu transmit(); 20907335Sgblack@eecs.umich.edu txPacket = 0; 20917335Sgblack@eecs.umich.edu 20927639Sgblack@eecs.umich.edu if (!txEnable) { 20937639Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "halting TX state machine\n"); 20947639Sgblack@eecs.umich.edu txState = txIdle; 20957335Sgblack@eecs.umich.edu goto exit; 20967335Sgblack@eecs.umich.edu } else 20977335Sgblack@eecs.umich.edu txState = txAdvance; 20987335Sgblack@eecs.umich.edu 20997639Sgblack@eecs.umich.edu if (doTxDmaWrite()) 21007335Sgblack@eecs.umich.edu goto exit; 21017335Sgblack@eecs.umich.edu } 21027335Sgblack@eecs.umich.edu } else { 21037335Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 21047335Sgblack@eecs.umich.edu if (!txFifo.full()) { 21057335Sgblack@eecs.umich.edu txState = txFragRead; 21067335Sgblack@eecs.umich.edu 21077639Sgblack@eecs.umich.edu /* 21087639Sgblack@eecs.umich.edu * The number of bytes transferred is either whatever 21097335Sgblack@eecs.umich.edu * is left in the descriptor (txDescCnt), or if there 21107335Sgblack@eecs.umich.edu * is not enough room in the fifo, just whatever room 21117335Sgblack@eecs.umich.edu * is left in the fifo 21127335Sgblack@eecs.umich.edu */ 21137335Sgblack@eecs.umich.edu txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 21147335Sgblack@eecs.umich.edu 21157335Sgblack@eecs.umich.edu txDmaAddr = txFragPtr & 0x3fffffff; 21167639Sgblack@eecs.umich.edu txDmaData = txPacketBufPtr; 21177335Sgblack@eecs.umich.edu txDmaLen = txXferLen; 21187639Sgblack@eecs.umich.edu txDmaFree = dmaDataFree; 21197639Sgblack@eecs.umich.edu 21207335Sgblack@eecs.umich.edu if (doTxDmaRead()) 21217321Sgblack@eecs.umich.edu goto exit; 21227321Sgblack@eecs.umich.edu } else { 21237321Sgblack@eecs.umich.edu txState = txFifoBlock; 21247321Sgblack@eecs.umich.edu transmit(); 21257321Sgblack@eecs.umich.edu 21267356Sgblack@eecs.umich.edu goto exit; 21277356Sgblack@eecs.umich.edu } 21287356Sgblack@eecs.umich.edu 21297356Sgblack@eecs.umich.edu } 21307356Sgblack@eecs.umich.edu break; 21317356Sgblack@eecs.umich.edu 21327363Sgblack@eecs.umich.edu case txFragRead: 21337363Sgblack@eecs.umich.edu if (txDmaState != dmaIdle) 21347363Sgblack@eecs.umich.edu goto exit; 21357363Sgblack@eecs.umich.edu 21367363Sgblack@eecs.umich.edu txPacketBufPtr += txXferLen; 21377363Sgblack@eecs.umich.edu txFragPtr += txXferLen; 21387363Sgblack@eecs.umich.edu txDescCnt -= txXferLen; 21397363Sgblack@eecs.umich.edu txFifo.reserve(txXferLen); 21407363Sgblack@eecs.umich.edu 21417363Sgblack@eecs.umich.edu txState = txFifoBlock; 21427363Sgblack@eecs.umich.edu break; 21437363Sgblack@eecs.umich.edu 21447363Sgblack@eecs.umich.edu case txDescWrite: 21457363Sgblack@eecs.umich.edu if (txDmaState != dmaIdle) 21467372Sgblack@eecs.umich.edu goto exit; 21477389Sgblack@eecs.umich.edu 21487389Sgblack@eecs.umich.edu if (cmdsts & CMDSTS_INTR) 21497372Sgblack@eecs.umich.edu devIntrPost(ISR_TXDESC); 21507372Sgblack@eecs.umich.edu 21517372Sgblack@eecs.umich.edu if (!txEnable) { 21527372Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "halting TX state machine\n"); 21537372Sgblack@eecs.umich.edu txState = txIdle; 21547372Sgblack@eecs.umich.edu goto exit; 21557372Sgblack@eecs.umich.edu } else 21567372Sgblack@eecs.umich.edu txState = txAdvance; 21577372Sgblack@eecs.umich.edu break; 21587372Sgblack@eecs.umich.edu 21597372Sgblack@eecs.umich.edu case txAdvance: 21607372Sgblack@eecs.umich.edu if (link == 0) { 21617372Sgblack@eecs.umich.edu devIntrPost(ISR_TXIDLE); 21627372Sgblack@eecs.umich.edu txState = txIdle; 21637372Sgblack@eecs.umich.edu goto exit; 21647372Sgblack@eecs.umich.edu } else { 21657372Sgblack@eecs.umich.edu if (txDmaState != dmaIdle) 21667372Sgblack@eecs.umich.edu goto exit; 21677363Sgblack@eecs.umich.edu txState = txDescRead; 21687363Sgblack@eecs.umich.edu regs.txdp = link; 21697370Sgblack@eecs.umich.edu CTDD = false; 21707372Sgblack@eecs.umich.edu 21717376Sgblack@eecs.umich.edu txDmaAddr = link & 0x3fffffff; 21727376Sgblack@eecs.umich.edu txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 21737370Sgblack@eecs.umich.edu txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 21747376Sgblack@eecs.umich.edu txDmaFree = dmaDescFree; 21757376Sgblack@eecs.umich.edu 21767370Sgblack@eecs.umich.edu if (doTxDmaRead()) 21777370Sgblack@eecs.umich.edu goto exit; 21787372Sgblack@eecs.umich.edu } 21797376Sgblack@eecs.umich.edu break; 21807376Sgblack@eecs.umich.edu 21817370Sgblack@eecs.umich.edu default: 21827376Sgblack@eecs.umich.edu panic("invalid state"); 21837376Sgblack@eecs.umich.edu } 21847370Sgblack@eecs.umich.edu 21857370Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "entering next txState=%s\n", 21867371Sgblack@eecs.umich.edu NsTxStateStrings[txState]); 21877371Sgblack@eecs.umich.edu goto next; 21887372Sgblack@eecs.umich.edu 21897376Sgblack@eecs.umich.edu exit: 21907376Sgblack@eecs.umich.edu /** 21917371Sgblack@eecs.umich.edu * @todo do we want to schedule a future kick? 21927376Sgblack@eecs.umich.edu */ 21937376Sgblack@eecs.umich.edu DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 21947371Sgblack@eecs.umich.edu NsTxStateStrings[txState]); 21957371Sgblack@eecs.umich.edu 21967372Sgblack@eecs.umich.edu if (clock && !txKickEvent.scheduled()) 21977376Sgblack@eecs.umich.edu txKickEvent.schedule(txKickTick); 21987376Sgblack@eecs.umich.edu} 21997371Sgblack@eecs.umich.edu 22007376Sgblack@eecs.umich.edu/** 22017376Sgblack@eecs.umich.edu * Advance the EEPROM state machine 22027371Sgblack@eecs.umich.edu * Called on rising edge of EEPROM clock bit in MEAR 22037371Sgblack@eecs.umich.edu */ 22047363Sgblack@eecs.umich.eduvoid 22057363Sgblack@eecs.umich.eduNSGigE::eepromKick() 22067372Sgblack@eecs.umich.edu{ 22077376Sgblack@eecs.umich.edu switch (eepromState) { 22087376Sgblack@eecs.umich.edu 22097364Sgblack@eecs.umich.edu case eepromStart: 22107376Sgblack@eecs.umich.edu 22117376Sgblack@eecs.umich.edu // Wait for start bit 22127364Sgblack@eecs.umich.edu if (regs.mear & MEAR_EEDI) { 22137371Sgblack@eecs.umich.edu // Set up to get 2 opcode bits 22147372Sgblack@eecs.umich.edu eepromState = eepromGetOpcode; 22157376Sgblack@eecs.umich.edu eepromBitsToRx = 2; 22167376Sgblack@eecs.umich.edu eepromOpcode = 0; 22177371Sgblack@eecs.umich.edu } 22187376Sgblack@eecs.umich.edu break; 22197376Sgblack@eecs.umich.edu 22207371Sgblack@eecs.umich.edu case eepromGetOpcode: 22217363Sgblack@eecs.umich.edu eepromOpcode <<= 1; 22227363Sgblack@eecs.umich.edu eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 22237363Sgblack@eecs.umich.edu --eepromBitsToRx; 22247372Sgblack@eecs.umich.edu 22257376Sgblack@eecs.umich.edu // Done getting opcode 22267376Sgblack@eecs.umich.edu if (eepromBitsToRx == 0) { 22277367Sgblack@eecs.umich.edu if (eepromOpcode != EEPROM_READ) 22287376Sgblack@eecs.umich.edu panic("only EEPROM reads are implemented!"); 22297376Sgblack@eecs.umich.edu 22307367Sgblack@eecs.umich.edu // Set up to get address 22317363Sgblack@eecs.umich.edu eepromState = eepromGetAddress; 22327372Sgblack@eecs.umich.edu eepromBitsToRx = 6; 22337376Sgblack@eecs.umich.edu eepromAddress = 0; 22347376Sgblack@eecs.umich.edu } 22357368Sgblack@eecs.umich.edu break; 22367376Sgblack@eecs.umich.edu 22377376Sgblack@eecs.umich.edu case eepromGetAddress: 22387368Sgblack@eecs.umich.edu eepromAddress <<= 1; 22397363Sgblack@eecs.umich.edu eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 22407363Sgblack@eecs.umich.edu --eepromBitsToRx; 22417363Sgblack@eecs.umich.edu 22427372Sgblack@eecs.umich.edu // Done getting address 22437376Sgblack@eecs.umich.edu if (eepromBitsToRx == 0) { 22447376Sgblack@eecs.umich.edu 22457369Sgblack@eecs.umich.edu if (eepromAddress >= EEPROM_SIZE) 22467376Sgblack@eecs.umich.edu panic("EEPROM read access out of range!"); 22477376Sgblack@eecs.umich.edu 22487369Sgblack@eecs.umich.edu switch (eepromAddress) { 22497363Sgblack@eecs.umich.edu 22507363Sgblack@eecs.umich.edu case EEPROM_PMATCH2_ADDR: 22517363Sgblack@eecs.umich.edu eepromData = rom.perfectMatch[5]; 22527363Sgblack@eecs.umich.edu eepromData <<= 8; 22537363Sgblack@eecs.umich.edu eepromData += rom.perfectMatch[4]; 22547363Sgblack@eecs.umich.edu break; 22557372Sgblack@eecs.umich.edu 22567363Sgblack@eecs.umich.edu case EEPROM_PMATCH1_ADDR: 22577376Sgblack@eecs.umich.edu eepromData = rom.perfectMatch[3]; 22587376Sgblack@eecs.umich.edu eepromData <<= 8; 22597363Sgblack@eecs.umich.edu eepromData += rom.perfectMatch[2]; 22607363Sgblack@eecs.umich.edu break; 22617376Sgblack@eecs.umich.edu 22627376Sgblack@eecs.umich.edu case EEPROM_PMATCH0_ADDR: 22637363Sgblack@eecs.umich.edu eepromData = rom.perfectMatch[1]; 22647363Sgblack@eecs.umich.edu eepromData <<= 8; 22657363Sgblack@eecs.umich.edu eepromData += rom.perfectMatch[0]; 22667363Sgblack@eecs.umich.edu break; 22677363Sgblack@eecs.umich.edu 22687372Sgblack@eecs.umich.edu default: 22697376Sgblack@eecs.umich.edu panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 22707376Sgblack@eecs.umich.edu } 22717363Sgblack@eecs.umich.edu // Set up to read data 22727376Sgblack@eecs.umich.edu eepromState = eepromRead; 22737376Sgblack@eecs.umich.edu eepromBitsToRx = 16; 22747363Sgblack@eecs.umich.edu 22757363Sgblack@eecs.umich.edu // Clear data in bit 22767372Sgblack@eecs.umich.edu regs.mear &= ~MEAR_EEDI; 22777376Sgblack@eecs.umich.edu } 22787376Sgblack@eecs.umich.edu break; 22797366Sgblack@eecs.umich.edu 22807376Sgblack@eecs.umich.edu case eepromRead: 22817376Sgblack@eecs.umich.edu // Clear Data Out bit 22827366Sgblack@eecs.umich.edu regs.mear &= ~MEAR_EEDO; 22837363Sgblack@eecs.umich.edu // Set bit to value of current EEPROM bit 22847363Sgblack@eecs.umich.edu regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 22857363Sgblack@eecs.umich.edu 22867372Sgblack@eecs.umich.edu eepromData <<= 1; 22877376Sgblack@eecs.umich.edu --eepromBitsToRx; 22887376Sgblack@eecs.umich.edu 22897365Sgblack@eecs.umich.edu // All done 22907376Sgblack@eecs.umich.edu if (eepromBitsToRx == 0) { 22917376Sgblack@eecs.umich.edu eepromState = eepromStart; 22927365Sgblack@eecs.umich.edu } 22937363Sgblack@eecs.umich.edu break; 22947372Sgblack@eecs.umich.edu 22957376Sgblack@eecs.umich.edu default: 22967376Sgblack@eecs.umich.edu panic("invalid EEPROM state"); 22977369Sgblack@eecs.umich.edu } 22987376Sgblack@eecs.umich.edu 22997376Sgblack@eecs.umich.edu} 23007369Sgblack@eecs.umich.edu 23017363Sgblack@eecs.umich.eduvoid 23027363Sgblack@eecs.umich.eduNSGigE::transferDone() 23037363Sgblack@eecs.umich.edu{ 23047398Sgblack@eecs.umich.edu if (txFifo.empty()) { 23057398Sgblack@eecs.umich.edu DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 23067398Sgblack@eecs.umich.edu return; 23077398Sgblack@eecs.umich.edu } 23087398Sgblack@eecs.umich.edu 23097398Sgblack@eecs.umich.edu DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 23107398Sgblack@eecs.umich.edu 23117398Sgblack@eecs.umich.edu if (txEvent.scheduled()) 23127398Sgblack@eecs.umich.edu txEvent.reschedule(curTick + cycles(1)); 23137398Sgblack@eecs.umich.edu else 23147398Sgblack@eecs.umich.edu txEvent.schedule(curTick + cycles(1)); 23157398Sgblack@eecs.umich.edu} 23167398Sgblack@eecs.umich.edu 23177398Sgblack@eecs.umich.edubool 23187398Sgblack@eecs.umich.eduNSGigE::rxFilter(const EthPacketPtr &packet) 23197398Sgblack@eecs.umich.edu{ 23207398Sgblack@eecs.umich.edu EthPtr eth = packet; 23217363Sgblack@eecs.umich.edu bool drop = true; 23227377Sgblack@eecs.umich.edu string type; 23237389Sgblack@eecs.umich.edu 23247389Sgblack@eecs.umich.edu const EthAddr &dst = eth->dst(); 23257389Sgblack@eecs.umich.edu if (dst.unicast()) { 23267389Sgblack@eecs.umich.edu // If we're accepting all unicast addresses 23277389Sgblack@eecs.umich.edu if (acceptUnicast) 23287377Sgblack@eecs.umich.edu drop = false; 23297389Sgblack@eecs.umich.edu 23307389Sgblack@eecs.umich.edu // If we make a perfect match 23317389Sgblack@eecs.umich.edu if (acceptPerfect && dst == rom.perfectMatch) 23327389Sgblack@eecs.umich.edu drop = false; 23337389Sgblack@eecs.umich.edu 23347377Sgblack@eecs.umich.edu if (acceptArp && eth->type() == ETH_TYPE_ARP) 23357363Sgblack@eecs.umich.edu drop = false; 23367377Sgblack@eecs.umich.edu 23377389Sgblack@eecs.umich.edu } else if (dst.broadcast()) { 23387389Sgblack@eecs.umich.edu // if we're accepting broadcasts 23397389Sgblack@eecs.umich.edu if (acceptBroadcast) 23407389Sgblack@eecs.umich.edu drop = false; 23417389Sgblack@eecs.umich.edu 23427377Sgblack@eecs.umich.edu } else if (dst.multicast()) { 23437389Sgblack@eecs.umich.edu // if we're accepting all multicasts 23447389Sgblack@eecs.umich.edu if (acceptMulticast) 23457389Sgblack@eecs.umich.edu drop = false; 23467389Sgblack@eecs.umich.edu 23477389Sgblack@eecs.umich.edu // Multicast hashing faked - all packets accepted 23487377Sgblack@eecs.umich.edu if (multicastHashEnable) 23497363Sgblack@eecs.umich.edu drop = false; 23507363Sgblack@eecs.umich.edu } 23517374Sgblack@eecs.umich.edu 23528270SAli.Saidi@ARM.com if (drop) { 23538270SAli.Saidi@ARM.com DPRINTF(Ethernet, "rxFilter drop\n"); 23547374Sgblack@eecs.umich.edu DDUMP(EthernetData, packet->data, packet->length); 23557374Sgblack@eecs.umich.edu } 23567374Sgblack@eecs.umich.edu 23577374Sgblack@eecs.umich.edu return drop; 23587374Sgblack@eecs.umich.edu} 23597374Sgblack@eecs.umich.edu 23607363Sgblack@eecs.umich.edubool 23617363Sgblack@eecs.umich.eduNSGigE::recvPacket(EthPacketPtr packet) 23627363Sgblack@eecs.umich.edu{ 23637373Sgblack@eecs.umich.edu rxBytes += packet->length; 23647373Sgblack@eecs.umich.edu rxPackets++; 23657373Sgblack@eecs.umich.edu 23667373Sgblack@eecs.umich.edu DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 23677373Sgblack@eecs.umich.edu rxFifo.avail()); 23687373Sgblack@eecs.umich.edu 23697373Sgblack@eecs.umich.edu if (!rxEnable) { 23707373Sgblack@eecs.umich.edu DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 23717373Sgblack@eecs.umich.edu return true; 23727373Sgblack@eecs.umich.edu } 23737373Sgblack@eecs.umich.edu 23747373Sgblack@eecs.umich.edu if (!rxFilterEnable) { 23757373Sgblack@eecs.umich.edu DPRINTF(Ethernet, 23767373Sgblack@eecs.umich.edu "receive packet filtering disabled . . . packet dropped\n"); 23777373Sgblack@eecs.umich.edu return true; 23787373Sgblack@eecs.umich.edu } 23797373Sgblack@eecs.umich.edu 23807363Sgblack@eecs.umich.edu if (rxFilter(packet)) { 23817379Sgblack@eecs.umich.edu DPRINTF(Ethernet, "packet filtered...dropped\n"); 23827379Sgblack@eecs.umich.edu return true; 23837379Sgblack@eecs.umich.edu } 23847379Sgblack@eecs.umich.edu 23857379Sgblack@eecs.umich.edu if (rxFifo.avail() < packet->length) { 23867379Sgblack@eecs.umich.edu#if TRACING_ON 23877379Sgblack@eecs.umich.edu IpPtr ip(packet); 23887379Sgblack@eecs.umich.edu TcpPtr tcp(ip); 23897379Sgblack@eecs.umich.edu if (ip) { 23907379Sgblack@eecs.umich.edu DPRINTF(Ethernet, 23917379Sgblack@eecs.umich.edu "packet won't fit in receive buffer...pkt ID %d dropped\n", 23927379Sgblack@eecs.umich.edu ip->id()); 23937379Sgblack@eecs.umich.edu if (tcp) { 23947379Sgblack@eecs.umich.edu DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 23957379Sgblack@eecs.umich.edu } 23967379Sgblack@eecs.umich.edu } 23977379Sgblack@eecs.umich.edu#endif 23987379Sgblack@eecs.umich.edu droppedPackets++; 23997379Sgblack@eecs.umich.edu devIntrPost(ISR_RXORN); 24007379Sgblack@eecs.umich.edu return false; 24017363Sgblack@eecs.umich.edu } 24027379Sgblack@eecs.umich.edu 24037379Sgblack@eecs.umich.edu rxFifo.push(packet); 24047379Sgblack@eecs.umich.edu 24057379Sgblack@eecs.umich.edu rxKick(); 24067379Sgblack@eecs.umich.edu return true; 24077379Sgblack@eecs.umich.edu} 24087379Sgblack@eecs.umich.edu 24097379Sgblack@eecs.umich.edu//===================================================================== 24107379Sgblack@eecs.umich.edu// 24117379Sgblack@eecs.umich.edu// 24127379Sgblack@eecs.umich.eduvoid 24137379Sgblack@eecs.umich.eduNSGigE::serialize(ostream &os) 24147379Sgblack@eecs.umich.edu{ 24157379Sgblack@eecs.umich.edu // Serialize the PciDev base class 24167379Sgblack@eecs.umich.edu PciDev::serialize(os); 24177379Sgblack@eecs.umich.edu 24187379Sgblack@eecs.umich.edu /* 24197379Sgblack@eecs.umich.edu * Finalize any DMA events now. 24207379Sgblack@eecs.umich.edu */ 24217379Sgblack@eecs.umich.edu // @todo will mem system save pending dma? 24227363Sgblack@eecs.umich.edu 24237380Sgblack@eecs.umich.edu /* 24247380Sgblack@eecs.umich.edu * Serialize the device registers 24257380Sgblack@eecs.umich.edu */ 24267380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.command); 24277380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.config); 24287380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.mear); 24297380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.ptscr); 24307380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.isr); 24317373Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.imr); 24327380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.ier); 24337380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.ihr); 24347380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.txdp); 24357380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.txdp_hi); 24367380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.txcfg); 24377380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.gpior); 24387380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.rxdp); 24397373Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.rxdp_hi); 24407363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.rxcfg); 24417380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.pqcr); 24427380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.wcsr); 24437380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.pcr); 24447380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.rfcr); 24457380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.rfdr); 24467380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.brar); 24477380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.brdr); 24487380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.srr); 24497373Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.mibc); 24507380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.vrcr); 24517380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.vtcr); 24527380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.vdr); 24537380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.ccsr); 24547380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.tbicr); 24557380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.tbisr); 24567380Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.tanar); 24577373Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.tanlpar); 24587363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.taner); 24597379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(regs.tesr); 24607379Sgblack@eecs.umich.edu 24617379Sgblack@eecs.umich.edu SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 24627379Sgblack@eecs.umich.edu SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 24637379Sgblack@eecs.umich.edu 24647379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(ioEnable); 24657379Sgblack@eecs.umich.edu 24667379Sgblack@eecs.umich.edu /* 24677379Sgblack@eecs.umich.edu * Serialize the data Fifos 24687379Sgblack@eecs.umich.edu */ 24697379Sgblack@eecs.umich.edu rxFifo.serialize("rxFifo", os); 24707379Sgblack@eecs.umich.edu txFifo.serialize("txFifo", os); 24717379Sgblack@eecs.umich.edu 24727379Sgblack@eecs.umich.edu /* 24737379Sgblack@eecs.umich.edu * Serialize the various helper variables 24747379Sgblack@eecs.umich.edu */ 24757379Sgblack@eecs.umich.edu bool txPacketExists = txPacket; 24767379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txPacketExists); 24777379Sgblack@eecs.umich.edu if (txPacketExists) { 24787379Sgblack@eecs.umich.edu txPacket->length = txPacketBufPtr - txPacket->data; 24797363Sgblack@eecs.umich.edu txPacket->serialize("txPacket", os); 24807379Sgblack@eecs.umich.edu uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 24817379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txPktBufPtr); 24827379Sgblack@eecs.umich.edu } 24837379Sgblack@eecs.umich.edu 24847379Sgblack@eecs.umich.edu bool rxPacketExists = rxPacket; 24857379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxPacketExists); 24867379Sgblack@eecs.umich.edu if (rxPacketExists) { 24877379Sgblack@eecs.umich.edu rxPacket->serialize("rxPacket", os); 24887379Sgblack@eecs.umich.edu uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 24897379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxPktBufPtr); 24907379Sgblack@eecs.umich.edu } 24917379Sgblack@eecs.umich.edu 24927379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txXferLen); 24937379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxXferLen); 24947379Sgblack@eecs.umich.edu 24957379Sgblack@eecs.umich.edu /* 24967379Sgblack@eecs.umich.edu * Serialize Cached Descriptors 24977379Sgblack@eecs.umich.edu */ 24987379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc64.link); 24997379Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc64.bufptr); 25007363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc64.cmdsts); 25017363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc64.extsts); 25027363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc64.link); 25037363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc64.bufptr); 25047363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc64.cmdsts); 25057363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc64.extsts); 25067363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc32.link); 25077363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc32.bufptr); 25087363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc32.cmdsts); 25097363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(rxDesc32.extsts); 25107363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc32.link); 25117363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc32.bufptr); 25127363Sgblack@eecs.umich.edu SERIALIZE_SCALAR(txDesc32.cmdsts); 2513 SERIALIZE_SCALAR(txDesc32.extsts); 2514 SERIALIZE_SCALAR(extstsEnable); 2515 2516 /* 2517 * Serialize tx state machine 2518 */ 2519 int txState = this->txState; 2520 SERIALIZE_SCALAR(txState); 2521 SERIALIZE_SCALAR(txEnable); 2522 SERIALIZE_SCALAR(CTDD); 2523 SERIALIZE_SCALAR(txFragPtr); 2524 SERIALIZE_SCALAR(txDescCnt); 2525 int txDmaState = this->txDmaState; 2526 SERIALIZE_SCALAR(txDmaState); 2527 SERIALIZE_SCALAR(txKickTick); 2528 2529 /* 2530 * Serialize rx state machine 2531 */ 2532 int rxState = this->rxState; 2533 SERIALIZE_SCALAR(rxState); 2534 SERIALIZE_SCALAR(rxEnable); 2535 SERIALIZE_SCALAR(CRDD); 2536 SERIALIZE_SCALAR(rxPktBytes); 2537 SERIALIZE_SCALAR(rxFragPtr); 2538 SERIALIZE_SCALAR(rxDescCnt); 2539 int rxDmaState = this->rxDmaState; 2540 SERIALIZE_SCALAR(rxDmaState); 2541 SERIALIZE_SCALAR(rxKickTick); 2542 2543 /* 2544 * Serialize EEPROM state machine 2545 */ 2546 int eepromState = this->eepromState; 2547 SERIALIZE_SCALAR(eepromState); 2548 SERIALIZE_SCALAR(eepromClk); 2549 SERIALIZE_SCALAR(eepromBitsToRx); 2550 SERIALIZE_SCALAR(eepromOpcode); 2551 SERIALIZE_SCALAR(eepromAddress); 2552 SERIALIZE_SCALAR(eepromData); 2553 2554 /* 2555 * If there's a pending transmit, store the time so we can 2556 * reschedule it later 2557 */ 2558 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2559 SERIALIZE_SCALAR(transmitTick); 2560 2561 /* 2562 * receive address filter settings 2563 */ 2564 SERIALIZE_SCALAR(rxFilterEnable); 2565 SERIALIZE_SCALAR(acceptBroadcast); 2566 SERIALIZE_SCALAR(acceptMulticast); 2567 SERIALIZE_SCALAR(acceptUnicast); 2568 SERIALIZE_SCALAR(acceptPerfect); 2569 SERIALIZE_SCALAR(acceptArp); 2570 SERIALIZE_SCALAR(multicastHashEnable); 2571 2572 /* 2573 * Keep track of pending interrupt status. 2574 */ 2575 SERIALIZE_SCALAR(intrTick); 2576 SERIALIZE_SCALAR(cpuPendingIntr); 2577 Tick intrEventTick = 0; 2578 if (intrEvent) 2579 intrEventTick = intrEvent->when(); 2580 SERIALIZE_SCALAR(intrEventTick); 2581 2582} 2583 2584void 2585NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2586{ 2587 // Unserialize the PciDev base class 2588 PciDev::unserialize(cp, section); 2589 2590 UNSERIALIZE_SCALAR(regs.command); 2591 UNSERIALIZE_SCALAR(regs.config); 2592 UNSERIALIZE_SCALAR(regs.mear); 2593 UNSERIALIZE_SCALAR(regs.ptscr); 2594 UNSERIALIZE_SCALAR(regs.isr); 2595 UNSERIALIZE_SCALAR(regs.imr); 2596 UNSERIALIZE_SCALAR(regs.ier); 2597 UNSERIALIZE_SCALAR(regs.ihr); 2598 UNSERIALIZE_SCALAR(regs.txdp); 2599 UNSERIALIZE_SCALAR(regs.txdp_hi); 2600 UNSERIALIZE_SCALAR(regs.txcfg); 2601 UNSERIALIZE_SCALAR(regs.gpior); 2602 UNSERIALIZE_SCALAR(regs.rxdp); 2603 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2604 UNSERIALIZE_SCALAR(regs.rxcfg); 2605 UNSERIALIZE_SCALAR(regs.pqcr); 2606 UNSERIALIZE_SCALAR(regs.wcsr); 2607 UNSERIALIZE_SCALAR(regs.pcr); 2608 UNSERIALIZE_SCALAR(regs.rfcr); 2609 UNSERIALIZE_SCALAR(regs.rfdr); 2610 UNSERIALIZE_SCALAR(regs.brar); 2611 UNSERIALIZE_SCALAR(regs.brdr); 2612 UNSERIALIZE_SCALAR(regs.srr); 2613 UNSERIALIZE_SCALAR(regs.mibc); 2614 UNSERIALIZE_SCALAR(regs.vrcr); 2615 UNSERIALIZE_SCALAR(regs.vtcr); 2616 UNSERIALIZE_SCALAR(regs.vdr); 2617 UNSERIALIZE_SCALAR(regs.ccsr); 2618 UNSERIALIZE_SCALAR(regs.tbicr); 2619 UNSERIALIZE_SCALAR(regs.tbisr); 2620 UNSERIALIZE_SCALAR(regs.tanar); 2621 UNSERIALIZE_SCALAR(regs.tanlpar); 2622 UNSERIALIZE_SCALAR(regs.taner); 2623 UNSERIALIZE_SCALAR(regs.tesr); 2624 2625 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2626 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2627 2628 UNSERIALIZE_SCALAR(ioEnable); 2629 2630 /* 2631 * unserialize the data fifos 2632 */ 2633 rxFifo.unserialize("rxFifo", cp, section); 2634 txFifo.unserialize("txFifo", cp, section); 2635 2636 /* 2637 * unserialize the various helper variables 2638 */ 2639 bool txPacketExists; 2640 UNSERIALIZE_SCALAR(txPacketExists); 2641 if (txPacketExists) { 2642 txPacket = new EthPacketData(16384); 2643 txPacket->unserialize("txPacket", cp, section); 2644 uint32_t txPktBufPtr; 2645 UNSERIALIZE_SCALAR(txPktBufPtr); 2646 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2647 } else 2648 txPacket = 0; 2649 2650 bool rxPacketExists; 2651 UNSERIALIZE_SCALAR(rxPacketExists); 2652 rxPacket = 0; 2653 if (rxPacketExists) { 2654 rxPacket = new EthPacketData(16384); 2655 rxPacket->unserialize("rxPacket", cp, section); 2656 uint32_t rxPktBufPtr; 2657 UNSERIALIZE_SCALAR(rxPktBufPtr); 2658 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2659 } else 2660 rxPacket = 0; 2661 2662 UNSERIALIZE_SCALAR(txXferLen); 2663 UNSERIALIZE_SCALAR(rxXferLen); 2664 2665 /* 2666 * Unserialize Cached Descriptors 2667 */ 2668 UNSERIALIZE_SCALAR(rxDesc64.link); 2669 UNSERIALIZE_SCALAR(rxDesc64.bufptr); 2670 UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 2671 UNSERIALIZE_SCALAR(rxDesc64.extsts); 2672 UNSERIALIZE_SCALAR(txDesc64.link); 2673 UNSERIALIZE_SCALAR(txDesc64.bufptr); 2674 UNSERIALIZE_SCALAR(txDesc64.cmdsts); 2675 UNSERIALIZE_SCALAR(txDesc64.extsts); 2676 UNSERIALIZE_SCALAR(rxDesc32.link); 2677 UNSERIALIZE_SCALAR(rxDesc32.bufptr); 2678 UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 2679 UNSERIALIZE_SCALAR(rxDesc32.extsts); 2680 UNSERIALIZE_SCALAR(txDesc32.link); 2681 UNSERIALIZE_SCALAR(txDesc32.bufptr); 2682 UNSERIALIZE_SCALAR(txDesc32.cmdsts); 2683 UNSERIALIZE_SCALAR(txDesc32.extsts); 2684 UNSERIALIZE_SCALAR(extstsEnable); 2685 2686 /* 2687 * unserialize tx state machine 2688 */ 2689 int txState; 2690 UNSERIALIZE_SCALAR(txState); 2691 this->txState = (TxState) txState; 2692 UNSERIALIZE_SCALAR(txEnable); 2693 UNSERIALIZE_SCALAR(CTDD); 2694 UNSERIALIZE_SCALAR(txFragPtr); 2695 UNSERIALIZE_SCALAR(txDescCnt); 2696 int txDmaState; 2697 UNSERIALIZE_SCALAR(txDmaState); 2698 this->txDmaState = (DmaState) txDmaState; 2699 UNSERIALIZE_SCALAR(txKickTick); 2700 if (txKickTick) 2701 txKickEvent.schedule(txKickTick); 2702 2703 /* 2704 * unserialize rx state machine 2705 */ 2706 int rxState; 2707 UNSERIALIZE_SCALAR(rxState); 2708 this->rxState = (RxState) rxState; 2709 UNSERIALIZE_SCALAR(rxEnable); 2710 UNSERIALIZE_SCALAR(CRDD); 2711 UNSERIALIZE_SCALAR(rxPktBytes); 2712 UNSERIALIZE_SCALAR(rxFragPtr); 2713 UNSERIALIZE_SCALAR(rxDescCnt); 2714 int rxDmaState; 2715 UNSERIALIZE_SCALAR(rxDmaState); 2716 this->rxDmaState = (DmaState) rxDmaState; 2717 UNSERIALIZE_SCALAR(rxKickTick); 2718 if (rxKickTick) 2719 rxKickEvent.schedule(rxKickTick); 2720 2721 /* 2722 * Unserialize EEPROM state machine 2723 */ 2724 int eepromState; 2725 UNSERIALIZE_SCALAR(eepromState); 2726 this->eepromState = (EEPROMState) eepromState; 2727 UNSERIALIZE_SCALAR(eepromClk); 2728 UNSERIALIZE_SCALAR(eepromBitsToRx); 2729 UNSERIALIZE_SCALAR(eepromOpcode); 2730 UNSERIALIZE_SCALAR(eepromAddress); 2731 UNSERIALIZE_SCALAR(eepromData); 2732 2733 /* 2734 * If there's a pending transmit, reschedule it now 2735 */ 2736 Tick transmitTick; 2737 UNSERIALIZE_SCALAR(transmitTick); 2738 if (transmitTick) 2739 txEvent.schedule(curTick + transmitTick); 2740 2741 /* 2742 * unserialize receive address filter settings 2743 */ 2744 UNSERIALIZE_SCALAR(rxFilterEnable); 2745 UNSERIALIZE_SCALAR(acceptBroadcast); 2746 UNSERIALIZE_SCALAR(acceptMulticast); 2747 UNSERIALIZE_SCALAR(acceptUnicast); 2748 UNSERIALIZE_SCALAR(acceptPerfect); 2749 UNSERIALIZE_SCALAR(acceptArp); 2750 UNSERIALIZE_SCALAR(multicastHashEnable); 2751 2752 /* 2753 * Keep track of pending interrupt status. 2754 */ 2755 UNSERIALIZE_SCALAR(intrTick); 2756 UNSERIALIZE_SCALAR(cpuPendingIntr); 2757 Tick intrEventTick; 2758 UNSERIALIZE_SCALAR(intrEventTick); 2759 if (intrEventTick) { 2760 intrEvent = new IntrEvent(this, true); 2761 intrEvent->schedule(intrEventTick); 2762 } 2763} 2764 2765BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2766 2767 SimObjectParam<EtherInt *> peer; 2768 SimObjectParam<NSGigE *> device; 2769 2770END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2771 2772BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2773 2774 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2775 INIT_PARAM(device, "Ethernet device of this interface") 2776 2777END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2778 2779CREATE_SIM_OBJECT(NSGigEInt) 2780{ 2781 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2782 2783 EtherInt *p = (EtherInt *)peer; 2784 if (p) { 2785 dev_int->setPeer(p); 2786 p->setPeer(dev_int); 2787 } 2788 2789 return dev_int; 2790} 2791 2792REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2793 2794 2795BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2796 2797 SimObjectParam<System *> system; 2798 SimObjectParam<Platform *> platform; 2799 SimObjectParam<PciConfigData *> configdata; 2800 Param<uint32_t> pci_bus; 2801 Param<uint32_t> pci_dev; 2802 Param<uint32_t> pci_func; 2803 Param<Tick> pio_latency; 2804 2805 Param<Tick> clock; 2806 Param<bool> dma_desc_free; 2807 Param<bool> dma_data_free; 2808 Param<Tick> dma_read_delay; 2809 Param<Tick> dma_write_delay; 2810 Param<Tick> dma_read_factor; 2811 Param<Tick> dma_write_factor; 2812 Param<bool> dma_no_allocate; 2813 Param<Tick> intr_delay; 2814 2815 Param<Tick> rx_delay; 2816 Param<Tick> tx_delay; 2817 Param<uint32_t> rx_fifo_size; 2818 Param<uint32_t> tx_fifo_size; 2819 2820 Param<bool> rx_filter; 2821 Param<string> hardware_address; 2822 Param<bool> rx_thread; 2823 Param<bool> tx_thread; 2824 Param<bool> rss; 2825 2826END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2827 2828BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2829 2830 INIT_PARAM(system, "System pointer"), 2831 INIT_PARAM(platform, "Platform pointer"), 2832 INIT_PARAM(configdata, "PCI Config data"), 2833 INIT_PARAM(pci_bus, "PCI bus ID"), 2834 INIT_PARAM(pci_dev, "PCI device number"), 2835 INIT_PARAM(pci_func, "PCI function code"), 2836 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2837 INIT_PARAM(clock, "State machine cycle time"), 2838 2839 INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), 2840 INIT_PARAM(dma_data_free, "DMA of Data is free"), 2841 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 2842 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 2843 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 2844 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 2845 INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), 2846 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2847 2848 INIT_PARAM(rx_delay, "Receive Delay"), 2849 INIT_PARAM(tx_delay, "Transmit Delay"), 2850 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 2851 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 2852 2853 INIT_PARAM(rx_filter, "Enable Receive Filter"), 2854 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 2855 INIT_PARAM(rx_thread, ""), 2856 INIT_PARAM(tx_thread, ""), 2857 INIT_PARAM(rss, "") 2858 2859END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2860 2861 2862CREATE_SIM_OBJECT(NSGigE) 2863{ 2864 NSGigE::Params *params = new NSGigE::Params; 2865 2866 params->name = getInstanceName(); 2867 params->platform = platform; 2868 params->system = system; 2869 params->configData = configdata; 2870 params->busNum = pci_bus; 2871 params->deviceNum = pci_dev; 2872 params->functionNum = pci_func; 2873 params->pio_delay = pio_latency; 2874 2875 params->clock = clock; 2876 params->dma_desc_free = dma_desc_free; 2877 params->dma_data_free = dma_data_free; 2878 params->dma_read_delay = dma_read_delay; 2879 params->dma_write_delay = dma_write_delay; 2880 params->dma_read_factor = dma_read_factor; 2881 params->dma_write_factor = dma_write_factor; 2882 params->dma_no_allocate = dma_no_allocate; 2883 params->pio_delay = pio_latency; 2884 params->intr_delay = intr_delay; 2885 2886 params->rx_delay = rx_delay; 2887 params->tx_delay = tx_delay; 2888 params->rx_fifo_size = rx_fifo_size; 2889 params->tx_fifo_size = tx_fifo_size; 2890 2891 params->rx_filter = rx_filter; 2892 params->eaddr = hardware_address; 2893 params->rx_thread = rx_thread; 2894 params->tx_thread = tx_thread; 2895 params->rss = rss; 2896 2897 return new NSGigE(params); 2898} 2899 2900REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2901