ns_gige.cc revision 2641
16657Snate@binkert.org/* 26657Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan 36657Snate@binkert.org * All rights reserved. 46657Snate@binkert.org * 56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org * modification, are permitted provided that the following conditions are 76657Snate@binkert.org * met: redistributions of source code must retain the above copyright 86657Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org * documentation and/or other materials provided with the distribution; 126657Snate@binkert.org * neither the name of the copyright holders nor the names of its 136657Snate@binkert.org * contributors may be used to endorse or promote products derived from 146657Snate@binkert.org * this software without specific prior written permission. 156657Snate@binkert.org * 166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org */ 286999Snate@binkert.org 296657Snate@binkert.org/** @file 306657Snate@binkert.org * Device module for modelling the National Semiconductor 316657Snate@binkert.org * DP83820 ethernet controller. Does not support priority queueing 326657Snate@binkert.org */ 338189SLisa.Hsu@amd.com#include <deque> 346657Snate@binkert.org#include <string> 356882SBrad.Beckmann@amd.com 367055Snate@binkert.org#include "arch/alpha/ev5.hh" 376882SBrad.Beckmann@amd.com#include "base/inet.hh" 386882SBrad.Beckmann@amd.com#include "cpu/exec_context.hh" 398191SLisa.Hsu@amd.com#include "dev/etherlink.hh" 406882SBrad.Beckmann@amd.com#include "dev/ns_gige.hh" 416882SBrad.Beckmann@amd.com#include "dev/pciconfigall.hh" 429102SNuwan.Jayasena@amd.com#include "mem/packet.hh" 436888SBrad.Beckmann@amd.com#include "sim/builder.hh" 446882SBrad.Beckmann@amd.com#include "sim/debug.hh" 456882SBrad.Beckmann@amd.com#include "sim/host.hh" 466657Snate@binkert.org#include "sim/stats.hh" 476657Snate@binkert.org#include "sim/system.hh" 486657Snate@binkert.org 496657Snate@binkert.orgconst char *NsRxStateStrings[] = 506657Snate@binkert.org{ 517839Snilay@cs.wisc.edu "rxIdle", 526657Snate@binkert.org "rxDescRefr", 536882SBrad.Beckmann@amd.com "rxDescRead", 546882SBrad.Beckmann@amd.com "rxFifoBlock", 556882SBrad.Beckmann@amd.com "rxFragWrite", 566882SBrad.Beckmann@amd.com "rxDescWrite", 576882SBrad.Beckmann@amd.com "rxAdvance" 586882SBrad.Beckmann@amd.com}; 596657Snate@binkert.org 606657Snate@binkert.orgconst char *NsTxStateStrings[] = 616657Snate@binkert.org{ 626657Snate@binkert.org "txIdle", 636657Snate@binkert.org "txDescRefr", 649104Shestness@cs.utexas.edu "txDescRead", 656657Snate@binkert.org "txFifoBlock", 666657Snate@binkert.org "txFragRead", 676657Snate@binkert.org "txDescWrite", 686657Snate@binkert.org "txAdvance" 697839Snilay@cs.wisc.edu}; 707839Snilay@cs.wisc.edu 716657Snate@binkert.orgconst char *NsDmaState[] = 726657Snate@binkert.org{ 736657Snate@binkert.org "dmaIdle", 746657Snate@binkert.org "dmaReading", 756657Snate@binkert.org "dmaWriting", 766657Snate@binkert.org "dmaReadWaiting", 776657Snate@binkert.org "dmaWriteWaiting" 786657Snate@binkert.org}; 796657Snate@binkert.org 806657Snate@binkert.orgusing namespace std; 816657Snate@binkert.orgusing namespace Net; 826657Snate@binkert.orgusing namespace TheISA; 836657Snate@binkert.org 846657Snate@binkert.org/////////////////////////////////////////////////////////////////////// 856657Snate@binkert.org// 866657Snate@binkert.org// NSGigE PCI Device 876657Snate@binkert.org// 886657Snate@binkert.orgNSGigE::NSGigE(Params *p) 896657Snate@binkert.org : PciDev(p), ioEnable(false), 906657Snate@binkert.org txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 916779SBrad.Beckmann@amd.com txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 926657Snate@binkert.org txXferLen(0), rxXferLen(0), clock(p->clock), 936657Snate@binkert.org txState(txIdle), txEnable(false), CTDD(false), 946657Snate@binkert.org txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 956657Snate@binkert.org rxEnable(false), CRDD(false), rxPktBytes(0), 966657Snate@binkert.org rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 976657Snate@binkert.org eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), 986657Snate@binkert.org txDmaReadEvent(this), txDmaWriteEvent(this), 996657Snate@binkert.org dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1006657Snate@binkert.org txDelay(p->tx_delay), rxDelay(p->rx_delay), 1019104Shestness@cs.utexas.edu rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1029104Shestness@cs.utexas.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1039104Shestness@cs.utexas.edu acceptMulticast(false), acceptUnicast(false), 1049104Shestness@cs.utexas.edu acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1056657Snate@binkert.org intrTick(0), cpuPendingIntr(false), 1066657Snate@binkert.org intrEvent(0), interface(0) 1076657Snate@binkert.org{ 1086657Snate@binkert.org 1096657Snate@binkert.org intrDelay = p->intr_delay; 1106657Snate@binkert.org dmaReadDelay = p->dma_read_delay; 1116657Snate@binkert.org dmaWriteDelay = p->dma_write_delay; 1126657Snate@binkert.org dmaReadFactor = p->dma_read_factor; 1136657Snate@binkert.org dmaWriteFactor = p->dma_write_factor; 1146657Snate@binkert.org 1156657Snate@binkert.org regsReset(); 1166657Snate@binkert.org memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1176657Snate@binkert.org 1186657Snate@binkert.org memset(&rxDesc32, 0, sizeof(rxDesc32)); 1196657Snate@binkert.org memset(&txDesc32, 0, sizeof(txDesc32)); 1207839Snilay@cs.wisc.edu memset(&rxDesc64, 0, sizeof(rxDesc64)); 1217839Snilay@cs.wisc.edu memset(&txDesc64, 0, sizeof(txDesc64)); 1227839Snilay@cs.wisc.edu} 1237839Snilay@cs.wisc.edu 1247839Snilay@cs.wisc.eduNSGigE::~NSGigE() 1257839Snilay@cs.wisc.edu{} 1267839Snilay@cs.wisc.edu 1277839Snilay@cs.wisc.eduvoid 1287839Snilay@cs.wisc.eduNSGigE::regStats() 1297839Snilay@cs.wisc.edu{ 1307839Snilay@cs.wisc.edu txBytes 1317839Snilay@cs.wisc.edu .name(name() + ".txBytes") 1327839Snilay@cs.wisc.edu .desc("Bytes Transmitted") 1337839Snilay@cs.wisc.edu .prereq(txBytes) 1347839Snilay@cs.wisc.edu ; 1356657Snate@binkert.org 1366657Snate@binkert.org rxBytes 1376657Snate@binkert.org .name(name() + ".rxBytes") 1386657Snate@binkert.org .desc("Bytes Received") 1396657Snate@binkert.org .prereq(rxBytes) 1406657Snate@binkert.org ; 1416657Snate@binkert.org 1426657Snate@binkert.org txPackets 1436657Snate@binkert.org .name(name() + ".txPackets") 1446657Snate@binkert.org .desc("Number of Packets Transmitted") 1456657Snate@binkert.org .prereq(txBytes) 1466657Snate@binkert.org ; 1476657Snate@binkert.org 1486657Snate@binkert.org rxPackets 1496657Snate@binkert.org .name(name() + ".rxPackets") 1506657Snate@binkert.org .desc("Number of Packets Received") 1516657Snate@binkert.org .prereq(rxBytes) 1526657Snate@binkert.org ; 1536657Snate@binkert.org 1546657Snate@binkert.org txIpChecksums 1556657Snate@binkert.org .name(name() + ".txIpChecksums") 1566657Snate@binkert.org .desc("Number of tx IP Checksums done by device") 1576657Snate@binkert.org .precision(0) 1586657Snate@binkert.org .prereq(txBytes) 1596657Snate@binkert.org ; 1606657Snate@binkert.org 1616657Snate@binkert.org rxIpChecksums 1626657Snate@binkert.org .name(name() + ".rxIpChecksums") 1636657Snate@binkert.org .desc("Number of rx IP Checksums done by device") 1646657Snate@binkert.org .precision(0) 1656657Snate@binkert.org .prereq(rxBytes) 1666877Ssteve.reinhardt@amd.com ; 1676657Snate@binkert.org 1686657Snate@binkert.org txTcpChecksums 1696657Snate@binkert.org .name(name() + ".txTcpChecksums") 1706657Snate@binkert.org .desc("Number of tx TCP Checksums done by device") 1716657Snate@binkert.org .precision(0) 1726657Snate@binkert.org .prereq(txBytes) 1737542SBrad.Beckmann@amd.com ; 1747542SBrad.Beckmann@amd.com 1756657Snate@binkert.org rxTcpChecksums 1766877Ssteve.reinhardt@amd.com .name(name() + ".rxTcpChecksums") 1776999Snate@binkert.org .desc("Number of rx TCP Checksums done by device") 1786877Ssteve.reinhardt@amd.com .precision(0) 1796877Ssteve.reinhardt@amd.com .prereq(rxBytes) 1806877Ssteve.reinhardt@amd.com ; 1816877Ssteve.reinhardt@amd.com 1826877Ssteve.reinhardt@amd.com txUdpChecksums 1836877Ssteve.reinhardt@amd.com .name(name() + ".txUdpChecksums") 1846877Ssteve.reinhardt@amd.com .desc("Number of tx UDP Checksums done by device") 1856877Ssteve.reinhardt@amd.com .precision(0) 1866877Ssteve.reinhardt@amd.com .prereq(txBytes) 1876877Ssteve.reinhardt@amd.com ; 1886877Ssteve.reinhardt@amd.com 1896877Ssteve.reinhardt@amd.com rxUdpChecksums 1906877Ssteve.reinhardt@amd.com .name(name() + ".rxUdpChecksums") 1916877Ssteve.reinhardt@amd.com .desc("Number of rx UDP Checksums done by device") 1926877Ssteve.reinhardt@amd.com .precision(0) 1936877Ssteve.reinhardt@amd.com .prereq(rxBytes) 1946882SBrad.Beckmann@amd.com ; 1956882SBrad.Beckmann@amd.com 1966882SBrad.Beckmann@amd.com descDmaReads 1976882SBrad.Beckmann@amd.com .name(name() + ".descDMAReads") 1986882SBrad.Beckmann@amd.com .desc("Number of descriptors the device read w/ DMA") 1996882SBrad.Beckmann@amd.com .precision(0) 2006882SBrad.Beckmann@amd.com ; 2016877Ssteve.reinhardt@amd.com 2026877Ssteve.reinhardt@amd.com descDmaWrites 2036877Ssteve.reinhardt@amd.com .name(name() + ".descDMAWrites") 2046877Ssteve.reinhardt@amd.com .desc("Number of descriptors the device wrote w/ DMA") 2056657Snate@binkert.org .precision(0) 2066657Snate@binkert.org ; 2076999Snate@binkert.org 2086657Snate@binkert.org descDmaRdBytes 2096657Snate@binkert.org .name(name() + ".descDmaReadBytes") 2106657Snate@binkert.org .desc("number of descriptor bytes read w/ DMA") 2116657Snate@binkert.org .precision(0) 2126657Snate@binkert.org ; 2136657Snate@binkert.org 2147007Snate@binkert.org descDmaWrBytes 2156657Snate@binkert.org .name(name() + ".descDmaWriteBytes") 2166657Snate@binkert.org .desc("number of descriptor bytes write w/ DMA") 2176657Snate@binkert.org .precision(0) 2186657Snate@binkert.org ; 2196657Snate@binkert.org 2207007Snate@binkert.org txBandwidth 2217007Snate@binkert.org .name(name() + ".txBandwidth") 2226657Snate@binkert.org .desc("Transmit Bandwidth (bits/s)") 2237002Snate@binkert.org .precision(0) 2247002Snate@binkert.org .prereq(txBytes) 2257002Snate@binkert.org ; 2267002Snate@binkert.org 2278229Snate@binkert.org rxBandwidth 2288229Snate@binkert.org .name(name() + ".rxBandwidth") 2296657Snate@binkert.org .desc("Receive Bandwidth (bits/s)") 2306657Snate@binkert.org .precision(0) 2318229Snate@binkert.org .prereq(rxBytes) 2328229Snate@binkert.org ; 2338229Snate@binkert.org 2348229Snate@binkert.org totBandwidth 2356657Snate@binkert.org .name(name() + ".totBandwidth") 2366657Snate@binkert.org .desc("Total Bandwidth (bits/s)") 2376657Snate@binkert.org .precision(0) 2386657Snate@binkert.org .prereq(totBytes) 2396793SBrad.Beckmann@amd.com ; 2406657Snate@binkert.org 2416657Snate@binkert.org totPackets 2426657Snate@binkert.org .name(name() + ".totPackets") 2436657Snate@binkert.org .desc("Total Packets") 2446657Snate@binkert.org .precision(0) 2457002Snate@binkert.org .prereq(totBytes) 2466657Snate@binkert.org ; 2477007Snate@binkert.org 2487007Snate@binkert.org totBytes 2497007Snate@binkert.org .name(name() + ".totBytes") 2507007Snate@binkert.org .desc("Total Bytes") 2517007Snate@binkert.org .precision(0) 2526657Snate@binkert.org .prereq(totBytes) 2536877Ssteve.reinhardt@amd.com ; 2546877Ssteve.reinhardt@amd.com 2556657Snate@binkert.org totPacketRate 2566877Ssteve.reinhardt@amd.com .name(name() + ".totPPS") 2576657Snate@binkert.org .desc("Total Tranmission Rate (packets/s)") 2586657Snate@binkert.org .precision(0) 2597002Snate@binkert.org .prereq(totBytes) 2607002Snate@binkert.org ; 2617567SBrad.Beckmann@amd.com 2627567SBrad.Beckmann@amd.com txPacketRate 2637922SBrad.Beckmann@amd.com .name(name() + ".txPPS") 2646881SBrad.Beckmann@amd.com .desc("Packet Tranmission Rate (packets/s)") 2657002Snate@binkert.org .precision(0) 2667002Snate@binkert.org .prereq(txBytes) 2676657Snate@binkert.org ; 2687002Snate@binkert.org 2696902SBrad.Beckmann@amd.com rxPacketRate 2706863Sdrh5@cs.wisc.edu .name(name() + ".rxPPS") 2716863Sdrh5@cs.wisc.edu .desc("Packet Reception Rate (packets/s)") 2728683Snilay@cs.wisc.edu .precision(0) 2738683Snilay@cs.wisc.edu .prereq(rxBytes) 2747007Snate@binkert.org ; 2756657Snate@binkert.org 2766657Snate@binkert.org postedSwi 2776657Snate@binkert.org .name(name() + ".postedSwi") 2786657Snate@binkert.org .desc("number of software interrupts posted to CPU") 2796657Snate@binkert.org .precision(0) 2806657Snate@binkert.org ; 2816882SBrad.Beckmann@amd.com 2826882SBrad.Beckmann@amd.com totalSwi 2836882SBrad.Beckmann@amd.com .name(name() + ".totalSwi") 2846882SBrad.Beckmann@amd.com .desc("total number of Swi written to ISR") 2856657Snate@binkert.org .precision(0) 2866657Snate@binkert.org ; 2876657Snate@binkert.org 2886657Snate@binkert.org coalescedSwi 2897007Snate@binkert.org .name(name() + ".coalescedSwi") 2907839Snilay@cs.wisc.edu .desc("average number of Swi's coalesced into each post") 2917839Snilay@cs.wisc.edu .precision(0) 2927839Snilay@cs.wisc.edu ; 2937839Snilay@cs.wisc.edu 2947839Snilay@cs.wisc.edu postedRxIdle 2957839Snilay@cs.wisc.edu .name(name() + ".postedRxIdle") 2967839Snilay@cs.wisc.edu .desc("number of rxIdle interrupts posted to CPU") 2977839Snilay@cs.wisc.edu .precision(0) 2987839Snilay@cs.wisc.edu ; 2997839Snilay@cs.wisc.edu 3007839Snilay@cs.wisc.edu totalRxIdle 3017839Snilay@cs.wisc.edu .name(name() + ".totalRxIdle") 3027007Snate@binkert.org .desc("total number of RxIdle written to ISR") 3037007Snate@binkert.org .precision(0) 3047007Snate@binkert.org ; 3057007Snate@binkert.org 3067007Snate@binkert.org coalescedRxIdle 3077839Snilay@cs.wisc.edu .name(name() + ".coalescedRxIdle") 3087839Snilay@cs.wisc.edu .desc("average number of RxIdle's coalesced into each post") 3097839Snilay@cs.wisc.edu .precision(0) 3107839Snilay@cs.wisc.edu ; 3117839Snilay@cs.wisc.edu 3127839Snilay@cs.wisc.edu postedRxOk 3137839Snilay@cs.wisc.edu .name(name() + ".postedRxOk") 3147839Snilay@cs.wisc.edu .desc("number of RxOk interrupts posted to CPU") 3157839Snilay@cs.wisc.edu .precision(0) 3167839Snilay@cs.wisc.edu ; 3177839Snilay@cs.wisc.edu 3187839Snilay@cs.wisc.edu totalRxOk 3197007Snate@binkert.org .name(name() + ".totalRxOk") 3207007Snate@binkert.org .desc("total number of RxOk written to ISR") 3217002Snate@binkert.org .precision(0) 3226657Snate@binkert.org ; 3236657Snate@binkert.org 3246657Snate@binkert.org coalescedRxOk 3257055Snate@binkert.org .name(name() + ".coalescedRxOk") 3266657Snate@binkert.org .desc("average number of RxOk's coalesced into each post") 3276657Snate@binkert.org .precision(0) 3286657Snate@binkert.org ; 3296863Sdrh5@cs.wisc.edu 3307055Snate@binkert.org postedRxDesc 3317567SBrad.Beckmann@amd.com .name(name() + ".postedRxDesc") 3328943Sandreas.hansson@arm.com .desc("number of RxDesc interrupts posted to CPU") 3337567SBrad.Beckmann@amd.com .precision(0) 3347567SBrad.Beckmann@amd.com ; 3357567SBrad.Beckmann@amd.com 3367542SBrad.Beckmann@amd.com totalRxDesc 3377542SBrad.Beckmann@amd.com .name(name() + ".totalRxDesc") 3386657Snate@binkert.org .desc("total number of RxDesc written to ISR") 3397007Snate@binkert.org .precision(0) 3406657Snate@binkert.org ; 3416657Snate@binkert.org 3426657Snate@binkert.org coalescedRxDesc 3436657Snate@binkert.org .name(name() + ".coalescedRxDesc") 3446657Snate@binkert.org .desc("average number of RxDesc's coalesced into each post") 3456657Snate@binkert.org .precision(0) 3466657Snate@binkert.org ; 3476657Snate@binkert.org 3487839Snilay@cs.wisc.edu postedTxOk 3497839Snilay@cs.wisc.edu .name(name() + ".postedTxOk") 3507839Snilay@cs.wisc.edu .desc("number of TxOk interrupts posted to CPU") 3517839Snilay@cs.wisc.edu .precision(0) 3527839Snilay@cs.wisc.edu ; 3537839Snilay@cs.wisc.edu 3547839Snilay@cs.wisc.edu totalTxOk 3557839Snilay@cs.wisc.edu .name(name() + ".totalTxOk") 3567839Snilay@cs.wisc.edu .desc("total number of TxOk written to ISR") 3577839Snilay@cs.wisc.edu .precision(0) 3587839Snilay@cs.wisc.edu ; 3597839Snilay@cs.wisc.edu 3607839Snilay@cs.wisc.edu coalescedTxOk 3617839Snilay@cs.wisc.edu .name(name() + ".coalescedTxOk") 3627839Snilay@cs.wisc.edu .desc("average number of TxOk's coalesced into each post") 3637839Snilay@cs.wisc.edu .precision(0) 3646657Snate@binkert.org ; 3656657Snate@binkert.org 3666657Snate@binkert.org postedTxIdle 3676657Snate@binkert.org .name(name() + ".postedTxIdle") 3687839Snilay@cs.wisc.edu .desc("number of TxIdle interrupts posted to CPU") 3697839Snilay@cs.wisc.edu .precision(0) 3707839Snilay@cs.wisc.edu ; 3717839Snilay@cs.wisc.edu 3727839Snilay@cs.wisc.edu totalTxIdle 3737839Snilay@cs.wisc.edu .name(name() + ".totalTxIdle") 3747839Snilay@cs.wisc.edu .desc("total number of TxIdle written to ISR") 3757839Snilay@cs.wisc.edu .precision(0) 3767839Snilay@cs.wisc.edu ; 3777839Snilay@cs.wisc.edu 3787839Snilay@cs.wisc.edu coalescedTxIdle 3797839Snilay@cs.wisc.edu .name(name() + ".coalescedTxIdle") 3807839Snilay@cs.wisc.edu .desc("average number of TxIdle's coalesced into each post") 3817839Snilay@cs.wisc.edu .precision(0) 3827839Snilay@cs.wisc.edu ; 3837839Snilay@cs.wisc.edu 3846657Snate@binkert.org postedTxDesc 3856657Snate@binkert.org .name(name() + ".postedTxDesc") 3866657Snate@binkert.org .desc("number of TxDesc interrupts posted to CPU") 3876657Snate@binkert.org .precision(0) 3887007Snate@binkert.org ; 3896657Snate@binkert.org 3906657Snate@binkert.org totalTxDesc 3916657Snate@binkert.org .name(name() + ".totalTxDesc") 3926657Snate@binkert.org .desc("total number of TxDesc written to ISR") 3936657Snate@binkert.org .precision(0) 3946657Snate@binkert.org ; 3956657Snate@binkert.org 3966657Snate@binkert.org coalescedTxDesc 3976657Snate@binkert.org .name(name() + ".coalescedTxDesc") 3986657Snate@binkert.org .desc("average number of TxDesc's coalesced into each post") 3997007Snate@binkert.org .precision(0) 4006657Snate@binkert.org ; 4016657Snate@binkert.org 4026657Snate@binkert.org postedRxOrn 4036657Snate@binkert.org .name(name() + ".postedRxOrn") 4046657Snate@binkert.org .desc("number of RxOrn posted to CPU") 4056999Snate@binkert.org .precision(0) 4066657Snate@binkert.org ; 4076657Snate@binkert.org 4086657Snate@binkert.org totalRxOrn 4096657Snate@binkert.org .name(name() + ".totalRxOrn") 4107007Snate@binkert.org .desc("total number of RxOrn written to ISR") 4116657Snate@binkert.org .precision(0) 4126657Snate@binkert.org ; 4136657Snate@binkert.org 4146657Snate@binkert.org coalescedRxOrn 4156657Snate@binkert.org .name(name() + ".coalescedRxOrn") 4168946Sandreas.hansson@arm.com .desc("average number of RxOrn's coalesced into each post") 4178946Sandreas.hansson@arm.com .precision(0) 4188946Sandreas.hansson@arm.com ; 4197832Snate@binkert.org 4207002Snate@binkert.org coalescedTotal 4217002Snate@binkert.org .name(name() + ".coalescedTotal") 4227002Snate@binkert.org .desc("average number of interrupts coalesced into each post") 4238641Snate@binkert.org .precision(0) 4247056Snate@binkert.org ; 4258232Snate@binkert.org 4268232Snate@binkert.org postedInterrupts 4276657Snate@binkert.org .name(name() + ".postedInterrupts") 4288229Snate@binkert.org .desc("number of posts to CPU") 4296657Snate@binkert.org .precision(0) 4306657Snate@binkert.org ; 4317056Snate@binkert.org 4327056Snate@binkert.org droppedPackets 4336657Snate@binkert.org .name(name() + ".droppedPackets") 4347002Snate@binkert.org .desc("number of packets dropped") 4357002Snate@binkert.org .precision(0) 4366657Snate@binkert.org ; 4376657Snate@binkert.org 4386657Snate@binkert.org coalescedSwi = totalSwi / postedInterrupts; 4396657Snate@binkert.org coalescedRxIdle = totalRxIdle / postedInterrupts; 4406657Snate@binkert.org coalescedRxOk = totalRxOk / postedInterrupts; 4416793SBrad.Beckmann@amd.com coalescedRxDesc = totalRxDesc / postedInterrupts; 4426657Snate@binkert.org coalescedTxOk = totalTxOk / postedInterrupts; 4436657Snate@binkert.org coalescedTxIdle = totalTxIdle / postedInterrupts; 4446657Snate@binkert.org coalescedTxDesc = totalTxDesc / postedInterrupts; 4456657Snate@binkert.org coalescedRxOrn = totalRxOrn / postedInterrupts; 4466877Ssteve.reinhardt@amd.com 4476877Ssteve.reinhardt@amd.com coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 4486877Ssteve.reinhardt@amd.com totalTxOk + totalTxIdle + totalTxDesc + 4496877Ssteve.reinhardt@amd.com totalRxOrn) / postedInterrupts; 4506877Ssteve.reinhardt@amd.com 4516877Ssteve.reinhardt@amd.com txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4526657Snate@binkert.org rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4537542SBrad.Beckmann@amd.com totBandwidth = txBandwidth + rxBandwidth; 4546657Snate@binkert.org totBytes = txBytes + rxBytes; 4557007Snate@binkert.org totPackets = txPackets + rxPackets; 4566657Snate@binkert.org 4576657Snate@binkert.org txPacketRate = txPackets / simSeconds; 4587007Snate@binkert.org rxPacketRate = rxPackets / simSeconds; 4596657Snate@binkert.org} 4606877Ssteve.reinhardt@amd.com 4616877Ssteve.reinhardt@amd.com 4626657Snate@binkert.org/** 4636877Ssteve.reinhardt@amd.com * This is to write to the PCI general configuration registers 4646877Ssteve.reinhardt@amd.com */ 4656877Ssteve.reinhardt@amd.comvoid 4666877Ssteve.reinhardt@amd.comNSGigE::writeConfig(int offset, const uint16_t data) 4676877Ssteve.reinhardt@amd.com{ 4686969SBrad.Beckmann@amd.com if (offset < PCI_DEVICE_SPECIFIC) 4698532SLisa.Hsu@amd.com PciDev::writeConfig(offset, data); 4706657Snate@binkert.org else 4717567SBrad.Beckmann@amd.com panic("Device specific PCI config space not implemented!\n"); 4727567SBrad.Beckmann@amd.com 4737567SBrad.Beckmann@amd.com switch (offset) { 4747567SBrad.Beckmann@amd.com // seems to work fine without all these PCI settings, but i 4757567SBrad.Beckmann@amd.com // put in the IO to double check, an assertion will fail if we 4767567SBrad.Beckmann@amd.com // need to properly implement it 4776657Snate@binkert.org case PCI_COMMAND: 4786882SBrad.Beckmann@amd.com if (config.data[offset] & PCI_CMD_IOSE) 4796882SBrad.Beckmann@amd.com ioEnable = true; 4806882SBrad.Beckmann@amd.com else 4816882SBrad.Beckmann@amd.com ioEnable = false; 4826882SBrad.Beckmann@amd.com break; 4836882SBrad.Beckmann@amd.com } 4846882SBrad.Beckmann@amd.com} 4858189SLisa.Hsu@amd.com 4868189SLisa.Hsu@amd.com/** 4876877Ssteve.reinhardt@amd.com * This reads the device registers, which are detailed in the NS83820 4888189SLisa.Hsu@amd.com * spec sheet 4898189SLisa.Hsu@amd.com */ 4908189SLisa.Hsu@amd.comTick 4918189SLisa.Hsu@amd.comNSGigE::read(Packet *pkt) 4926882SBrad.Beckmann@amd.com{ 4936882SBrad.Beckmann@amd.com assert(ioEnable); 4946882SBrad.Beckmann@amd.com 4956882SBrad.Beckmann@amd.com pkt->time += pioDelay; 4966882SBrad.Beckmann@amd.com pkt->allocate(); 4976882SBrad.Beckmann@amd.com 4986882SBrad.Beckmann@amd.com //The mask is to give you only the offset into the device register file 4996882SBrad.Beckmann@amd.com Addr daddr = pkt->getAddr() & 0xfff; 5006882SBrad.Beckmann@amd.com DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 5016882SBrad.Beckmann@amd.com daddr, pkt->getAddr(), pkt->getSize()); 5028189SLisa.Hsu@amd.com 5036882SBrad.Beckmann@amd.com 5046882SBrad.Beckmann@amd.com // there are some reserved registers, you can see ns_gige_reg.h and 5056882SBrad.Beckmann@amd.com // the spec sheet for details 5068189SLisa.Hsu@amd.com if (daddr > LAST && daddr <= RESERVED) { 5078189SLisa.Hsu@amd.com panic("Accessing reserved register"); 5088189SLisa.Hsu@amd.com } else if (daddr > RESERVED && daddr <= 0x3FC) { 5098189SLisa.Hsu@amd.com if (pkt->getSize() == sizeof(uint8_t)) 5108938SLisa.Hsu@amd.com readConfig(daddr & 0xff, pkt->getPtr<uint8_t>()); 5118938SLisa.Hsu@amd.com if (pkt->getSize() == sizeof(uint16_t)) 5128938SLisa.Hsu@amd.com readConfig(daddr & 0xff, pkt->getPtr<uint16_t>()); 5138938SLisa.Hsu@amd.com if (pkt->getSize() == sizeof(uint32_t)) 5148938SLisa.Hsu@amd.com readConfig(daddr & 0xff, pkt->getPtr<uint32_t>()); 5158938SLisa.Hsu@amd.com pkt->result = Packet::Success; 5168938SLisa.Hsu@amd.com return pioDelay; 5176888SBrad.Beckmann@amd.com } else if (daddr >= MIB_START && daddr <= MIB_END) { 5186888SBrad.Beckmann@amd.com // don't implement all the MIB's. hopefully the kernel 5196888SBrad.Beckmann@amd.com // doesn't actually DEPEND upon their values 5206888SBrad.Beckmann@amd.com // MIB are just hardware stats keepers 5216888SBrad.Beckmann@amd.com pkt->set<uint32_t>(0); 5228189SLisa.Hsu@amd.com pkt->result = Packet::Success; 5236888SBrad.Beckmann@amd.com return pioDelay; 5246888SBrad.Beckmann@amd.com } else if (daddr > 0x3FC) 5256657Snate@binkert.org panic("Something is messed up!\n"); 5266888SBrad.Beckmann@amd.com 5276888SBrad.Beckmann@amd.com assert(pkt->getSize() == sizeof(uint32_t)); 5286888SBrad.Beckmann@amd.com uint32_t ® = *pkt->getPtr<uint32_t>(); 5296888SBrad.Beckmann@amd.com uint16_t rfaddr; 5306657Snate@binkert.org 5316657Snate@binkert.org switch (daddr) { 5326657Snate@binkert.org case CR: 5336657Snate@binkert.org reg = regs.command; 5346657Snate@binkert.org //these are supposed to be cleared on a read 5356657Snate@binkert.org reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 5366657Snate@binkert.org break; 5376657Snate@binkert.org 5386657Snate@binkert.org case CFGR: 5397007Snate@binkert.org reg = regs.config; 5407007Snate@binkert.org break; 5416657Snate@binkert.org 5427007Snate@binkert.org case MEAR: 5437007Snate@binkert.org reg = regs.mear; 5447007Snate@binkert.org break; 5456657Snate@binkert.org 5466657Snate@binkert.org case PTSCR: 5476657Snate@binkert.org reg = regs.ptscr; 5487007Snate@binkert.org break; 5497542SBrad.Beckmann@amd.com 5507542SBrad.Beckmann@amd.com case ISR: 5517007Snate@binkert.org reg = regs.isr; 5526657Snate@binkert.org devIntrClear(ISR_ALL); 5536657Snate@binkert.org break; 5546657Snate@binkert.org 5556657Snate@binkert.org case IMR: 5566657Snate@binkert.org reg = regs.imr; 5576657Snate@binkert.org break; 5586657Snate@binkert.org 5596657Snate@binkert.org case IER: 5606657Snate@binkert.org reg = regs.ier; 5616657Snate@binkert.org break; 5626657Snate@binkert.org 5636657Snate@binkert.org case IHR: 5646657Snate@binkert.org reg = regs.ihr; 5656657Snate@binkert.org break; 5666657Snate@binkert.org 5676657Snate@binkert.org case TXDP: 5686657Snate@binkert.org reg = regs.txdp; 5696657Snate@binkert.org break; 5706657Snate@binkert.org 5716657Snate@binkert.org case TXDP_HI: 5726657Snate@binkert.org reg = regs.txdp_hi; 5736657Snate@binkert.org break; 5746657Snate@binkert.org 5756657Snate@binkert.org case TX_CFG: 5766657Snate@binkert.org reg = regs.txcfg; 5776657Snate@binkert.org break; 5786657Snate@binkert.org 5796657Snate@binkert.org case GPIOR: 5807007Snate@binkert.org reg = regs.gpior; 5816657Snate@binkert.org break; 5826657Snate@binkert.org 5836657Snate@binkert.org case RXDP: 5846657Snate@binkert.org reg = regs.rxdp; 5857007Snate@binkert.org break; 5866657Snate@binkert.org 5877007Snate@binkert.org case RXDP_HI: 5887007Snate@binkert.org reg = regs.rxdp_hi; 5896657Snate@binkert.org break; 5906657Snate@binkert.org 5916657Snate@binkert.org case RX_CFG: 5926657Snate@binkert.org reg = regs.rxcfg; 5936657Snate@binkert.org break; 5946657Snate@binkert.org 5956657Snate@binkert.org case PQCR: 5966657Snate@binkert.org reg = regs.pqcr; 5976657Snate@binkert.org break; 5986657Snate@binkert.org 5996657Snate@binkert.org case WCSR: 6006657Snate@binkert.org reg = regs.wcsr; 6016657Snate@binkert.org break; 6026657Snate@binkert.org 6036657Snate@binkert.org case PCR: 6047566SBrad.Beckmann@amd.com reg = regs.pcr; 6056657Snate@binkert.org break; 6066657Snate@binkert.org 6076657Snate@binkert.org // see the spec sheet for how RFCR and RFDR work 6086657Snate@binkert.org // basically, you write to RFCR to tell the machine 6096657Snate@binkert.org // what you want to do next, then you act upon RFDR, 6108308Stushar@csail.mit.edu // and the device will be prepared b/c of what you 6116657Snate@binkert.org // wrote to RFCR 6126657Snate@binkert.org case RFCR: 6136657Snate@binkert.org reg = regs.rfcr; 6147007Snate@binkert.org break; 6157007Snate@binkert.org 6168308Stushar@csail.mit.edu case RFDR: 6176657Snate@binkert.org rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 6186657Snate@binkert.org switch (rfaddr) { 6196657Snate@binkert.org // Read from perfect match ROM octets 6206657Snate@binkert.org case 0x000: 6216657Snate@binkert.org reg = rom.perfectMatch[1]; 6226657Snate@binkert.org reg = reg << 8; 6236657Snate@binkert.org reg += rom.perfectMatch[0]; 6246657Snate@binkert.org break; 6256657Snate@binkert.org case 0x002: 6266657Snate@binkert.org reg = rom.perfectMatch[3] << 8; 6276657Snate@binkert.org reg += rom.perfectMatch[2]; 6286657Snate@binkert.org break; 6298187SLisa.Hsu@amd.com case 0x004: 6306657Snate@binkert.org reg = rom.perfectMatch[5] << 8; 6316657Snate@binkert.org reg += rom.perfectMatch[4]; 6326657Snate@binkert.org break; 6336657Snate@binkert.org default: 6346657Snate@binkert.org // Read filter hash table 6356657Snate@binkert.org if (rfaddr >= FHASH_ADDR && 6366657Snate@binkert.org rfaddr < FHASH_ADDR + FHASH_SIZE) { 6376657Snate@binkert.org 6386657Snate@binkert.org // Only word-aligned reads supported 6397454Snate@binkert.org if (rfaddr % 2) 6406657Snate@binkert.org panic("unaligned read from filter hash table!"); 6416657Snate@binkert.org 6426657Snate@binkert.org reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 6436657Snate@binkert.org reg += rom.filterHash[rfaddr - FHASH_ADDR]; 6447007Snate@binkert.org break; 6457056Snate@binkert.org } 6467007Snate@binkert.org 6477007Snate@binkert.org panic("reading RFDR for something other than pattern" 6486657Snate@binkert.org " matching or hashing! %#x\n", rfaddr); 6497566SBrad.Beckmann@amd.com } 6507566SBrad.Beckmann@amd.com break; 6517566SBrad.Beckmann@amd.com 6527566SBrad.Beckmann@amd.com case SRR: 6537566SBrad.Beckmann@amd.com reg = regs.srr; 6547566SBrad.Beckmann@amd.com break; 6557566SBrad.Beckmann@amd.com 6566657Snate@binkert.org case MIBC: 6577672Snate@binkert.org reg = regs.mibc; 6586657Snate@binkert.org reg &= ~(MIBC_MIBS | MIBC_ACLR); 6596657Snate@binkert.org break; 6606657Snate@binkert.org 6616657Snate@binkert.org case VRCR: 6627672Snate@binkert.org reg = regs.vrcr; 6636657Snate@binkert.org break; 6647056Snate@binkert.org 6656657Snate@binkert.org case VTCR: 6666657Snate@binkert.org reg = regs.vtcr; 6677672Snate@binkert.org break; 6686657Snate@binkert.org 6696657Snate@binkert.org case VDR: 6706657Snate@binkert.org reg = regs.vdr; 6716657Snate@binkert.org break; 6726657Snate@binkert.org 6736657Snate@binkert.org case CCSR: 6746657Snate@binkert.org reg = regs.ccsr; 6756657Snate@binkert.org break; 6766657Snate@binkert.org 6776657Snate@binkert.org case TBICR: 6786657Snate@binkert.org reg = regs.tbicr; 6797542SBrad.Beckmann@amd.com break; 6806657Snate@binkert.org 6816657Snate@binkert.org case TBISR: 6826657Snate@binkert.org reg = regs.tbisr; 6836657Snate@binkert.org break; 6846657Snate@binkert.org 6856657Snate@binkert.org case TANAR: 6866657Snate@binkert.org reg = regs.tanar; 6876657Snate@binkert.org break; 6886657Snate@binkert.org 6896657Snate@binkert.org case TANLPAR: 6906657Snate@binkert.org reg = regs.tanlpar; 6916657Snate@binkert.org break; 6926657Snate@binkert.org 6936657Snate@binkert.org case TANER: 6948683Snilay@cs.wisc.edu reg = regs.taner; 6958683Snilay@cs.wisc.edu break; 6968683Snilay@cs.wisc.edu 6978683Snilay@cs.wisc.edu case TESR: 6988683Snilay@cs.wisc.edu reg = regs.tesr; 6998683Snilay@cs.wisc.edu break; 7006657Snate@binkert.org 7017007Snate@binkert.org case M5REG: 7027007Snate@binkert.org reg = 0; 7037007Snate@binkert.org if (params()->rx_thread) 7046657Snate@binkert.org reg |= M5REG_RX_THREAD; 7056657Snate@binkert.org if (params()->tx_thread) 7066657Snate@binkert.org reg |= M5REG_TX_THREAD; 7077007Snate@binkert.org if (params()->rss) 7087007Snate@binkert.org reg |= M5REG_RSS; 7097007Snate@binkert.org break; 7106657Snate@binkert.org 7116657Snate@binkert.org default: 7126657Snate@binkert.org panic("reading unimplemented register: addr=%#x", daddr); 7138683Snilay@cs.wisc.edu } 7148683Snilay@cs.wisc.edu 7158683Snilay@cs.wisc.edu DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 7168683Snilay@cs.wisc.edu daddr, reg, reg); 7178683Snilay@cs.wisc.edu 7188683Snilay@cs.wisc.edu pkt->result = Packet::Success; 7197007Snate@binkert.org return pioDelay; 7207007Snate@binkert.org} 7217007Snate@binkert.org 7226657Snate@binkert.orgTick 7236657Snate@binkert.orgNSGigE::write(Packet *pkt) 7246657Snate@binkert.org{ 7257007Snate@binkert.org assert(ioEnable); 7267007Snate@binkert.org 7277007Snate@binkert.org Addr daddr = pkt->getAddr() & 0xfff; 7286657Snate@binkert.org DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 7296657Snate@binkert.org daddr, pkt->getAddr(), pkt->getSize()); 7306657Snate@binkert.org 7317007Snate@binkert.org pkt->time += pioDelay; 7327007Snate@binkert.org 7337007Snate@binkert.org if (daddr > LAST && daddr <= RESERVED) { 7346657Snate@binkert.org panic("Accessing reserved register"); 7356657Snate@binkert.org } else if (daddr > RESERVED && daddr <= 0x3FC) { 7367007Snate@binkert.org if (pkt->getSize() == sizeof(uint8_t)) 7377007Snate@binkert.org writeConfig(daddr & 0xff, pkt->get<uint8_t>()); 7387567SBrad.Beckmann@amd.com if (pkt->getSize() == sizeof(uint16_t)) 7397567SBrad.Beckmann@amd.com writeConfig(daddr & 0xff, pkt->get<uint16_t>()); 7407567SBrad.Beckmann@amd.com if (pkt->getSize() == sizeof(uint32_t)) 7417567SBrad.Beckmann@amd.com writeConfig(daddr & 0xff, pkt->get<uint32_t>()); 7427567SBrad.Beckmann@amd.com pkt->result = Packet::Success; 7437567SBrad.Beckmann@amd.com return pioDelay; 7447567SBrad.Beckmann@amd.com } else if (daddr > 0x3FC) 7457567SBrad.Beckmann@amd.com panic("Something is messed up!\n"); 7467567SBrad.Beckmann@amd.com 7477567SBrad.Beckmann@amd.com if (pkt->getSize() == sizeof(uint32_t)) { 7487567SBrad.Beckmann@amd.com uint32_t reg = pkt->get<uint32_t>(); 7497567SBrad.Beckmann@amd.com uint16_t rfaddr; 7507567SBrad.Beckmann@amd.com 7518155Snilay@cs.wisc.edu DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 7528155Snilay@cs.wisc.edu 7538155Snilay@cs.wisc.edu switch (daddr) { 7548155Snilay@cs.wisc.edu case CR: 7558155Snilay@cs.wisc.edu regs.command = reg; 7568155Snilay@cs.wisc.edu if (reg & CR_TXD) { 7578155Snilay@cs.wisc.edu txEnable = false; 7588155Snilay@cs.wisc.edu } else if (reg & CR_TXE) { 7598155Snilay@cs.wisc.edu txEnable = true; 7608155Snilay@cs.wisc.edu 7618155Snilay@cs.wisc.edu // the kernel is enabling the transmit machine 7627567SBrad.Beckmann@amd.com if (txState == txIdle) 7638155Snilay@cs.wisc.edu txKick(); 7648155Snilay@cs.wisc.edu } 7657567SBrad.Beckmann@amd.com 7667567SBrad.Beckmann@amd.com if (reg & CR_RXD) { 7677567SBrad.Beckmann@amd.com rxEnable = false; 7687567SBrad.Beckmann@amd.com } else if (reg & CR_RXE) { 7697922SBrad.Beckmann@amd.com rxEnable = true; 7707922SBrad.Beckmann@amd.com 7717922SBrad.Beckmann@amd.com if (rxState == rxIdle) 7727922SBrad.Beckmann@amd.com rxKick(); 7737922SBrad.Beckmann@amd.com } 7747922SBrad.Beckmann@amd.com 7757922SBrad.Beckmann@amd.com if (reg & CR_TXR) 7767922SBrad.Beckmann@amd.com txReset(); 7778154Snilay@cs.wisc.edu 7788154Snilay@cs.wisc.edu if (reg & CR_RXR) 7798154Snilay@cs.wisc.edu rxReset(); 7808154Snilay@cs.wisc.edu 7818154Snilay@cs.wisc.edu if (reg & CR_SWI) 7828154Snilay@cs.wisc.edu devIntrPost(ISR_SWI); 7838154Snilay@cs.wisc.edu 7848154Snilay@cs.wisc.edu if (reg & CR_RST) { 7858154Snilay@cs.wisc.edu txReset(); 7868154Snilay@cs.wisc.edu rxReset(); 7878154Snilay@cs.wisc.edu 7888154Snilay@cs.wisc.edu regsReset(); 7898154Snilay@cs.wisc.edu } 7908154Snilay@cs.wisc.edu break; 7918154Snilay@cs.wisc.edu 7928154Snilay@cs.wisc.edu case CFGR: 7938154Snilay@cs.wisc.edu if (reg & CFGR_LNKSTS || 7948154Snilay@cs.wisc.edu reg & CFGR_SPDSTS || 7958154Snilay@cs.wisc.edu reg & CFGR_DUPSTS || 7968154Snilay@cs.wisc.edu reg & CFGR_RESERVED || 7978154Snilay@cs.wisc.edu reg & CFGR_T64ADDR || 7987922SBrad.Beckmann@amd.com reg & CFGR_PCI64_DET) 7997922SBrad.Beckmann@amd.com 8007922SBrad.Beckmann@amd.com // First clear all writable bits 8017922SBrad.Beckmann@amd.com regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 8027007Snate@binkert.org CFGR_RESERVED | CFGR_T64ADDR | 8037007Snate@binkert.org CFGR_PCI64_DET; 8046863Sdrh5@cs.wisc.edu // Now set the appropriate writable bits 8056863Sdrh5@cs.wisc.edu regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 8066863Sdrh5@cs.wisc.edu CFGR_RESERVED | CFGR_T64ADDR | 8077007Snate@binkert.org CFGR_PCI64_DET); 8087007Snate@binkert.org 8097007Snate@binkert.org// all these #if 0's are because i don't THINK the kernel needs to 8107007Snate@binkert.org// have these implemented. if there is a problem relating to one of 8116863Sdrh5@cs.wisc.edu// these, you may need to add functionality in. 8126863Sdrh5@cs.wisc.edu if (reg & CFGR_TBI_EN) ; 8136863Sdrh5@cs.wisc.edu if (reg & CFGR_MODE_1000) ; 8146863Sdrh5@cs.wisc.edu 8156863Sdrh5@cs.wisc.edu if (reg & CFGR_AUTO_1000) 8166863Sdrh5@cs.wisc.edu panic("CFGR_AUTO_1000 not implemented!\n"); 8177007Snate@binkert.org 8187007Snate@binkert.org if (reg & CFGR_PINT_DUPSTS || 8197007Snate@binkert.org reg & CFGR_PINT_LNKSTS || 8207007Snate@binkert.org reg & CFGR_PINT_SPDSTS) 8217007Snate@binkert.org ; 8226657Snate@binkert.org 8237007Snate@binkert.org if (reg & CFGR_TMRTEST) ; 8247007Snate@binkert.org if (reg & CFGR_MRM_DIS) ; 8257007Snate@binkert.org if (reg & CFGR_MWI_DIS) ; 8266657Snate@binkert.org 8276657Snate@binkert.org if (reg & CFGR_T64ADDR) ; 8287007Snate@binkert.org // panic("CFGR_T64ADDR is read only register!\n"); 8297007Snate@binkert.org 8307007Snate@binkert.org if (reg & CFGR_PCI64_DET) 8316657Snate@binkert.org panic("CFGR_PCI64_DET is read only register!\n"); 8326657Snate@binkert.org 8337007Snate@binkert.org if (reg & CFGR_DATA64_EN) ; 8347007Snate@binkert.org if (reg & CFGR_M64ADDR) ; 8357007Snate@binkert.org if (reg & CFGR_PHY_RST) ; 8366902SBrad.Beckmann@amd.com if (reg & CFGR_PHY_DIS) ; 8376902SBrad.Beckmann@amd.com 8386902SBrad.Beckmann@amd.com if (reg & CFGR_EXTSTS_EN) 8396902SBrad.Beckmann@amd.com extstsEnable = true; 8406902SBrad.Beckmann@amd.com else 8416902SBrad.Beckmann@amd.com extstsEnable = false; 8426902SBrad.Beckmann@amd.com 8437025SBrad.Beckmann@amd.com if (reg & CFGR_REQALG) ; 8446902SBrad.Beckmann@amd.com if (reg & CFGR_SB) ; 8456902SBrad.Beckmann@amd.com if (reg & CFGR_POW) ; 8466902SBrad.Beckmann@amd.com if (reg & CFGR_EXD) ; 8476902SBrad.Beckmann@amd.com if (reg & CFGR_PESEL) ; 8486902SBrad.Beckmann@amd.com if (reg & CFGR_BROM_DIS) ; 8497542SBrad.Beckmann@amd.com if (reg & CFGR_EXT_125) ; 8507542SBrad.Beckmann@amd.com if (reg & CFGR_BEM) ; 8517542SBrad.Beckmann@amd.com break; 8526902SBrad.Beckmann@amd.com 8536902SBrad.Beckmann@amd.com case MEAR: 8546902SBrad.Beckmann@amd.com // Clear writable bits 8556902SBrad.Beckmann@amd.com regs.mear &= MEAR_EEDO; 8566902SBrad.Beckmann@amd.com // Set appropriate writable bits 8576902SBrad.Beckmann@amd.com regs.mear |= reg & ~MEAR_EEDO; 8586902SBrad.Beckmann@amd.com 8596902SBrad.Beckmann@amd.com // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 8606902SBrad.Beckmann@amd.com // even though it could get it through RFDR 8616902SBrad.Beckmann@amd.com if (reg & MEAR_EESEL) { 8626902SBrad.Beckmann@amd.com // Rising edge of clock 8636902SBrad.Beckmann@amd.com if (reg & MEAR_EECLK && !eepromClk) 8646902SBrad.Beckmann@amd.com eepromKick(); 8656902SBrad.Beckmann@amd.com } 8666902SBrad.Beckmann@amd.com else { 8677542SBrad.Beckmann@amd.com eepromState = eepromStart; 8686902SBrad.Beckmann@amd.com regs.mear &= ~MEAR_EEDI; 8697839Snilay@cs.wisc.edu } 8707839Snilay@cs.wisc.edu 8717839Snilay@cs.wisc.edu eepromClk = reg & MEAR_EECLK; 8727839Snilay@cs.wisc.edu 8737839Snilay@cs.wisc.edu // since phy is completely faked, MEAR_MD* don't matter 8747839Snilay@cs.wisc.edu if (reg & MEAR_MDIO) ; 8757839Snilay@cs.wisc.edu if (reg & MEAR_MDDIR) ; 8767839Snilay@cs.wisc.edu if (reg & MEAR_MDC) ; 8777839Snilay@cs.wisc.edu break; 8787839Snilay@cs.wisc.edu 8797839Snilay@cs.wisc.edu case PTSCR: 8807839Snilay@cs.wisc.edu regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 8817839Snilay@cs.wisc.edu // these control BISTs for various parts of chip - we 8827839Snilay@cs.wisc.edu // don't care or do just fake that the BIST is done 8837839Snilay@cs.wisc.edu if (reg & PTSCR_RBIST_EN) 8847839Snilay@cs.wisc.edu regs.ptscr |= PTSCR_RBIST_DONE; 8857839Snilay@cs.wisc.edu if (reg & PTSCR_EEBIST_EN) 8867839Snilay@cs.wisc.edu regs.ptscr &= ~PTSCR_EEBIST_EN; 8877839Snilay@cs.wisc.edu if (reg & PTSCR_EELOAD_EN) 8887839Snilay@cs.wisc.edu regs.ptscr &= ~PTSCR_EELOAD_EN; 8897839Snilay@cs.wisc.edu break; 8907839Snilay@cs.wisc.edu 8917839Snilay@cs.wisc.edu case ISR: /* writing to the ISR has no effect */ 8927839Snilay@cs.wisc.edu panic("ISR is a read only register!\n"); 8937839Snilay@cs.wisc.edu 8947839Snilay@cs.wisc.edu case IMR: 8957839Snilay@cs.wisc.edu regs.imr = reg; 8967839Snilay@cs.wisc.edu devIntrChangeMask(); 8977839Snilay@cs.wisc.edu break; 8987839Snilay@cs.wisc.edu 8997839Snilay@cs.wisc.edu case IER: 9007839Snilay@cs.wisc.edu regs.ier = reg; 9017839Snilay@cs.wisc.edu break; 9027839Snilay@cs.wisc.edu 9037839Snilay@cs.wisc.edu case IHR: 9047839Snilay@cs.wisc.edu regs.ihr = reg; 9057839Snilay@cs.wisc.edu /* not going to implement real interrupt holdoff */ 9066902SBrad.Beckmann@amd.com break; 9078683Snilay@cs.wisc.edu 9088683Snilay@cs.wisc.edu case TXDP: 9098683Snilay@cs.wisc.edu regs.txdp = (reg & 0xFFFFFFFC); 9108683Snilay@cs.wisc.edu assert(txState == txIdle); 9118683Snilay@cs.wisc.edu CTDD = false; 9128683Snilay@cs.wisc.edu break; 9138683Snilay@cs.wisc.edu 9148683Snilay@cs.wisc.edu case TXDP_HI: 9158683Snilay@cs.wisc.edu regs.txdp_hi = reg; 9168683Snilay@cs.wisc.edu break; 9178683Snilay@cs.wisc.edu 9188683Snilay@cs.wisc.edu case TX_CFG: 9198683Snilay@cs.wisc.edu regs.txcfg = reg; 9208683Snilay@cs.wisc.edu#if 0 9218683Snilay@cs.wisc.edu if (reg & TX_CFG_CSI) ; 9228683Snilay@cs.wisc.edu if (reg & TX_CFG_HBI) ; 9238683Snilay@cs.wisc.edu if (reg & TX_CFG_MLB) ; 9246657Snate@binkert.org if (reg & TX_CFG_ATP) ; 9256657Snate@binkert.org if (reg & TX_CFG_ECRETRY) { 9267839Snilay@cs.wisc.edu /* 9277839Snilay@cs.wisc.edu * this could easily be implemented, but considering 9287839Snilay@cs.wisc.edu * the network is just a fake pipe, wouldn't make 9297839Snilay@cs.wisc.edu * sense to do this 9306657Snate@binkert.org */ 9317839Snilay@cs.wisc.edu } 9327839Snilay@cs.wisc.edu 9337839Snilay@cs.wisc.edu if (reg & TX_CFG_BRST_DIS) ; 9347839Snilay@cs.wisc.edu#endif 9357839Snilay@cs.wisc.edu 9368055Sksewell@umich.edu#if 0 9377839Snilay@cs.wisc.edu /* we handle our own DMA, ignore the kernel's exhortations */ 9387839Snilay@cs.wisc.edu if (reg & TX_CFG_MXDMA) ; 9396657Snate@binkert.org#endif 9407839Snilay@cs.wisc.edu 9417839Snilay@cs.wisc.edu // also, we currently don't care about fill/drain 9427839Snilay@cs.wisc.edu // thresholds though this may change in the future with 9437839Snilay@cs.wisc.edu // more realistic networks or a driver which changes it 9447839Snilay@cs.wisc.edu // according to feedback 9457839Snilay@cs.wisc.edu 9467839Snilay@cs.wisc.edu break; 9477839Snilay@cs.wisc.edu 9487839Snilay@cs.wisc.edu case GPIOR: 9497839Snilay@cs.wisc.edu // Only write writable bits 9507839Snilay@cs.wisc.edu regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9518055Sksewell@umich.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 9527839Snilay@cs.wisc.edu regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 9537839Snilay@cs.wisc.edu | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 9547839Snilay@cs.wisc.edu /* these just control general purpose i/o pins, don't matter */ 9557839Snilay@cs.wisc.edu break; 9567839Snilay@cs.wisc.edu 9577839Snilay@cs.wisc.edu case RXDP: 9587839Snilay@cs.wisc.edu regs.rxdp = reg; 9597839Snilay@cs.wisc.edu CRDD = false; 9607839Snilay@cs.wisc.edu break; 9617839Snilay@cs.wisc.edu 9627839Snilay@cs.wisc.edu case RXDP_HI: 9637839Snilay@cs.wisc.edu regs.rxdp_hi = reg; 9647839Snilay@cs.wisc.edu break; 9657839Snilay@cs.wisc.edu 9668055Sksewell@umich.edu case RX_CFG: 9677839Snilay@cs.wisc.edu regs.rxcfg = reg; 9687839Snilay@cs.wisc.edu#if 0 9697839Snilay@cs.wisc.edu if (reg & RX_CFG_AEP) ; 9707839Snilay@cs.wisc.edu if (reg & RX_CFG_ARP) ; 9717839Snilay@cs.wisc.edu if (reg & RX_CFG_STRIPCRC) ; 9727839Snilay@cs.wisc.edu if (reg & RX_CFG_RX_RD) ; 9737839Snilay@cs.wisc.edu if (reg & RX_CFG_ALP) ; 9747839Snilay@cs.wisc.edu if (reg & RX_CFG_AIRL) ; 9757839Snilay@cs.wisc.edu 9767839Snilay@cs.wisc.edu /* we handle our own DMA, ignore what kernel says about it */ 9776657Snate@binkert.org if (reg & RX_CFG_MXDMA) ; 9787007Snate@binkert.org 9797007Snate@binkert.org //also, we currently don't care about fill/drain thresholds 9806657Snate@binkert.org //though this may change in the future with more realistic 9818055Sksewell@umich.edu //networks or a driver which changes it according to feedback 9826657Snate@binkert.org if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 9836657Snate@binkert.org#endif 9846657Snate@binkert.org break; 9856657Snate@binkert.org 9868478Snilay@cs.wisc.edu case PQCR: 9878478Snilay@cs.wisc.edu /* there is no priority queueing used in the linux 2.6 driver */ 9888478Snilay@cs.wisc.edu regs.pqcr = reg; 9896657Snate@binkert.org break; 9906657Snate@binkert.org 9916657Snate@binkert.org case WCSR: 9926657Snate@binkert.org /* not going to implement wake on LAN */ 9936657Snate@binkert.org regs.wcsr = reg; 9946999Snate@binkert.org break; 9956657Snate@binkert.org 9966657Snate@binkert.org case PCR: 9979104Shestness@cs.utexas.edu /* not going to implement pause control */ 9989104Shestness@cs.utexas.edu regs.pcr = reg; 9999104Shestness@cs.utexas.edu break; 10009104Shestness@cs.utexas.edu 10016657Snate@binkert.org case RFCR: 10026657Snate@binkert.org regs.rfcr = reg; 10036657Snate@binkert.org 10046657Snate@binkert.org rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 10058946Sandreas.hansson@arm.com acceptBroadcast = (reg & RFCR_AAB) ? true : false; 10068946Sandreas.hansson@arm.com acceptMulticast = (reg & RFCR_AAM) ? true : false; 10078946Sandreas.hansson@arm.com acceptUnicast = (reg & RFCR_AAU) ? true : false; 10087832Snate@binkert.org acceptPerfect = (reg & RFCR_APM) ? true : false; 10097832Snate@binkert.org acceptArp = (reg & RFCR_AARP) ? true : false; 10107007Snate@binkert.org multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 10118232Snate@binkert.org 10128229Snate@binkert.org#if 0 10138229Snate@binkert.org if (reg & RFCR_APAT) 10148229Snate@binkert.org panic("RFCR_APAT not implemented!\n"); 10159104Shestness@cs.utexas.edu#endif 10169104Shestness@cs.utexas.edu if (reg & RFCR_UHEN) 10179104Shestness@cs.utexas.edu panic("Unicast hash filtering not used by drivers!\n"); 10189104Shestness@cs.utexas.edu 10199104Shestness@cs.utexas.edu if (reg & RFCR_ULM) 10209104Shestness@cs.utexas.edu panic("RFCR_ULM not implemented!\n"); 10218229Snate@binkert.org 10226657Snate@binkert.org break; 10236657Snate@binkert.org 10246657Snate@binkert.org case RFDR: 10256657Snate@binkert.org rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 10267055Snate@binkert.org switch (rfaddr) { 10277055Snate@binkert.org case 0x000: 10287007Snate@binkert.org rom.perfectMatch[0] = (uint8_t)reg; 10297007Snate@binkert.org rom.perfectMatch[1] = (uint8_t)(reg >> 8); 10306657Snate@binkert.org break; 10316657Snate@binkert.org case 0x002: 10326657Snate@binkert.org rom.perfectMatch[2] = (uint8_t)reg; 10336657Snate@binkert.org rom.perfectMatch[3] = (uint8_t)(reg >> 8); 10346657Snate@binkert.org break; 10356657Snate@binkert.org case 0x004: 10367007Snate@binkert.org rom.perfectMatch[4] = (uint8_t)reg; 10377007Snate@binkert.org rom.perfectMatch[5] = (uint8_t)(reg >> 8); 10387007Snate@binkert.org break; 10397007Snate@binkert.org default: 10407007Snate@binkert.org 10416657Snate@binkert.org if (rfaddr >= FHASH_ADDR && 10426657Snate@binkert.org rfaddr < FHASH_ADDR + FHASH_SIZE) { 10436657Snate@binkert.org 10446657Snate@binkert.org // Only word-aligned writes supported 10456657Snate@binkert.org if (rfaddr % 2) 10466657Snate@binkert.org panic("unaligned write to filter hash table!"); 10476657Snate@binkert.org 10486657Snate@binkert.org rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 10496657Snate@binkert.org rom.filterHash[rfaddr - FHASH_ADDR + 1] 10506657Snate@binkert.org = (uint8_t)(reg >> 8); 10516657Snate@binkert.org break; 10526657Snate@binkert.org } 10537567SBrad.Beckmann@amd.com panic("writing RFDR for something other than pattern matching\ 10547567SBrad.Beckmann@amd.com or hashing! %#x\n", rfaddr); 10557567SBrad.Beckmann@amd.com } 10567567SBrad.Beckmann@amd.com 10576657Snate@binkert.org case BRAR: 10586657Snate@binkert.org regs.brar = reg; 10596657Snate@binkert.org break; 10606657Snate@binkert.org 10616657Snate@binkert.org case BRDR: 10626657Snate@binkert.org panic("the driver never uses BRDR, something is wrong!\n"); 10636657Snate@binkert.org 10646657Snate@binkert.org case SRR: 10656657Snate@binkert.org panic("SRR is read only register!\n"); 10666657Snate@binkert.org 10677007Snate@binkert.org case MIBC: 10686657Snate@binkert.org panic("the driver never uses MIBC, something is wrong!\n"); 10696657Snate@binkert.org 10706657Snate@binkert.org case VRCR: 10716657Snate@binkert.org regs.vrcr = reg; 10726657Snate@binkert.org break; 10736657Snate@binkert.org 10746657Snate@binkert.org case VTCR: 10756657Snate@binkert.org regs.vtcr = reg; 10766999Snate@binkert.org break; 10776657Snate@binkert.org 10786657Snate@binkert.org case VDR: 10796657Snate@binkert.org panic("the driver never uses VDR, something is wrong!\n"); 10806657Snate@binkert.org 10816657Snate@binkert.org case CCSR: 10826657Snate@binkert.org /* not going to implement clockrun stuff */ 10837832Snate@binkert.org regs.ccsr = reg; 10847832Snate@binkert.org break; 10857805Snilay@cs.wisc.edu 10867832Snate@binkert.org case TBICR: 10878232Snate@binkert.org regs.tbicr = reg; 10888232Snate@binkert.org if (reg & TBICR_MR_LOOPBACK) 10898229Snate@binkert.org panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 10908229Snate@binkert.org 10918229Snate@binkert.org if (reg & TBICR_MR_AN_ENABLE) { 10928229Snate@binkert.org regs.tanlpar = regs.tanar; 10936657Snate@binkert.org regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 10946657Snate@binkert.org } 10956657Snate@binkert.org 10966657Snate@binkert.org#if 0 10976657Snate@binkert.org if (reg & TBICR_MR_RESTART_AN) ; 10986657Snate@binkert.org#endif 10996657Snate@binkert.org 11006657Snate@binkert.org break; 11017007Snate@binkert.org 11027007Snate@binkert.org case TBISR: 11037839Snilay@cs.wisc.edu panic("TBISR is read only register!\n"); 11047839Snilay@cs.wisc.edu 11057839Snilay@cs.wisc.edu case TANAR: 11067839Snilay@cs.wisc.edu // Only write the writable bits 11077839Snilay@cs.wisc.edu regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 11087839Snilay@cs.wisc.edu regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 11097839Snilay@cs.wisc.edu 11107839Snilay@cs.wisc.edu // Pause capability unimplemented 11117839Snilay@cs.wisc.edu#if 0 11127839Snilay@cs.wisc.edu if (reg & TANAR_PS2) ; 11137007Snate@binkert.org if (reg & TANAR_PS1) ; 11146657Snate@binkert.org#endif 11157839Snilay@cs.wisc.edu 11167839Snilay@cs.wisc.edu break; 11178337Snilay@cs.wisc.edu 11187839Snilay@cs.wisc.edu case TANLPAR: 11198337Snilay@cs.wisc.edu panic("this should only be written to by the fake phy!\n"); 11207839Snilay@cs.wisc.edu 11218337Snilay@cs.wisc.edu case TANER: 11227839Snilay@cs.wisc.edu panic("TANER is read only register!\n"); 11238337Snilay@cs.wisc.edu 11247839Snilay@cs.wisc.edu case TESR: 11257839Snilay@cs.wisc.edu regs.tesr = reg; 11266657Snate@binkert.org break; 11276657Snate@binkert.org 11287780Snilay@cs.wisc.edu default: 11297780Snilay@cs.wisc.edu panic("invalid register access daddr=%#x", daddr); 11307780Snilay@cs.wisc.edu } 11317780Snilay@cs.wisc.edu } else { 11327780Snilay@cs.wisc.edu panic("Invalid Request Size"); 11337780Snilay@cs.wisc.edu } 11346657Snate@binkert.org pkt->result = Packet::Success; 11357007Snate@binkert.org return pioDelay; 11367839Snilay@cs.wisc.edu} 11377839Snilay@cs.wisc.edu 11387839Snilay@cs.wisc.eduvoid 11397839Snilay@cs.wisc.eduNSGigE::devIntrPost(uint32_t interrupts) 11407839Snilay@cs.wisc.edu{ 11417839Snilay@cs.wisc.edu if (interrupts & ISR_RESERVE) 11427839Snilay@cs.wisc.edu panic("Cannot set a reserved interrupt"); 11437839Snilay@cs.wisc.edu 11447839Snilay@cs.wisc.edu if (interrupts & ISR_NOIMPL) 11456657Snate@binkert.org warn("interrupt not implemented %#x\n", interrupts); 11467839Snilay@cs.wisc.edu 11476657Snate@binkert.org interrupts &= ISR_IMPL; 11487780Snilay@cs.wisc.edu regs.isr |= interrupts; 11497780Snilay@cs.wisc.edu 11507542SBrad.Beckmann@amd.com if (interrupts & regs.imr) { 11518266Sksewell@umich.edu if (interrupts & ISR_SWI) { 11528266Sksewell@umich.edu totalSwi++; 11538266Sksewell@umich.edu } 11548266Sksewell@umich.edu if (interrupts & ISR_RXIDLE) { 11558266Sksewell@umich.edu totalRxIdle++; 11568266Sksewell@umich.edu } 11576657Snate@binkert.org if (interrupts & ISR_RXOK) { 11587832Snate@binkert.org totalRxOk++; 11597839Snilay@cs.wisc.edu } 11607839Snilay@cs.wisc.edu if (interrupts & ISR_RXDESC) { 11618337Snilay@cs.wisc.edu totalRxDesc++; 11628341Snilay@cs.wisc.edu } 11637839Snilay@cs.wisc.edu if (interrupts & ISR_TXOK) { 11648337Snilay@cs.wisc.edu totalTxOk++; 11658341Snilay@cs.wisc.edu } 11667839Snilay@cs.wisc.edu if (interrupts & ISR_TXIDLE) { 11678337Snilay@cs.wisc.edu totalTxIdle++; 11688341Snilay@cs.wisc.edu } 11697839Snilay@cs.wisc.edu if (interrupts & ISR_TXDESC) { 11708337Snilay@cs.wisc.edu totalTxDesc++; 11718341Snilay@cs.wisc.edu } 11727839Snilay@cs.wisc.edu if (interrupts & ISR_RXORN) { 11737839Snilay@cs.wisc.edu totalRxOrn++; 11746657Snate@binkert.org } 11758266Sksewell@umich.edu } 11768266Sksewell@umich.edu 11778266Sksewell@umich.edu DPRINTF(EthernetIntr, 11788266Sksewell@umich.edu "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 11798266Sksewell@umich.edu interrupts, regs.isr, regs.imr); 11808266Sksewell@umich.edu 11816657Snate@binkert.org if ((regs.isr & regs.imr)) { 11827780Snilay@cs.wisc.edu Tick when = curTick; 11838266Sksewell@umich.edu if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 11848266Sksewell@umich.edu when += intrDelay; 11858266Sksewell@umich.edu cpuIntrPost(when); 11868266Sksewell@umich.edu } 11878266Sksewell@umich.edu} 11888266Sksewell@umich.edu 11896657Snate@binkert.org/* writing this interrupt counting stats inside this means that this function 11906657Snate@binkert.org is now limited to being used to clear all interrupts upon the kernel 11916657Snate@binkert.org reading isr and servicing. just telling you in case you were thinking 11926657Snate@binkert.org of expanding use. 11936657Snate@binkert.org*/ 11947007Snate@binkert.orgvoid 11957007Snate@binkert.orgNSGigE::devIntrClear(uint32_t interrupts) 11967007Snate@binkert.org{ 11977007Snate@binkert.org if (interrupts & ISR_RESERVE) 11987839Snilay@cs.wisc.edu panic("Cannot clear a reserved interrupt"); 11997839Snilay@cs.wisc.edu 12007839Snilay@cs.wisc.edu if (regs.isr & regs.imr & ISR_SWI) { 12017839Snilay@cs.wisc.edu postedSwi++; 12027839Snilay@cs.wisc.edu } 12037839Snilay@cs.wisc.edu if (regs.isr & regs.imr & ISR_RXIDLE) { 12047839Snilay@cs.wisc.edu postedRxIdle++; 12057839Snilay@cs.wisc.edu } 12067839Snilay@cs.wisc.edu if (regs.isr & regs.imr & ISR_RXOK) { 12077839Snilay@cs.wisc.edu postedRxOk++; 12087839Snilay@cs.wisc.edu } 12097007Snate@binkert.org if (regs.isr & regs.imr & ISR_RXDESC) { 12106657Snate@binkert.org postedRxDesc++; 12116657Snate@binkert.org } 12126657Snate@binkert.org if (regs.isr & regs.imr & ISR_TXOK) { 12136657Snate@binkert.org postedTxOk++; 12146657Snate@binkert.org } 12156657Snate@binkert.org if (regs.isr & regs.imr & ISR_TXIDLE) { 12166657Snate@binkert.org postedTxIdle++; 12176657Snate@binkert.org } 12186657Snate@binkert.org if (regs.isr & regs.imr & ISR_TXDESC) { 12196657Snate@binkert.org postedTxDesc++; 12206657Snate@binkert.org } 12216999Snate@binkert.org if (regs.isr & regs.imr & ISR_RXORN) { 12226657Snate@binkert.org postedRxOrn++; 12236657Snate@binkert.org } 12246657Snate@binkert.org 12256657Snate@binkert.org if (regs.isr & regs.imr & ISR_IMPL) 12266657Snate@binkert.org postedInterrupts++; 12276657Snate@binkert.org 12289104Shestness@cs.utexas.edu interrupts &= ~ISR_NOIMPL; 12296657Snate@binkert.org regs.isr &= ~interrupts; 12306657Snate@binkert.org 12316657Snate@binkert.org DPRINTF(EthernetIntr, 12326657Snate@binkert.org "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 12336657Snate@binkert.org interrupts, regs.isr, regs.imr); 12346657Snate@binkert.org 12356657Snate@binkert.org if (!(regs.isr & regs.imr)) 12367007Snate@binkert.org cpuIntrClear(); 12376657Snate@binkert.org} 12386657Snate@binkert.org 12396657Snate@binkert.orgvoid 12406657Snate@binkert.orgNSGigE::devIntrChangeMask() 12416657Snate@binkert.org{ 12426657Snate@binkert.org DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 12436657Snate@binkert.org regs.isr, regs.imr, regs.isr & regs.imr); 12446657Snate@binkert.org 12456657Snate@binkert.org if (regs.isr & regs.imr) 12466657Snate@binkert.org cpuIntrPost(curTick); 12476657Snate@binkert.org else 12489104Shestness@cs.utexas.edu cpuIntrClear(); 12499104Shestness@cs.utexas.edu} 12509104Shestness@cs.utexas.edu 12519104Shestness@cs.utexas.eduvoid 12526657Snate@binkert.orgNSGigE::cpuIntrPost(Tick when) 12536657Snate@binkert.org{ 12546657Snate@binkert.org // If the interrupt you want to post is later than an interrupt 12556657Snate@binkert.org // already scheduled, just let it post in the coming one and don't 12566657Snate@binkert.org // schedule another. 12576657Snate@binkert.org // HOWEVER, must be sure that the scheduled intrTick is in the 12586657Snate@binkert.org // future (this was formerly the source of a bug) 12596657Snate@binkert.org /** 12606657Snate@binkert.org * @todo this warning should be removed and the intrTick code should 12616657Snate@binkert.org * be fixed. 12627839Snilay@cs.wisc.edu */ 12637839Snilay@cs.wisc.edu assert(when >= curTick); 12647839Snilay@cs.wisc.edu assert(intrTick >= curTick || intrTick == 0); 12657839Snilay@cs.wisc.edu if (when > intrTick && intrTick != 0) { 12667839Snilay@cs.wisc.edu DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 12677839Snilay@cs.wisc.edu intrTick); 12687839Snilay@cs.wisc.edu return; 12697839Snilay@cs.wisc.edu } 12707839Snilay@cs.wisc.edu 12717839Snilay@cs.wisc.edu intrTick = when; 12727839Snilay@cs.wisc.edu if (intrTick < curTick) { 12737839Snilay@cs.wisc.edu debug_break(); 12746657Snate@binkert.org intrTick = curTick; 12756657Snate@binkert.org } 12766657Snate@binkert.org 12776657Snate@binkert.org DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 12786657Snate@binkert.org intrTick); 12796657Snate@binkert.org 12806657Snate@binkert.org if (intrEvent) 12816657Snate@binkert.org intrEvent->squash(); 12826657Snate@binkert.org intrEvent = new IntrEvent(this, true); 12836657Snate@binkert.org intrEvent->schedule(intrTick); 12846657Snate@binkert.org} 12856657Snate@binkert.org 12866657Snate@binkert.orgvoid 12876657Snate@binkert.orgNSGigE::cpuInterrupt() 12886657Snate@binkert.org{ 12896657Snate@binkert.org assert(intrTick == curTick); 12906657Snate@binkert.org 12916657Snate@binkert.org // Whether or not there's a pending interrupt, we don't care about 12926657Snate@binkert.org // it anymore 12936657Snate@binkert.org intrEvent = 0; 12946657Snate@binkert.org intrTick = 0; 12957805Snilay@cs.wisc.edu 12968159SBrad.Beckmann@amd.com // Don't send an interrupt if there's already one 12978159SBrad.Beckmann@amd.com if (cpuPendingIntr) { 12986657Snate@binkert.org DPRINTF(EthernetIntr, 12996657Snate@binkert.org "would send an interrupt now, but there's already pending\n"); 13006657Snate@binkert.org } else { 13016657Snate@binkert.org // Send interrupt 13026657Snate@binkert.org cpuPendingIntr = true; 13036657Snate@binkert.org 13047542SBrad.Beckmann@amd.com DPRINTF(EthernetIntr, "posting interrupt\n"); 13057542SBrad.Beckmann@amd.com intrPost(); 13067542SBrad.Beckmann@amd.com } 13077542SBrad.Beckmann@amd.com} 13087542SBrad.Beckmann@amd.com 13097542SBrad.Beckmann@amd.comvoid 13107542SBrad.Beckmann@amd.comNSGigE::cpuIntrClear() 13117542SBrad.Beckmann@amd.com{ 13127542SBrad.Beckmann@amd.com if (!cpuPendingIntr) 13137542SBrad.Beckmann@amd.com return; 13147542SBrad.Beckmann@amd.com 13157832Snate@binkert.org if (intrEvent) { 13167542SBrad.Beckmann@amd.com intrEvent->squash(); 13177542SBrad.Beckmann@amd.com intrEvent = 0; 13187542SBrad.Beckmann@amd.com } 13198229Snate@binkert.org 13207542SBrad.Beckmann@amd.com intrTick = 0; 13217542SBrad.Beckmann@amd.com 13227542SBrad.Beckmann@amd.com cpuPendingIntr = false; 13237542SBrad.Beckmann@amd.com 13247542SBrad.Beckmann@amd.com DPRINTF(EthernetIntr, "clearing interrupt\n"); 13257542SBrad.Beckmann@amd.com intrClear(); 13267542SBrad.Beckmann@amd.com} 13277542SBrad.Beckmann@amd.com 13287542SBrad.Beckmann@amd.combool 13297542SBrad.Beckmann@amd.comNSGigE::cpuIntrPending() const 13307542SBrad.Beckmann@amd.com{ return cpuPendingIntr; } 13317542SBrad.Beckmann@amd.com 13327542SBrad.Beckmann@amd.comvoid 13337542SBrad.Beckmann@amd.comNSGigE::txReset() 13347542SBrad.Beckmann@amd.com{ 13357542SBrad.Beckmann@amd.com 13367542SBrad.Beckmann@amd.com DPRINTF(Ethernet, "transmit reset\n"); 13377542SBrad.Beckmann@amd.com 13387542SBrad.Beckmann@amd.com CTDD = false; 13397542SBrad.Beckmann@amd.com txEnable = false;; 13407542SBrad.Beckmann@amd.com txFragPtr = 0; 13417542SBrad.Beckmann@amd.com assert(txDescCnt == 0); 13427542SBrad.Beckmann@amd.com txFifo.clear(); 13437542SBrad.Beckmann@amd.com txState = txIdle; 13447542SBrad.Beckmann@amd.com assert(txDmaState == dmaIdle); 13457542SBrad.Beckmann@amd.com} 13467542SBrad.Beckmann@amd.com 13477542SBrad.Beckmann@amd.comvoid 13487542SBrad.Beckmann@amd.comNSGigE::rxReset() 13497542SBrad.Beckmann@amd.com{ 13507542SBrad.Beckmann@amd.com DPRINTF(Ethernet, "receive reset\n"); 13517542SBrad.Beckmann@amd.com 13527542SBrad.Beckmann@amd.com CRDD = false; 13537542SBrad.Beckmann@amd.com assert(rxPktBytes == 0); 13547542SBrad.Beckmann@amd.com rxEnable = false; 13557542SBrad.Beckmann@amd.com rxFragPtr = 0; 13567542SBrad.Beckmann@amd.com assert(rxDescCnt == 0); 13577542SBrad.Beckmann@amd.com assert(rxDmaState == dmaIdle); 13587542SBrad.Beckmann@amd.com rxFifo.clear(); 13597542SBrad.Beckmann@amd.com rxState = rxIdle; 13607542SBrad.Beckmann@amd.com} 13617542SBrad.Beckmann@amd.com 13627542SBrad.Beckmann@amd.comvoid 13637542SBrad.Beckmann@amd.comNSGigE::regsReset() 13647542SBrad.Beckmann@amd.com{ 13657542SBrad.Beckmann@amd.com memset(®s, 0, sizeof(regs)); 13667542SBrad.Beckmann@amd.com regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 13677542SBrad.Beckmann@amd.com regs.mear = 0x12; 13687542SBrad.Beckmann@amd.com regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 13697542SBrad.Beckmann@amd.com // fill threshold to 32 bytes 13707542SBrad.Beckmann@amd.com regs.rxcfg = 0x4; // set drain threshold to 16 bytes 13717542SBrad.Beckmann@amd.com regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 13727542SBrad.Beckmann@amd.com regs.mibc = MIBC_FRZ; 13737542SBrad.Beckmann@amd.com regs.vdr = 0x81; // set the vlan tag type to 802.1q 13747542SBrad.Beckmann@amd.com regs.tesr = 0xc000; // TBI capable of both full and half duplex 13757542SBrad.Beckmann@amd.com regs.brar = 0xffffffff; 13767542SBrad.Beckmann@amd.com 13777542SBrad.Beckmann@amd.com extstsEnable = false; 13787542SBrad.Beckmann@amd.com acceptBroadcast = false; 13797542SBrad.Beckmann@amd.com acceptMulticast = false; 13807542SBrad.Beckmann@amd.com acceptUnicast = false; 13817542SBrad.Beckmann@amd.com acceptPerfect = false; 13827542SBrad.Beckmann@amd.com acceptArp = false; 13837542SBrad.Beckmann@amd.com} 13847542SBrad.Beckmann@amd.com 13857542SBrad.Beckmann@amd.combool 13867542SBrad.Beckmann@amd.comNSGigE::doRxDmaRead() 13877542SBrad.Beckmann@amd.com{ 13887542SBrad.Beckmann@amd.com assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 13897542SBrad.Beckmann@amd.com rxDmaState = dmaReading; 13907542SBrad.Beckmann@amd.com 13917542SBrad.Beckmann@amd.com if (dmaPending()) 13927542SBrad.Beckmann@amd.com rxDmaState = dmaReadWaiting; 13937542SBrad.Beckmann@amd.com else 13947542SBrad.Beckmann@amd.com dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 13957542SBrad.Beckmann@amd.com 13967542SBrad.Beckmann@amd.com return true; 13977542SBrad.Beckmann@amd.com} 13987542SBrad.Beckmann@amd.com 13997542SBrad.Beckmann@amd.comvoid 14006657Snate@binkert.orgNSGigE::rxDmaReadDone() 14016999Snate@binkert.org{ 14026657Snate@binkert.org assert(rxDmaState == dmaReading); 14036657Snate@binkert.org rxDmaState = dmaIdle; 14046657Snate@binkert.org 14056657Snate@binkert.org DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 14066657Snate@binkert.org rxDmaAddr, rxDmaLen); 14076657Snate@binkert.org DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 14087542SBrad.Beckmann@amd.com 14097542SBrad.Beckmann@amd.com // If the transmit state machine has a pending DMA, let it go first 14106657Snate@binkert.org if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 14117832Snate@binkert.org txKick(); 14127002Snate@binkert.org 14137002Snate@binkert.org rxKick(); 14148229Snate@binkert.org} 14158229Snate@binkert.org 14168608Snilay@cs.wisc.edubool 14176657Snate@binkert.orgNSGigE::doRxDmaWrite() 14187007Snate@binkert.org{ 14197007Snate@binkert.org assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 14206657Snate@binkert.org rxDmaState = dmaWriting; 14216657Snate@binkert.org 14226657Snate@binkert.org if (dmaPending()) 14236657Snate@binkert.org rxDmaState = dmaWriteWaiting; 14246657Snate@binkert.org else 14257542SBrad.Beckmann@amd.com dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 14267542SBrad.Beckmann@amd.com return true; 14277542SBrad.Beckmann@amd.com} 14286657Snate@binkert.org 14296657Snate@binkert.orgvoid 14306657Snate@binkert.orgNSGigE::rxDmaWriteDone() 14316657Snate@binkert.org{ 14326657Snate@binkert.org assert(rxDmaState == dmaWriting); 14336657Snate@binkert.org rxDmaState = dmaIdle; 14346657Snate@binkert.org 14356657Snate@binkert.org DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 14366657Snate@binkert.org rxDmaAddr, rxDmaLen); 14377007Snate@binkert.org DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 14386657Snate@binkert.org 14396657Snate@binkert.org // If the transmit state machine has a pending DMA, let it go first 14406657Snate@binkert.org if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 14416657Snate@binkert.org txKick(); 14426999Snate@binkert.org 14436657Snate@binkert.org rxKick(); 14446657Snate@binkert.org} 14456657Snate@binkert.org 14466657Snate@binkert.orgvoid 14476657Snate@binkert.orgNSGigE::rxKick() 14486657Snate@binkert.org{ 14497832Snate@binkert.org bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 14507832Snate@binkert.org 14516657Snate@binkert.org DPRINTF(EthernetSM, 14526657Snate@binkert.org "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 14536657Snate@binkert.org NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 14546657Snate@binkert.org 14556657Snate@binkert.org Addr link, bufptr; 14566657Snate@binkert.org uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 14576657Snate@binkert.org uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 14586657Snate@binkert.org 14596657Snate@binkert.org next: 14606657Snate@binkert.org if (clock) { 14616657Snate@binkert.org if (rxKickTick > curTick) { 14626657Snate@binkert.org DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 14636657Snate@binkert.org rxKickTick); 14646657Snate@binkert.org 14657007Snate@binkert.org goto exit; 14667007Snate@binkert.org } 14677007Snate@binkert.org 14686657Snate@binkert.org // Go to the next state machine clock tick. 14696657Snate@binkert.org rxKickTick = curTick + cycles(1); 14706657Snate@binkert.org } 14717007Snate@binkert.org 14727007Snate@binkert.org switch(rxDmaState) { 14737007Snate@binkert.org case dmaReadWaiting: 14746657Snate@binkert.org if (doRxDmaRead()) 14756657Snate@binkert.org goto exit; 14766657Snate@binkert.org break; 14776657Snate@binkert.org case dmaWriteWaiting: 14786657Snate@binkert.org if (doRxDmaWrite()) 14796657Snate@binkert.org goto exit; 14806657Snate@binkert.org break; 14816657Snate@binkert.org default: 14826657Snate@binkert.org break; 14836657Snate@binkert.org } 14846657Snate@binkert.org 14857007Snate@binkert.org link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 14867007Snate@binkert.org bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 14876657Snate@binkert.org 14886657Snate@binkert.org // see state machine from spec for details 14896657Snate@binkert.org // the way this works is, if you finish work on one state and can 14906657Snate@binkert.org // go directly to another, you do that through jumping to the 14916657Snate@binkert.org // label "next". however, if you have intermediate work, like DMA 14927007Snate@binkert.org // so that you can't go to the next state yet, you go to exit and 14937007Snate@binkert.org // exit the loop. however, when the DMA is done it will trigger 14947007Snate@binkert.org // an event and come back to this loop. 14956657Snate@binkert.org switch (rxState) { 14966657Snate@binkert.org case rxIdle: 14976657Snate@binkert.org if (!rxEnable) { 14987007Snate@binkert.org DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 14997542SBrad.Beckmann@amd.com goto exit; 15007542SBrad.Beckmann@amd.com } 15016657Snate@binkert.org 15027542SBrad.Beckmann@amd.com if (CRDD) { 15037542SBrad.Beckmann@amd.com rxState = rxDescRefr; 15047002Snate@binkert.org 15057542SBrad.Beckmann@amd.com rxDmaAddr = regs.rxdp & 0x3fffffff; 15067542SBrad.Beckmann@amd.com rxDmaData = 15077542SBrad.Beckmann@amd.com is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 15087542SBrad.Beckmann@amd.com rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 15096657Snate@binkert.org rxDmaFree = dmaDescFree; 15107542SBrad.Beckmann@amd.com 15117542SBrad.Beckmann@amd.com descDmaReads++; 15127542SBrad.Beckmann@amd.com descDmaRdBytes += rxDmaLen; 15137542SBrad.Beckmann@amd.com 15147542SBrad.Beckmann@amd.com if (doRxDmaRead()) 15157542SBrad.Beckmann@amd.com goto exit; 15167542SBrad.Beckmann@amd.com } else { 15177542SBrad.Beckmann@amd.com rxState = rxDescRead; 15186657Snate@binkert.org 15196657Snate@binkert.org rxDmaAddr = regs.rxdp & 0x3fffffff; 15206657Snate@binkert.org rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 15216657Snate@binkert.org rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 15226657Snate@binkert.org rxDmaFree = dmaDescFree; 15236657Snate@binkert.org 15247007Snate@binkert.org descDmaReads++; 15256999Snate@binkert.org descDmaRdBytes += rxDmaLen; 15267007Snate@binkert.org 15277007Snate@binkert.org if (doRxDmaRead()) 15287007Snate@binkert.org goto exit; 15297007Snate@binkert.org } 15307007Snate@binkert.org break; 15317007Snate@binkert.org 15326657Snate@binkert.org case rxDescRefr: 15336657Snate@binkert.org if (rxDmaState != dmaIdle) 15346657Snate@binkert.org goto exit; 15356657Snate@binkert.org 15366657Snate@binkert.org rxState = rxAdvance; 15376657Snate@binkert.org break; 15386657Snate@binkert.org 15396657Snate@binkert.org case rxDescRead: 15406657Snate@binkert.org if (rxDmaState != dmaIdle) 15416657Snate@binkert.org goto exit; 15426657Snate@binkert.org 15436657Snate@binkert.org DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 15446657Snate@binkert.org regs.rxdp & 0x3fffffff); 15456657Snate@binkert.org DPRINTF(EthernetDesc, 15466657Snate@binkert.org "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 15476657Snate@binkert.org link, bufptr, cmdsts, extsts); 15486657Snate@binkert.org 15496657Snate@binkert.org if (cmdsts & CMDSTS_OWN) { 15506657Snate@binkert.org devIntrPost(ISR_RXIDLE); 15516657Snate@binkert.org rxState = rxIdle; 15526657Snate@binkert.org goto exit; 15536657Snate@binkert.org } else { 15546657Snate@binkert.org rxState = rxFifoBlock; 15556657Snate@binkert.org rxFragPtr = bufptr; 15566657Snate@binkert.org rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 15576657Snate@binkert.org } 15586657Snate@binkert.org break; 15596657Snate@binkert.org 15606657Snate@binkert.org case rxFifoBlock: 15616999Snate@binkert.org if (!rxPacket) { 15626657Snate@binkert.org /** 15636657Snate@binkert.org * @todo in reality, we should be able to start processing 15647007Snate@binkert.org * the packet as it arrives, and not have to wait for the 15657007Snate@binkert.org * full packet ot be in the receive fifo. 15666657Snate@binkert.org */ 15676657Snate@binkert.org if (rxFifo.empty()) 15686657Snate@binkert.org goto exit; 15696657Snate@binkert.org 15706657Snate@binkert.org DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 15716657Snate@binkert.org 15726657Snate@binkert.org // If we don't have a packet, grab a new one from the fifo. 15736657Snate@binkert.org rxPacket = rxFifo.front(); 15746657Snate@binkert.org rxPktBytes = rxPacket->length; 15756657Snate@binkert.org rxPacketBufPtr = rxPacket->data; 15766657Snate@binkert.org 15776657Snate@binkert.org#if TRACING_ON 15786657Snate@binkert.org if (DTRACE(Ethernet)) { 15796657Snate@binkert.org IpPtr ip(rxPacket); 15806657Snate@binkert.org if (ip) { 15816657Snate@binkert.org DPRINTF(Ethernet, "ID is %d\n", ip->id()); 15826657Snate@binkert.org TcpPtr tcp(ip); 15836657Snate@binkert.org if (tcp) { 15846657Snate@binkert.org DPRINTF(Ethernet, 15856657Snate@binkert.org "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 15866657Snate@binkert.org tcp->sport(), tcp->dport(), tcp->seq(), 15876657Snate@binkert.org tcp->ack()); 15886657Snate@binkert.org } 15896657Snate@binkert.org } 15906657Snate@binkert.org } 15916657Snate@binkert.org#endif 15926657Snate@binkert.org 15936657Snate@binkert.org // sanity check - i think the driver behaves like this 15946657Snate@binkert.org assert(rxDescCnt >= rxPktBytes); 15956657Snate@binkert.org rxFifo.pop(); 15966657Snate@binkert.org } 15976657Snate@binkert.org 15986657Snate@binkert.org 15996657Snate@binkert.org // dont' need the && rxDescCnt > 0 if driver sanity check 16006657Snate@binkert.org // above holds 16016657Snate@binkert.org if (rxPktBytes > 0) { 16026657Snate@binkert.org rxState = rxFragWrite; 16036657Snate@binkert.org // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 16046657Snate@binkert.org // check holds 16056657Snate@binkert.org rxXferLen = rxPktBytes; 16066657Snate@binkert.org 16076657Snate@binkert.org rxDmaAddr = rxFragPtr & 0x3fffffff; 16086657Snate@binkert.org rxDmaData = rxPacketBufPtr; 16096657Snate@binkert.org rxDmaLen = rxXferLen; 16106657Snate@binkert.org rxDmaFree = dmaDataFree; 16116657Snate@binkert.org 16126657Snate@binkert.org if (doRxDmaWrite()) 16136657Snate@binkert.org goto exit; 16146657Snate@binkert.org 16156657Snate@binkert.org } else { 16166657Snate@binkert.org rxState = rxDescWrite; 16176657Snate@binkert.org 16186657Snate@binkert.org //if (rxPktBytes == 0) { /* packet is done */ 16196657Snate@binkert.org assert(rxPktBytes == 0); 16206657Snate@binkert.org DPRINTF(EthernetSM, "done with receiving packet\n"); 16216657Snate@binkert.org 16226657Snate@binkert.org cmdsts |= CMDSTS_OWN; 16236657Snate@binkert.org cmdsts &= ~CMDSTS_MORE; 16246657Snate@binkert.org cmdsts |= CMDSTS_OK; 16256657Snate@binkert.org cmdsts &= 0xffff0000; 16266657Snate@binkert.org cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 16276657Snate@binkert.org 16286657Snate@binkert.org#if 0 16296657Snate@binkert.org /* 16306657Snate@binkert.org * all the driver uses these are for its own stats keeping 16316657Snate@binkert.org * which we don't care about, aren't necessary for 16326657Snate@binkert.org * functionality and doing this would just slow us down. 16336657Snate@binkert.org * if they end up using this in a later version for 16346657Snate@binkert.org * functional purposes, just undef 16356657Snate@binkert.org */ 16366657Snate@binkert.org if (rxFilterEnable) { 16376657Snate@binkert.org cmdsts &= ~CMDSTS_DEST_MASK; 16386657Snate@binkert.org const EthAddr &dst = rxFifoFront()->dst(); 16396657Snate@binkert.org if (dst->unicast()) 16406657Snate@binkert.org cmdsts |= CMDSTS_DEST_SELF; 16416657Snate@binkert.org if (dst->multicast()) 16426657Snate@binkert.org cmdsts |= CMDSTS_DEST_MULTI; 16436657Snate@binkert.org if (dst->broadcast()) 16446657Snate@binkert.org cmdsts |= CMDSTS_DEST_MASK; 16456657Snate@binkert.org } 16466657Snate@binkert.org#endif 16476657Snate@binkert.org 16486657Snate@binkert.org IpPtr ip(rxPacket); 16496657Snate@binkert.org if (extstsEnable && ip) { 16506657Snate@binkert.org extsts |= EXTSTS_IPPKT; 16516657Snate@binkert.org rxIpChecksums++; 16526657Snate@binkert.org if (cksum(ip) != 0) { 16536657Snate@binkert.org DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 16547007Snate@binkert.org extsts |= EXTSTS_IPERR; 16556657Snate@binkert.org } 16566657Snate@binkert.org TcpPtr tcp(ip); 16576657Snate@binkert.org UdpPtr udp(ip); 16586657Snate@binkert.org if (tcp) { 16596657Snate@binkert.org extsts |= EXTSTS_TCPPKT; 16606657Snate@binkert.org rxTcpChecksums++; 16616657Snate@binkert.org if (cksum(tcp) != 0) { 16627007Snate@binkert.org DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 16636657Snate@binkert.org extsts |= EXTSTS_TCPERR; 16646657Snate@binkert.org 16656657Snate@binkert.org } 16666657Snate@binkert.org } else if (udp) { 16676657Snate@binkert.org extsts |= EXTSTS_UDPPKT; 16686657Snate@binkert.org rxUdpChecksums++; 16696657Snate@binkert.org if (cksum(udp) != 0) { 16706657Snate@binkert.org DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 16716657Snate@binkert.org extsts |= EXTSTS_UDPERR; 16726657Snate@binkert.org } 16736657Snate@binkert.org } 16746657Snate@binkert.org } 16756657Snate@binkert.org rxPacket = 0; 16766657Snate@binkert.org 16776657Snate@binkert.org /* 16787007Snate@binkert.org * the driver seems to always receive into desc buffers 16796657Snate@binkert.org * of size 1514, so you never have a pkt that is split 16806657Snate@binkert.org * into multiple descriptors on the receive side, so 16816657Snate@binkert.org * i don't implement that case, hence the assert above. 16826657Snate@binkert.org */ 16836657Snate@binkert.org 16846657Snate@binkert.org DPRINTF(EthernetDesc, 16856657Snate@binkert.org "rxDesc: addr=%08x writeback cmdsts extsts\n", 16866657Snate@binkert.org regs.rxdp & 0x3fffffff); 16876657Snate@binkert.org DPRINTF(EthernetDesc, 16886657Snate@binkert.org "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 16896657Snate@binkert.org link, bufptr, cmdsts, extsts); 16906657Snate@binkert.org 16916657Snate@binkert.org rxDmaAddr = regs.rxdp & 0x3fffffff; 16926657Snate@binkert.org rxDmaData = &cmdsts; 16936657Snate@binkert.org if (is64bit) { 16946657Snate@binkert.org rxDmaAddr += offsetof(ns_desc64, cmdsts); 16956657Snate@binkert.org rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 16966657Snate@binkert.org } else { 16976657Snate@binkert.org rxDmaAddr += offsetof(ns_desc32, cmdsts); 16986657Snate@binkert.org rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 16996657Snate@binkert.org } 17006657Snate@binkert.org rxDmaFree = dmaDescFree; 1701 1702 descDmaWrites++; 1703 descDmaWrBytes += rxDmaLen; 1704 1705 if (doRxDmaWrite()) 1706 goto exit; 1707 } 1708 break; 1709 1710 case rxFragWrite: 1711 if (rxDmaState != dmaIdle) 1712 goto exit; 1713 1714 rxPacketBufPtr += rxXferLen; 1715 rxFragPtr += rxXferLen; 1716 rxPktBytes -= rxXferLen; 1717 1718 rxState = rxFifoBlock; 1719 break; 1720 1721 case rxDescWrite: 1722 if (rxDmaState != dmaIdle) 1723 goto exit; 1724 1725 assert(cmdsts & CMDSTS_OWN); 1726 1727 assert(rxPacket == 0); 1728 devIntrPost(ISR_RXOK); 1729 1730 if (cmdsts & CMDSTS_INTR) 1731 devIntrPost(ISR_RXDESC); 1732 1733 if (!rxEnable) { 1734 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1735 rxState = rxIdle; 1736 goto exit; 1737 } else 1738 rxState = rxAdvance; 1739 break; 1740 1741 case rxAdvance: 1742 if (link == 0) { 1743 devIntrPost(ISR_RXIDLE); 1744 rxState = rxIdle; 1745 CRDD = true; 1746 goto exit; 1747 } else { 1748 if (rxDmaState != dmaIdle) 1749 goto exit; 1750 rxState = rxDescRead; 1751 regs.rxdp = link; 1752 CRDD = false; 1753 1754 rxDmaAddr = regs.rxdp & 0x3fffffff; 1755 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1756 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1757 rxDmaFree = dmaDescFree; 1758 1759 if (doRxDmaRead()) 1760 goto exit; 1761 } 1762 break; 1763 1764 default: 1765 panic("Invalid rxState!"); 1766 } 1767 1768 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1769 NsRxStateStrings[rxState]); 1770 goto next; 1771 1772 exit: 1773 /** 1774 * @todo do we want to schedule a future kick? 1775 */ 1776 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1777 NsRxStateStrings[rxState]); 1778 1779 if (clock && !rxKickEvent.scheduled()) 1780 rxKickEvent.schedule(rxKickTick); 1781} 1782 1783void 1784NSGigE::transmit() 1785{ 1786 if (txFifo.empty()) { 1787 DPRINTF(Ethernet, "nothing to transmit\n"); 1788 return; 1789 } 1790 1791 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1792 txFifo.size()); 1793 if (interface->sendPacket(txFifo.front())) { 1794#if TRACING_ON 1795 if (DTRACE(Ethernet)) { 1796 IpPtr ip(txFifo.front()); 1797 if (ip) { 1798 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1799 TcpPtr tcp(ip); 1800 if (tcp) { 1801 DPRINTF(Ethernet, 1802 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1803 tcp->sport(), tcp->dport(), tcp->seq(), 1804 tcp->ack()); 1805 } 1806 } 1807 } 1808#endif 1809 1810 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1811 txBytes += txFifo.front()->length; 1812 txPackets++; 1813 1814 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1815 txFifo.avail()); 1816 txFifo.pop(); 1817 1818 /* 1819 * normally do a writeback of the descriptor here, and ONLY 1820 * after that is done, send this interrupt. but since our 1821 * stuff never actually fails, just do this interrupt here, 1822 * otherwise the code has to stray from this nice format. 1823 * besides, it's functionally the same. 1824 */ 1825 devIntrPost(ISR_TXOK); 1826 } 1827 1828 if (!txFifo.empty() && !txEvent.scheduled()) { 1829 DPRINTF(Ethernet, "reschedule transmit\n"); 1830 txEvent.schedule(curTick + retryTime); 1831 } 1832} 1833 1834bool 1835NSGigE::doTxDmaRead() 1836{ 1837 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1838 txDmaState = dmaReading; 1839 1840 if (dmaPending()) 1841 txDmaState = dmaReadWaiting; 1842 else 1843 dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 1844 1845 return true; 1846} 1847 1848void 1849NSGigE::txDmaReadDone() 1850{ 1851 assert(txDmaState == dmaReading); 1852 txDmaState = dmaIdle; 1853 1854 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1855 txDmaAddr, txDmaLen); 1856 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1857 1858 // If the receive state machine has a pending DMA, let it go first 1859 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1860 rxKick(); 1861 1862 txKick(); 1863} 1864 1865bool 1866NSGigE::doTxDmaWrite() 1867{ 1868 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1869 txDmaState = dmaWriting; 1870 1871 if (dmaPending()) 1872 txDmaState = dmaWriteWaiting; 1873 else 1874 dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1875 return true; 1876} 1877 1878void 1879NSGigE::txDmaWriteDone() 1880{ 1881 assert(txDmaState == dmaWriting); 1882 txDmaState = dmaIdle; 1883 1884 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1885 txDmaAddr, txDmaLen); 1886 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1887 1888 // If the receive state machine has a pending DMA, let it go first 1889 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1890 rxKick(); 1891 1892 txKick(); 1893} 1894 1895void 1896NSGigE::txKick() 1897{ 1898 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1899 1900 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 1901 NsTxStateStrings[txState], is64bit ? 64 : 32); 1902 1903 Addr link, bufptr; 1904 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 1905 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1906 1907 next: 1908 if (clock) { 1909 if (txKickTick > curTick) { 1910 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1911 txKickTick); 1912 goto exit; 1913 } 1914 1915 // Go to the next state machine clock tick. 1916 txKickTick = curTick + cycles(1); 1917 } 1918 1919 switch(txDmaState) { 1920 case dmaReadWaiting: 1921 if (doTxDmaRead()) 1922 goto exit; 1923 break; 1924 case dmaWriteWaiting: 1925 if (doTxDmaWrite()) 1926 goto exit; 1927 break; 1928 default: 1929 break; 1930 } 1931 1932 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 1933 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1934 switch (txState) { 1935 case txIdle: 1936 if (!txEnable) { 1937 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1938 goto exit; 1939 } 1940 1941 if (CTDD) { 1942 txState = txDescRefr; 1943 1944 txDmaAddr = regs.txdp & 0x3fffffff; 1945 txDmaData = 1946 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 1947 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1948 txDmaFree = dmaDescFree; 1949 1950 descDmaReads++; 1951 descDmaRdBytes += txDmaLen; 1952 1953 if (doTxDmaRead()) 1954 goto exit; 1955 1956 } else { 1957 txState = txDescRead; 1958 1959 txDmaAddr = regs.txdp & 0x3fffffff; 1960 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 1961 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1962 txDmaFree = dmaDescFree; 1963 1964 descDmaReads++; 1965 descDmaRdBytes += txDmaLen; 1966 1967 if (doTxDmaRead()) 1968 goto exit; 1969 } 1970 break; 1971 1972 case txDescRefr: 1973 if (txDmaState != dmaIdle) 1974 goto exit; 1975 1976 txState = txAdvance; 1977 break; 1978 1979 case txDescRead: 1980 if (txDmaState != dmaIdle) 1981 goto exit; 1982 1983 DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 1984 regs.txdp & 0x3fffffff); 1985 DPRINTF(EthernetDesc, 1986 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 1987 link, bufptr, cmdsts, extsts); 1988 1989 if (cmdsts & CMDSTS_OWN) { 1990 txState = txFifoBlock; 1991 txFragPtr = bufptr; 1992 txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1993 } else { 1994 devIntrPost(ISR_TXIDLE); 1995 txState = txIdle; 1996 goto exit; 1997 } 1998 break; 1999 2000 case txFifoBlock: 2001 if (!txPacket) { 2002 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2003 txPacket = new EthPacketData(16384); 2004 txPacketBufPtr = txPacket->data; 2005 } 2006 2007 if (txDescCnt == 0) { 2008 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 2009 if (cmdsts & CMDSTS_MORE) { 2010 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2011 txState = txDescWrite; 2012 2013 cmdsts &= ~CMDSTS_OWN; 2014 2015 txDmaAddr = regs.txdp & 0x3fffffff; 2016 txDmaData = &cmdsts; 2017 if (is64bit) { 2018 txDmaAddr += offsetof(ns_desc64, cmdsts); 2019 txDmaLen = sizeof(txDesc64.cmdsts); 2020 } else { 2021 txDmaAddr += offsetof(ns_desc32, cmdsts); 2022 txDmaLen = sizeof(txDesc32.cmdsts); 2023 } 2024 txDmaFree = dmaDescFree; 2025 2026 if (doTxDmaWrite()) 2027 goto exit; 2028 2029 } else { /* this packet is totally done */ 2030 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2031 /* deal with the the packet that just finished */ 2032 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2033 IpPtr ip(txPacket); 2034 if (extsts & EXTSTS_UDPPKT) { 2035 UdpPtr udp(ip); 2036 udp->sum(0); 2037 udp->sum(cksum(udp)); 2038 txUdpChecksums++; 2039 } else if (extsts & EXTSTS_TCPPKT) { 2040 TcpPtr tcp(ip); 2041 tcp->sum(0); 2042 tcp->sum(cksum(tcp)); 2043 txTcpChecksums++; 2044 } 2045 if (extsts & EXTSTS_IPPKT) { 2046 ip->sum(0); 2047 ip->sum(cksum(ip)); 2048 txIpChecksums++; 2049 } 2050 } 2051 2052 txPacket->length = txPacketBufPtr - txPacket->data; 2053 // this is just because the receive can't handle a 2054 // packet bigger want to make sure 2055 if (txPacket->length > 1514) 2056 panic("transmit packet too large, %s > 1514\n", 2057 txPacket->length); 2058 2059#ifndef NDEBUG 2060 bool success = 2061#endif 2062 txFifo.push(txPacket); 2063 assert(success); 2064 2065 /* 2066 * this following section is not tqo spec, but 2067 * functionally shouldn't be any different. normally, 2068 * the chip will wait til the transmit has occurred 2069 * before writing back the descriptor because it has 2070 * to wait to see that it was successfully transmitted 2071 * to decide whether to set CMDSTS_OK or not. 2072 * however, in the simulator since it is always 2073 * successfully transmitted, and writing it exactly to 2074 * spec would complicate the code, we just do it here 2075 */ 2076 2077 cmdsts &= ~CMDSTS_OWN; 2078 cmdsts |= CMDSTS_OK; 2079 2080 DPRINTF(EthernetDesc, 2081 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2082 cmdsts, extsts); 2083 2084 txDmaFree = dmaDescFree; 2085 txDmaAddr = regs.txdp & 0x3fffffff; 2086 txDmaData = &cmdsts; 2087 if (is64bit) { 2088 txDmaAddr += offsetof(ns_desc64, cmdsts); 2089 txDmaLen = 2090 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 2091 } else { 2092 txDmaAddr += offsetof(ns_desc32, cmdsts); 2093 txDmaLen = 2094 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 2095 } 2096 2097 descDmaWrites++; 2098 descDmaWrBytes += txDmaLen; 2099 2100 transmit(); 2101 txPacket = 0; 2102 2103 if (!txEnable) { 2104 DPRINTF(EthernetSM, "halting TX state machine\n"); 2105 txState = txIdle; 2106 goto exit; 2107 } else 2108 txState = txAdvance; 2109 2110 if (doTxDmaWrite()) 2111 goto exit; 2112 } 2113 } else { 2114 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2115 if (!txFifo.full()) { 2116 txState = txFragRead; 2117 2118 /* 2119 * The number of bytes transferred is either whatever 2120 * is left in the descriptor (txDescCnt), or if there 2121 * is not enough room in the fifo, just whatever room 2122 * is left in the fifo 2123 */ 2124 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2125 2126 txDmaAddr = txFragPtr & 0x3fffffff; 2127 txDmaData = txPacketBufPtr; 2128 txDmaLen = txXferLen; 2129 txDmaFree = dmaDataFree; 2130 2131 if (doTxDmaRead()) 2132 goto exit; 2133 } else { 2134 txState = txFifoBlock; 2135 transmit(); 2136 2137 goto exit; 2138 } 2139 2140 } 2141 break; 2142 2143 case txFragRead: 2144 if (txDmaState != dmaIdle) 2145 goto exit; 2146 2147 txPacketBufPtr += txXferLen; 2148 txFragPtr += txXferLen; 2149 txDescCnt -= txXferLen; 2150 txFifo.reserve(txXferLen); 2151 2152 txState = txFifoBlock; 2153 break; 2154 2155 case txDescWrite: 2156 if (txDmaState != dmaIdle) 2157 goto exit; 2158 2159 if (cmdsts & CMDSTS_INTR) 2160 devIntrPost(ISR_TXDESC); 2161 2162 if (!txEnable) { 2163 DPRINTF(EthernetSM, "halting TX state machine\n"); 2164 txState = txIdle; 2165 goto exit; 2166 } else 2167 txState = txAdvance; 2168 break; 2169 2170 case txAdvance: 2171 if (link == 0) { 2172 devIntrPost(ISR_TXIDLE); 2173 txState = txIdle; 2174 goto exit; 2175 } else { 2176 if (txDmaState != dmaIdle) 2177 goto exit; 2178 txState = txDescRead; 2179 regs.txdp = link; 2180 CTDD = false; 2181 2182 txDmaAddr = link & 0x3fffffff; 2183 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 2184 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 2185 txDmaFree = dmaDescFree; 2186 2187 if (doTxDmaRead()) 2188 goto exit; 2189 } 2190 break; 2191 2192 default: 2193 panic("invalid state"); 2194 } 2195 2196 DPRINTF(EthernetSM, "entering next txState=%s\n", 2197 NsTxStateStrings[txState]); 2198 goto next; 2199 2200 exit: 2201 /** 2202 * @todo do we want to schedule a future kick? 2203 */ 2204 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2205 NsTxStateStrings[txState]); 2206 2207 if (clock && !txKickEvent.scheduled()) 2208 txKickEvent.schedule(txKickTick); 2209} 2210 2211/** 2212 * Advance the EEPROM state machine 2213 * Called on rising edge of EEPROM clock bit in MEAR 2214 */ 2215void 2216NSGigE::eepromKick() 2217{ 2218 switch (eepromState) { 2219 2220 case eepromStart: 2221 2222 // Wait for start bit 2223 if (regs.mear & MEAR_EEDI) { 2224 // Set up to get 2 opcode bits 2225 eepromState = eepromGetOpcode; 2226 eepromBitsToRx = 2; 2227 eepromOpcode = 0; 2228 } 2229 break; 2230 2231 case eepromGetOpcode: 2232 eepromOpcode <<= 1; 2233 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 2234 --eepromBitsToRx; 2235 2236 // Done getting opcode 2237 if (eepromBitsToRx == 0) { 2238 if (eepromOpcode != EEPROM_READ) 2239 panic("only EEPROM reads are implemented!"); 2240 2241 // Set up to get address 2242 eepromState = eepromGetAddress; 2243 eepromBitsToRx = 6; 2244 eepromAddress = 0; 2245 } 2246 break; 2247 2248 case eepromGetAddress: 2249 eepromAddress <<= 1; 2250 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 2251 --eepromBitsToRx; 2252 2253 // Done getting address 2254 if (eepromBitsToRx == 0) { 2255 2256 if (eepromAddress >= EEPROM_SIZE) 2257 panic("EEPROM read access out of range!"); 2258 2259 switch (eepromAddress) { 2260 2261 case EEPROM_PMATCH2_ADDR: 2262 eepromData = rom.perfectMatch[5]; 2263 eepromData <<= 8; 2264 eepromData += rom.perfectMatch[4]; 2265 break; 2266 2267 case EEPROM_PMATCH1_ADDR: 2268 eepromData = rom.perfectMatch[3]; 2269 eepromData <<= 8; 2270 eepromData += rom.perfectMatch[2]; 2271 break; 2272 2273 case EEPROM_PMATCH0_ADDR: 2274 eepromData = rom.perfectMatch[1]; 2275 eepromData <<= 8; 2276 eepromData += rom.perfectMatch[0]; 2277 break; 2278 2279 default: 2280 panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 2281 } 2282 // Set up to read data 2283 eepromState = eepromRead; 2284 eepromBitsToRx = 16; 2285 2286 // Clear data in bit 2287 regs.mear &= ~MEAR_EEDI; 2288 } 2289 break; 2290 2291 case eepromRead: 2292 // Clear Data Out bit 2293 regs.mear &= ~MEAR_EEDO; 2294 // Set bit to value of current EEPROM bit 2295 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 2296 2297 eepromData <<= 1; 2298 --eepromBitsToRx; 2299 2300 // All done 2301 if (eepromBitsToRx == 0) { 2302 eepromState = eepromStart; 2303 } 2304 break; 2305 2306 default: 2307 panic("invalid EEPROM state"); 2308 } 2309 2310} 2311 2312void 2313NSGigE::transferDone() 2314{ 2315 if (txFifo.empty()) { 2316 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2317 return; 2318 } 2319 2320 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2321 2322 if (txEvent.scheduled()) 2323 txEvent.reschedule(curTick + cycles(1)); 2324 else 2325 txEvent.schedule(curTick + cycles(1)); 2326} 2327 2328bool 2329NSGigE::rxFilter(const EthPacketPtr &packet) 2330{ 2331 EthPtr eth = packet; 2332 bool drop = true; 2333 string type; 2334 2335 const EthAddr &dst = eth->dst(); 2336 if (dst.unicast()) { 2337 // If we're accepting all unicast addresses 2338 if (acceptUnicast) 2339 drop = false; 2340 2341 // If we make a perfect match 2342 if (acceptPerfect && dst == rom.perfectMatch) 2343 drop = false; 2344 2345 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2346 drop = false; 2347 2348 } else if (dst.broadcast()) { 2349 // if we're accepting broadcasts 2350 if (acceptBroadcast) 2351 drop = false; 2352 2353 } else if (dst.multicast()) { 2354 // if we're accepting all multicasts 2355 if (acceptMulticast) 2356 drop = false; 2357 2358 // Multicast hashing faked - all packets accepted 2359 if (multicastHashEnable) 2360 drop = false; 2361 } 2362 2363 if (drop) { 2364 DPRINTF(Ethernet, "rxFilter drop\n"); 2365 DDUMP(EthernetData, packet->data, packet->length); 2366 } 2367 2368 return drop; 2369} 2370 2371bool 2372NSGigE::recvPacket(EthPacketPtr packet) 2373{ 2374 rxBytes += packet->length; 2375 rxPackets++; 2376 2377 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2378 rxFifo.avail()); 2379 2380 if (!rxEnable) { 2381 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2382 return true; 2383 } 2384 2385 if (!rxFilterEnable) { 2386 DPRINTF(Ethernet, 2387 "receive packet filtering disabled . . . packet dropped\n"); 2388 return true; 2389 } 2390 2391 if (rxFilter(packet)) { 2392 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2393 return true; 2394 } 2395 2396 if (rxFifo.avail() < packet->length) { 2397#if TRACING_ON 2398 IpPtr ip(packet); 2399 TcpPtr tcp(ip); 2400 if (ip) { 2401 DPRINTF(Ethernet, 2402 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2403 ip->id()); 2404 if (tcp) { 2405 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2406 } 2407 } 2408#endif 2409 droppedPackets++; 2410 devIntrPost(ISR_RXORN); 2411 return false; 2412 } 2413 2414 rxFifo.push(packet); 2415 2416 rxKick(); 2417 return true; 2418} 2419 2420//===================================================================== 2421// 2422// 2423void 2424NSGigE::serialize(ostream &os) 2425{ 2426 // Serialize the PciDev base class 2427 PciDev::serialize(os); 2428 2429 /* 2430 * Finalize any DMA events now. 2431 */ 2432 // @todo will mem system save pending dma? 2433 2434 /* 2435 * Serialize the device registers 2436 */ 2437 SERIALIZE_SCALAR(regs.command); 2438 SERIALIZE_SCALAR(regs.config); 2439 SERIALIZE_SCALAR(regs.mear); 2440 SERIALIZE_SCALAR(regs.ptscr); 2441 SERIALIZE_SCALAR(regs.isr); 2442 SERIALIZE_SCALAR(regs.imr); 2443 SERIALIZE_SCALAR(regs.ier); 2444 SERIALIZE_SCALAR(regs.ihr); 2445 SERIALIZE_SCALAR(regs.txdp); 2446 SERIALIZE_SCALAR(regs.txdp_hi); 2447 SERIALIZE_SCALAR(regs.txcfg); 2448 SERIALIZE_SCALAR(regs.gpior); 2449 SERIALIZE_SCALAR(regs.rxdp); 2450 SERIALIZE_SCALAR(regs.rxdp_hi); 2451 SERIALIZE_SCALAR(regs.rxcfg); 2452 SERIALIZE_SCALAR(regs.pqcr); 2453 SERIALIZE_SCALAR(regs.wcsr); 2454 SERIALIZE_SCALAR(regs.pcr); 2455 SERIALIZE_SCALAR(regs.rfcr); 2456 SERIALIZE_SCALAR(regs.rfdr); 2457 SERIALIZE_SCALAR(regs.brar); 2458 SERIALIZE_SCALAR(regs.brdr); 2459 SERIALIZE_SCALAR(regs.srr); 2460 SERIALIZE_SCALAR(regs.mibc); 2461 SERIALIZE_SCALAR(regs.vrcr); 2462 SERIALIZE_SCALAR(regs.vtcr); 2463 SERIALIZE_SCALAR(regs.vdr); 2464 SERIALIZE_SCALAR(regs.ccsr); 2465 SERIALIZE_SCALAR(regs.tbicr); 2466 SERIALIZE_SCALAR(regs.tbisr); 2467 SERIALIZE_SCALAR(regs.tanar); 2468 SERIALIZE_SCALAR(regs.tanlpar); 2469 SERIALIZE_SCALAR(regs.taner); 2470 SERIALIZE_SCALAR(regs.tesr); 2471 2472 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2473 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2474 2475 SERIALIZE_SCALAR(ioEnable); 2476 2477 /* 2478 * Serialize the data Fifos 2479 */ 2480 rxFifo.serialize("rxFifo", os); 2481 txFifo.serialize("txFifo", os); 2482 2483 /* 2484 * Serialize the various helper variables 2485 */ 2486 bool txPacketExists = txPacket; 2487 SERIALIZE_SCALAR(txPacketExists); 2488 if (txPacketExists) { 2489 txPacket->length = txPacketBufPtr - txPacket->data; 2490 txPacket->serialize("txPacket", os); 2491 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2492 SERIALIZE_SCALAR(txPktBufPtr); 2493 } 2494 2495 bool rxPacketExists = rxPacket; 2496 SERIALIZE_SCALAR(rxPacketExists); 2497 if (rxPacketExists) { 2498 rxPacket->serialize("rxPacket", os); 2499 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2500 SERIALIZE_SCALAR(rxPktBufPtr); 2501 } 2502 2503 SERIALIZE_SCALAR(txXferLen); 2504 SERIALIZE_SCALAR(rxXferLen); 2505 2506 /* 2507 * Serialize Cached Descriptors 2508 */ 2509 SERIALIZE_SCALAR(rxDesc64.link); 2510 SERIALIZE_SCALAR(rxDesc64.bufptr); 2511 SERIALIZE_SCALAR(rxDesc64.cmdsts); 2512 SERIALIZE_SCALAR(rxDesc64.extsts); 2513 SERIALIZE_SCALAR(txDesc64.link); 2514 SERIALIZE_SCALAR(txDesc64.bufptr); 2515 SERIALIZE_SCALAR(txDesc64.cmdsts); 2516 SERIALIZE_SCALAR(txDesc64.extsts); 2517 SERIALIZE_SCALAR(rxDesc32.link); 2518 SERIALIZE_SCALAR(rxDesc32.bufptr); 2519 SERIALIZE_SCALAR(rxDesc32.cmdsts); 2520 SERIALIZE_SCALAR(rxDesc32.extsts); 2521 SERIALIZE_SCALAR(txDesc32.link); 2522 SERIALIZE_SCALAR(txDesc32.bufptr); 2523 SERIALIZE_SCALAR(txDesc32.cmdsts); 2524 SERIALIZE_SCALAR(txDesc32.extsts); 2525 SERIALIZE_SCALAR(extstsEnable); 2526 2527 /* 2528 * Serialize tx state machine 2529 */ 2530 int txState = this->txState; 2531 SERIALIZE_SCALAR(txState); 2532 SERIALIZE_SCALAR(txEnable); 2533 SERIALIZE_SCALAR(CTDD); 2534 SERIALIZE_SCALAR(txFragPtr); 2535 SERIALIZE_SCALAR(txDescCnt); 2536 int txDmaState = this->txDmaState; 2537 SERIALIZE_SCALAR(txDmaState); 2538 SERIALIZE_SCALAR(txKickTick); 2539 2540 /* 2541 * Serialize rx state machine 2542 */ 2543 int rxState = this->rxState; 2544 SERIALIZE_SCALAR(rxState); 2545 SERIALIZE_SCALAR(rxEnable); 2546 SERIALIZE_SCALAR(CRDD); 2547 SERIALIZE_SCALAR(rxPktBytes); 2548 SERIALIZE_SCALAR(rxFragPtr); 2549 SERIALIZE_SCALAR(rxDescCnt); 2550 int rxDmaState = this->rxDmaState; 2551 SERIALIZE_SCALAR(rxDmaState); 2552 SERIALIZE_SCALAR(rxKickTick); 2553 2554 /* 2555 * Serialize EEPROM state machine 2556 */ 2557 int eepromState = this->eepromState; 2558 SERIALIZE_SCALAR(eepromState); 2559 SERIALIZE_SCALAR(eepromClk); 2560 SERIALIZE_SCALAR(eepromBitsToRx); 2561 SERIALIZE_SCALAR(eepromOpcode); 2562 SERIALIZE_SCALAR(eepromAddress); 2563 SERIALIZE_SCALAR(eepromData); 2564 2565 /* 2566 * If there's a pending transmit, store the time so we can 2567 * reschedule it later 2568 */ 2569 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2570 SERIALIZE_SCALAR(transmitTick); 2571 2572 /* 2573 * receive address filter settings 2574 */ 2575 SERIALIZE_SCALAR(rxFilterEnable); 2576 SERIALIZE_SCALAR(acceptBroadcast); 2577 SERIALIZE_SCALAR(acceptMulticast); 2578 SERIALIZE_SCALAR(acceptUnicast); 2579 SERIALIZE_SCALAR(acceptPerfect); 2580 SERIALIZE_SCALAR(acceptArp); 2581 SERIALIZE_SCALAR(multicastHashEnable); 2582 2583 /* 2584 * Keep track of pending interrupt status. 2585 */ 2586 SERIALIZE_SCALAR(intrTick); 2587 SERIALIZE_SCALAR(cpuPendingIntr); 2588 Tick intrEventTick = 0; 2589 if (intrEvent) 2590 intrEventTick = intrEvent->when(); 2591 SERIALIZE_SCALAR(intrEventTick); 2592 2593} 2594 2595void 2596NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2597{ 2598 // Unserialize the PciDev base class 2599 PciDev::unserialize(cp, section); 2600 2601 UNSERIALIZE_SCALAR(regs.command); 2602 UNSERIALIZE_SCALAR(regs.config); 2603 UNSERIALIZE_SCALAR(regs.mear); 2604 UNSERIALIZE_SCALAR(regs.ptscr); 2605 UNSERIALIZE_SCALAR(regs.isr); 2606 UNSERIALIZE_SCALAR(regs.imr); 2607 UNSERIALIZE_SCALAR(regs.ier); 2608 UNSERIALIZE_SCALAR(regs.ihr); 2609 UNSERIALIZE_SCALAR(regs.txdp); 2610 UNSERIALIZE_SCALAR(regs.txdp_hi); 2611 UNSERIALIZE_SCALAR(regs.txcfg); 2612 UNSERIALIZE_SCALAR(regs.gpior); 2613 UNSERIALIZE_SCALAR(regs.rxdp); 2614 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2615 UNSERIALIZE_SCALAR(regs.rxcfg); 2616 UNSERIALIZE_SCALAR(regs.pqcr); 2617 UNSERIALIZE_SCALAR(regs.wcsr); 2618 UNSERIALIZE_SCALAR(regs.pcr); 2619 UNSERIALIZE_SCALAR(regs.rfcr); 2620 UNSERIALIZE_SCALAR(regs.rfdr); 2621 UNSERIALIZE_SCALAR(regs.brar); 2622 UNSERIALIZE_SCALAR(regs.brdr); 2623 UNSERIALIZE_SCALAR(regs.srr); 2624 UNSERIALIZE_SCALAR(regs.mibc); 2625 UNSERIALIZE_SCALAR(regs.vrcr); 2626 UNSERIALIZE_SCALAR(regs.vtcr); 2627 UNSERIALIZE_SCALAR(regs.vdr); 2628 UNSERIALIZE_SCALAR(regs.ccsr); 2629 UNSERIALIZE_SCALAR(regs.tbicr); 2630 UNSERIALIZE_SCALAR(regs.tbisr); 2631 UNSERIALIZE_SCALAR(regs.tanar); 2632 UNSERIALIZE_SCALAR(regs.tanlpar); 2633 UNSERIALIZE_SCALAR(regs.taner); 2634 UNSERIALIZE_SCALAR(regs.tesr); 2635 2636 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2637 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2638 2639 UNSERIALIZE_SCALAR(ioEnable); 2640 2641 /* 2642 * unserialize the data fifos 2643 */ 2644 rxFifo.unserialize("rxFifo", cp, section); 2645 txFifo.unserialize("txFifo", cp, section); 2646 2647 /* 2648 * unserialize the various helper variables 2649 */ 2650 bool txPacketExists; 2651 UNSERIALIZE_SCALAR(txPacketExists); 2652 if (txPacketExists) { 2653 txPacket = new EthPacketData(16384); 2654 txPacket->unserialize("txPacket", cp, section); 2655 uint32_t txPktBufPtr; 2656 UNSERIALIZE_SCALAR(txPktBufPtr); 2657 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2658 } else 2659 txPacket = 0; 2660 2661 bool rxPacketExists; 2662 UNSERIALIZE_SCALAR(rxPacketExists); 2663 rxPacket = 0; 2664 if (rxPacketExists) { 2665 rxPacket = new EthPacketData(16384); 2666 rxPacket->unserialize("rxPacket", cp, section); 2667 uint32_t rxPktBufPtr; 2668 UNSERIALIZE_SCALAR(rxPktBufPtr); 2669 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2670 } else 2671 rxPacket = 0; 2672 2673 UNSERIALIZE_SCALAR(txXferLen); 2674 UNSERIALIZE_SCALAR(rxXferLen); 2675 2676 /* 2677 * Unserialize Cached Descriptors 2678 */ 2679 UNSERIALIZE_SCALAR(rxDesc64.link); 2680 UNSERIALIZE_SCALAR(rxDesc64.bufptr); 2681 UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 2682 UNSERIALIZE_SCALAR(rxDesc64.extsts); 2683 UNSERIALIZE_SCALAR(txDesc64.link); 2684 UNSERIALIZE_SCALAR(txDesc64.bufptr); 2685 UNSERIALIZE_SCALAR(txDesc64.cmdsts); 2686 UNSERIALIZE_SCALAR(txDesc64.extsts); 2687 UNSERIALIZE_SCALAR(rxDesc32.link); 2688 UNSERIALIZE_SCALAR(rxDesc32.bufptr); 2689 UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 2690 UNSERIALIZE_SCALAR(rxDesc32.extsts); 2691 UNSERIALIZE_SCALAR(txDesc32.link); 2692 UNSERIALIZE_SCALAR(txDesc32.bufptr); 2693 UNSERIALIZE_SCALAR(txDesc32.cmdsts); 2694 UNSERIALIZE_SCALAR(txDesc32.extsts); 2695 UNSERIALIZE_SCALAR(extstsEnable); 2696 2697 /* 2698 * unserialize tx state machine 2699 */ 2700 int txState; 2701 UNSERIALIZE_SCALAR(txState); 2702 this->txState = (TxState) txState; 2703 UNSERIALIZE_SCALAR(txEnable); 2704 UNSERIALIZE_SCALAR(CTDD); 2705 UNSERIALIZE_SCALAR(txFragPtr); 2706 UNSERIALIZE_SCALAR(txDescCnt); 2707 int txDmaState; 2708 UNSERIALIZE_SCALAR(txDmaState); 2709 this->txDmaState = (DmaState) txDmaState; 2710 UNSERIALIZE_SCALAR(txKickTick); 2711 if (txKickTick) 2712 txKickEvent.schedule(txKickTick); 2713 2714 /* 2715 * unserialize rx state machine 2716 */ 2717 int rxState; 2718 UNSERIALIZE_SCALAR(rxState); 2719 this->rxState = (RxState) rxState; 2720 UNSERIALIZE_SCALAR(rxEnable); 2721 UNSERIALIZE_SCALAR(CRDD); 2722 UNSERIALIZE_SCALAR(rxPktBytes); 2723 UNSERIALIZE_SCALAR(rxFragPtr); 2724 UNSERIALIZE_SCALAR(rxDescCnt); 2725 int rxDmaState; 2726 UNSERIALIZE_SCALAR(rxDmaState); 2727 this->rxDmaState = (DmaState) rxDmaState; 2728 UNSERIALIZE_SCALAR(rxKickTick); 2729 if (rxKickTick) 2730 rxKickEvent.schedule(rxKickTick); 2731 2732 /* 2733 * Unserialize EEPROM state machine 2734 */ 2735 int eepromState; 2736 UNSERIALIZE_SCALAR(eepromState); 2737 this->eepromState = (EEPROMState) eepromState; 2738 UNSERIALIZE_SCALAR(eepromClk); 2739 UNSERIALIZE_SCALAR(eepromBitsToRx); 2740 UNSERIALIZE_SCALAR(eepromOpcode); 2741 UNSERIALIZE_SCALAR(eepromAddress); 2742 UNSERIALIZE_SCALAR(eepromData); 2743 2744 /* 2745 * If there's a pending transmit, reschedule it now 2746 */ 2747 Tick transmitTick; 2748 UNSERIALIZE_SCALAR(transmitTick); 2749 if (transmitTick) 2750 txEvent.schedule(curTick + transmitTick); 2751 2752 /* 2753 * unserialize receive address filter settings 2754 */ 2755 UNSERIALIZE_SCALAR(rxFilterEnable); 2756 UNSERIALIZE_SCALAR(acceptBroadcast); 2757 UNSERIALIZE_SCALAR(acceptMulticast); 2758 UNSERIALIZE_SCALAR(acceptUnicast); 2759 UNSERIALIZE_SCALAR(acceptPerfect); 2760 UNSERIALIZE_SCALAR(acceptArp); 2761 UNSERIALIZE_SCALAR(multicastHashEnable); 2762 2763 /* 2764 * Keep track of pending interrupt status. 2765 */ 2766 UNSERIALIZE_SCALAR(intrTick); 2767 UNSERIALIZE_SCALAR(cpuPendingIntr); 2768 Tick intrEventTick; 2769 UNSERIALIZE_SCALAR(intrEventTick); 2770 if (intrEventTick) { 2771 intrEvent = new IntrEvent(this, true); 2772 intrEvent->schedule(intrEventTick); 2773 } 2774} 2775 2776BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2777 2778 SimObjectParam<EtherInt *> peer; 2779 SimObjectParam<NSGigE *> device; 2780 2781END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2782 2783BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2784 2785 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2786 INIT_PARAM(device, "Ethernet device of this interface") 2787 2788END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2789 2790CREATE_SIM_OBJECT(NSGigEInt) 2791{ 2792 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2793 2794 EtherInt *p = (EtherInt *)peer; 2795 if (p) { 2796 dev_int->setPeer(p); 2797 p->setPeer(dev_int); 2798 } 2799 2800 return dev_int; 2801} 2802 2803REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2804 2805 2806BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2807 2808 SimObjectParam<System *> system; 2809 SimObjectParam<Platform *> platform; 2810 SimObjectParam<PciConfigAll *> configspace; 2811 SimObjectParam<PciConfigData *> configdata; 2812 Param<uint32_t> pci_bus; 2813 Param<uint32_t> pci_dev; 2814 Param<uint32_t> pci_func; 2815 Param<Tick> pio_latency; 2816 2817 Param<Tick> clock; 2818 Param<bool> dma_desc_free; 2819 Param<bool> dma_data_free; 2820 Param<Tick> dma_read_delay; 2821 Param<Tick> dma_write_delay; 2822 Param<Tick> dma_read_factor; 2823 Param<Tick> dma_write_factor; 2824 Param<bool> dma_no_allocate; 2825 Param<Tick> intr_delay; 2826 2827 Param<Tick> rx_delay; 2828 Param<Tick> tx_delay; 2829 Param<uint32_t> rx_fifo_size; 2830 Param<uint32_t> tx_fifo_size; 2831 2832 Param<bool> rx_filter; 2833 Param<string> hardware_address; 2834 Param<bool> rx_thread; 2835 Param<bool> tx_thread; 2836 Param<bool> rss; 2837 2838END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2839 2840BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2841 2842 INIT_PARAM(system, "System pointer"), 2843 INIT_PARAM(platform, "Platform pointer"), 2844 INIT_PARAM(configspace, "PCI Configspace"), 2845 INIT_PARAM(configdata, "PCI Config data"), 2846 INIT_PARAM(pci_bus, "PCI bus ID"), 2847 INIT_PARAM(pci_dev, "PCI device number"), 2848 INIT_PARAM(pci_func, "PCI function code"), 2849 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2850 INIT_PARAM(clock, "State machine cycle time"), 2851 2852 INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), 2853 INIT_PARAM(dma_data_free, "DMA of Data is free"), 2854 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 2855 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 2856 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 2857 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 2858 INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), 2859 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2860 2861 INIT_PARAM(rx_delay, "Receive Delay"), 2862 INIT_PARAM(tx_delay, "Transmit Delay"), 2863 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 2864 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 2865 2866 INIT_PARAM(rx_filter, "Enable Receive Filter"), 2867 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 2868 INIT_PARAM(rx_thread, ""), 2869 INIT_PARAM(tx_thread, ""), 2870 INIT_PARAM(rss, "") 2871 2872END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2873 2874 2875CREATE_SIM_OBJECT(NSGigE) 2876{ 2877 NSGigE::Params *params = new NSGigE::Params; 2878 2879 params->name = getInstanceName(); 2880 params->platform = platform; 2881 params->system = system; 2882 params->configSpace = configspace; 2883 params->configData = configdata; 2884 params->busNum = pci_bus; 2885 params->deviceNum = pci_dev; 2886 params->functionNum = pci_func; 2887 params->pio_delay = pio_latency; 2888 2889 params->clock = clock; 2890 params->dma_desc_free = dma_desc_free; 2891 params->dma_data_free = dma_data_free; 2892 params->dma_read_delay = dma_read_delay; 2893 params->dma_write_delay = dma_write_delay; 2894 params->dma_read_factor = dma_read_factor; 2895 params->dma_write_factor = dma_write_factor; 2896 params->dma_no_allocate = dma_no_allocate; 2897 params->pio_delay = pio_latency; 2898 params->intr_delay = intr_delay; 2899 2900 params->rx_delay = rx_delay; 2901 params->tx_delay = tx_delay; 2902 params->rx_fifo_size = rx_fifo_size; 2903 params->tx_fifo_size = tx_fifo_size; 2904 2905 params->rx_filter = rx_filter; 2906 params->eaddr = hardware_address; 2907 params->rx_thread = rx_thread; 2908 params->tx_thread = tx_thread; 2909 params->rss = rss; 2910 2911 return new NSGigE(params); 2912} 2913 2914REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2915