ns_gige.cc revision 1762
19814Sandreas.hansson@arm.com/* 22292SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 310333Smitch.hayenga@arm.com * All rights reserved. 410239Sbinhpham@cs.rutgers.edu * 57597Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without 67597Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are 77597Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright 87597Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer; 97597Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright 107597Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the 117597Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution; 127597Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its 137597Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from 147597Sminkyu.jeong@arm.com * this software without specific prior written permission. 157597Sminkyu.jeong@arm.com * 162292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272292SN/A */ 282292SN/A 292292SN/A/** @file 302292SN/A * Device module for modelling the National Semiconductor 312292SN/A * DP83820 ethernet controller. Does not support priority queueing 322292SN/A */ 332292SN/A#include <cstdio> 342292SN/A#include <deque> 352292SN/A#include <string> 362292SN/A 372292SN/A#include "base/inet.hh" 382292SN/A#include "cpu/exec_context.hh" 392292SN/A#include "dev/etherlink.hh" 402292SN/A#include "dev/ns_gige.hh" 412689Sktlim@umich.edu#include "dev/pciconfigall.hh" 422689Sktlim@umich.edu#include "mem/bus/bus.hh" 432689Sktlim@umich.edu#include "mem/bus/dma_interface.hh" 442292SN/A#include "mem/bus/pio_interface.hh" 452292SN/A#include "mem/bus/pio_interface_impl.hh" 469944Smatt.horsnell@ARM.com#include "mem/functional/memory_control.hh" 479944Smatt.horsnell@ARM.com#include "mem/functional/physical.hh" 489944Smatt.horsnell@ARM.com#include "sim/builder.hh" 498591Sgblack@eecs.umich.edu#include "sim/debug.hh" 503326Sktlim@umich.edu#include "sim/host.hh" 518229Snate@binkert.org#include "sim/stats.hh" 526658Snate@binkert.org#include "targetarch/vtophys.hh" 538887Sgeoffrey.blake@arm.com 542907Sktlim@umich.educonst char *NsRxStateStrings[] = 552292SN/A{ 568232Snate@binkert.org "rxIdle", 578232Snate@binkert.org "rxDescRefr", 588232Snate@binkert.org "rxDescRead", 599527SMatt.Horsnell@arm.com "rxFifoBlock", 602722Sktlim@umich.edu "rxFragWrite", 612669Sktlim@umich.edu "rxDescWrite", 622292SN/A "rxAdvance" 632669Sktlim@umich.edu}; 642678Sktlim@umich.edu 652678Sktlim@umich.educonst char *NsTxStateStrings[] = 668581Ssteve.reinhardt@amd.com{ 678581Ssteve.reinhardt@amd.com "txIdle", 682292SN/A "txDescRefr", 692292SN/A "txDescRead", 702292SN/A "txFifoBlock", 712669Sktlim@umich.edu "txFragRead", 722292SN/A "txDescWrite", 732678Sktlim@umich.edu "txAdvance" 742292SN/A}; 759444SAndreas.Sandberg@ARM.com 769444SAndreas.Sandberg@ARM.comconst char *NsDmaState[] = 779444SAndreas.Sandberg@ARM.com{ 784319Sktlim@umich.edu "dmaIdle", 794319Sktlim@umich.edu "dmaReading", 804319Sktlim@umich.edu "dmaWriting", 814319Sktlim@umich.edu "dmaReadWaiting", 824319Sktlim@umich.edu "dmaWriteWaiting" 832678Sktlim@umich.edu}; 842678Sktlim@umich.edu 852292SN/Ausing namespace std; 862678Sktlim@umich.eduusing namespace Net; 872678Sktlim@umich.edu 885336Shines@cs.fsu.edu/////////////////////////////////////////////////////////////////////// 892678Sktlim@umich.edu// 904873Sstever@eecs.umich.edu// NSGigE PCI Device 912678Sktlim@umich.edu// 922292SN/ANSGigE::NSGigE(Params *p) 932678Sktlim@umich.edu : PciDev(p), ioEnable(false), 942678Sktlim@umich.edu txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 952678Sktlim@umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 962678Sktlim@umich.edu txXferLen(0), rxXferLen(0), clock(p->clock), 972678Sktlim@umich.edu txState(txIdle), txEnable(false), CTDD(false), 982678Sktlim@umich.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 997852SMatt.Horsnell@arm.com rxEnable(false), CRDD(false), rxPktBytes(0), 1007852SMatt.Horsnell@arm.com rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1012344SN/A rxDmaReadEvent(this), rxDmaWriteEvent(this), 10210333Smitch.hayenga@arm.com txDmaReadEvent(this), txDmaWriteEvent(this), 10310333Smitch.hayenga@arm.com dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 10410333Smitch.hayenga@arm.com txDelay(p->tx_delay), rxDelay(p->rx_delay), 10510333Smitch.hayenga@arm.com rxKickTick(0), txKickTick(0), 10610333Smitch.hayenga@arm.com txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 10710333Smitch.hayenga@arm.com acceptMulticast(false), acceptUnicast(false), 10810333Smitch.hayenga@arm.com acceptPerfect(false), acceptArp(false), 10910333Smitch.hayenga@arm.com physmem(p->pmem), intrTick(0), cpuPendingIntr(false), 1102678Sktlim@umich.edu intrEvent(0), interface(0) 1116974Stjones1@inf.ed.ac.uk{ 1126974Stjones1@inf.ed.ac.uk if (p->header_bus) { 1136974Stjones1@inf.ed.ac.uk pioInterface = newPioInterface(name(), p->hier, 1146974Stjones1@inf.ed.ac.uk p->header_bus, this, 1156974Stjones1@inf.ed.ac.uk &NSGigE::cacheAccess); 1169444SAndreas.Sandberg@ARM.com 11710327Smitch.hayenga@arm.com pioLatency = p->pio_latency * p->header_bus->clockRate; 1182678Sktlim@umich.edu 1196974Stjones1@inf.ed.ac.uk if (p->payload_bus) 1206974Stjones1@inf.ed.ac.uk dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1216974Stjones1@inf.ed.ac.uk p->header_bus, 1226974Stjones1@inf.ed.ac.uk p->payload_bus, 1, 1236974Stjones1@inf.ed.ac.uk p->dma_no_allocate); 1246974Stjones1@inf.ed.ac.uk else 1252678Sktlim@umich.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1262678Sktlim@umich.edu p->header_bus, 1272678Sktlim@umich.edu p->header_bus, 1, 1282678Sktlim@umich.edu p->dma_no_allocate); 1292678Sktlim@umich.edu } else if (p->payload_bus) { 1302344SN/A pioInterface = newPioInterface(name(), p->hier, 1312307SN/A p->payload_bus, this, 1326974Stjones1@inf.ed.ac.uk &NSGigE::cacheAccess); 1336974Stjones1@inf.ed.ac.uk 1346974Stjones1@inf.ed.ac.uk pioLatency = p->pio_latency * p->payload_bus->clockRate; 1356974Stjones1@inf.ed.ac.uk 13610020Smatt.horsnell@ARM.com dmaInterface = new DMAInterface<Bus>(name() + ".dma", 13710020Smatt.horsnell@ARM.com p->payload_bus, 13810023Smatt.horsnell@ARM.com p->payload_bus, 1, 13910023Smatt.horsnell@ARM.com p->dma_no_allocate); 1402678Sktlim@umich.edu } 1412292SN/A 1422292SN/A 1432292SN/A intrDelay = p->intr_delay; 1442292SN/A dmaReadDelay = p->dma_read_delay; 1458545Ssaidi@eecs.umich.edu dmaWriteDelay = p->dma_write_delay; 14611243Spau.cabre@metempsy.com dmaReadFactor = p->dma_read_factor; 14711243Spau.cabre@metempsy.com dmaWriteFactor = p->dma_write_factor; 1482292SN/A 1492292SN/A regsReset(); 1502292SN/A memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1512292SN/A} 1522292SN/A 1535529Snate@binkert.orgNSGigE::~NSGigE() 1545529Snate@binkert.org{} 1555529Snate@binkert.org 1562292SN/Avoid 1574329Sktlim@umich.eduNSGigE::regStats() 1584329Sktlim@umich.edu{ 1594329Sktlim@umich.edu txBytes 1602907Sktlim@umich.edu .name(name() + ".txBytes") 1612907Sktlim@umich.edu .desc("Bytes Transmitted") 1622292SN/A .prereq(txBytes) 1632292SN/A ; 16410175SMitch.Hayenga@ARM.com 16510175SMitch.Hayenga@ARM.com rxBytes 1662329SN/A .name(name() + ".rxBytes") 1672329SN/A .desc("Bytes Received") 1682329SN/A .prereq(rxBytes) 1692292SN/A ; 1709936SFaissal.Sleiman@arm.com 1719936SFaissal.Sleiman@arm.com txPackets 1729936SFaissal.Sleiman@arm.com .name(name() + ".txPackets") 1739936SFaissal.Sleiman@arm.com .desc("Number of Packets Transmitted") 1742292SN/A .prereq(txBytes) 1752292SN/A ; 1762292SN/A 1778199SAli.Saidi@ARM.com rxPackets 1788199SAli.Saidi@ARM.com .name(name() + ".rxPackets") 1799444SAndreas.Sandberg@ARM.com .desc("Number of Packets Received") 1809444SAndreas.Sandberg@ARM.com .prereq(rxBytes) 1819444SAndreas.Sandberg@ARM.com ; 1829444SAndreas.Sandberg@ARM.com 1839444SAndreas.Sandberg@ARM.com txIpChecksums 1849444SAndreas.Sandberg@ARM.com .name(name() + ".txIpChecksums") 1859444SAndreas.Sandberg@ARM.com .desc("Number of tx IP Checksums done by device") 1869444SAndreas.Sandberg@ARM.com .precision(0) 1879444SAndreas.Sandberg@ARM.com .prereq(txBytes) 1889444SAndreas.Sandberg@ARM.com ; 1899444SAndreas.Sandberg@ARM.com 1909444SAndreas.Sandberg@ARM.com rxIpChecksums 1918199SAli.Saidi@ARM.com .name(name() + ".rxIpChecksums") 1922292SN/A .desc("Number of rx IP Checksums done by device") 1932292SN/A .precision(0) 1942292SN/A .prereq(rxBytes) 1952292SN/A ; 1962292SN/A 1972292SN/A txTcpChecksums 1983492Sktlim@umich.edu .name(name() + ".txTcpChecksums") 1992329SN/A .desc("Number of tx TCP Checksums done by device") 2002292SN/A .precision(0) 2019444SAndreas.Sandberg@ARM.com .prereq(txBytes) 2029444SAndreas.Sandberg@ARM.com ; 2039814Sandreas.hansson@arm.com 2042292SN/A rxTcpChecksums 2052292SN/A .name(name() + ".rxTcpChecksums") 2062292SN/A .desc("Number of rx TCP Checksums done by device") 2072292SN/A .precision(0) 2082292SN/A .prereq(rxBytes) 2092292SN/A ; 2102292SN/A 2112292SN/A txUdpChecksums 2122292SN/A .name(name() + ".txUdpChecksums") 21310386Sandreas.hansson@arm.com .desc("Number of tx UDP Checksums done by device") 2142292SN/A .precision(0) 2152292SN/A .prereq(txBytes) 2162292SN/A ; 2172292SN/A 2182292SN/A rxUdpChecksums 2192727Sktlim@umich.edu .name(name() + ".rxUdpChecksums") 2202727Sktlim@umich.edu .desc("Number of rx UDP Checksums done by device") 2212727Sktlim@umich.edu .precision(0) 2222727Sktlim@umich.edu .prereq(rxBytes) 2232727Sktlim@umich.edu ; 2242727Sktlim@umich.edu 2252727Sktlim@umich.edu descDmaReads 2262727Sktlim@umich.edu .name(name() + ".descDMAReads") 2272727Sktlim@umich.edu .desc("Number of descriptors the device read w/ DMA") 2282727Sktlim@umich.edu .precision(0) 2292727Sktlim@umich.edu ; 2302727Sktlim@umich.edu 2312727Sktlim@umich.edu descDmaWrites 2322727Sktlim@umich.edu .name(name() + ".descDMAWrites") 2332727Sktlim@umich.edu .desc("Number of descriptors the device wrote w/ DMA") 2342727Sktlim@umich.edu .precision(0) 2352727Sktlim@umich.edu ; 2362727Sktlim@umich.edu 2372361SN/A descDmaRdBytes 2382361SN/A .name(name() + ".descDmaReadBytes") 2392361SN/A .desc("number of descriptor bytes read w/ DMA") 2402361SN/A .precision(0) 2412727Sktlim@umich.edu ; 2422727Sktlim@umich.edu 2432727Sktlim@umich.edu descDmaWrBytes 2442727Sktlim@umich.edu .name(name() + ".descDmaWriteBytes") 2452727Sktlim@umich.edu .desc("number of descriptor bytes write w/ DMA") 2462727Sktlim@umich.edu .precision(0) 2472727Sktlim@umich.edu ; 2482727Sktlim@umich.edu 2492727Sktlim@umich.edu txBandwidth 2502727Sktlim@umich.edu .name(name() + ".txBandwidth") 2512727Sktlim@umich.edu .desc("Transmit Bandwidth (bits/s)") 2522727Sktlim@umich.edu .precision(0) 2532727Sktlim@umich.edu .prereq(txBytes) 2542727Sktlim@umich.edu ; 2552727Sktlim@umich.edu 2562727Sktlim@umich.edu rxBandwidth 2572727Sktlim@umich.edu .name(name() + ".rxBandwidth") 2582727Sktlim@umich.edu .desc("Receive Bandwidth (bits/s)") 2592727Sktlim@umich.edu .precision(0) 2602727Sktlim@umich.edu .prereq(rxBytes) 2612727Sktlim@umich.edu ; 2622727Sktlim@umich.edu 2632727Sktlim@umich.edu totBandwidth 2648922Swilliam.wang@arm.com .name(name() + ".totBandwidth") 2654329Sktlim@umich.edu .desc("Total Bandwidth (bits/s)") 2664329Sktlim@umich.edu .precision(0) 2674329Sktlim@umich.edu .prereq(totBytes) 2684329Sktlim@umich.edu ; 2694329Sktlim@umich.edu 2704329Sktlim@umich.edu totPackets 2712292SN/A .name(name() + ".totPackets") 2722292SN/A .desc("Total Packets") 2732292SN/A .precision(0) 2742292SN/A .prereq(totBytes) 2752292SN/A ; 2762292SN/A 2772292SN/A totBytes 2782292SN/A .name(name() + ".totBytes") 2792292SN/A .desc("Total Bytes") 2802292SN/A .precision(0) 2812292SN/A .prereq(totBytes) 2822292SN/A ; 2832292SN/A 2842292SN/A totPacketRate 2859444SAndreas.Sandberg@ARM.com .name(name() + ".totPPS") 2862307SN/A .desc("Total Tranmission Rate (packets/s)") 2879444SAndreas.Sandberg@ARM.com .precision(0) 2882367SN/A .prereq(totBytes) 2892307SN/A ; 2902329SN/A 2919444SAndreas.Sandberg@ARM.com txPacketRate 2922307SN/A .name(name() + ".txPPS") 2932307SN/A .desc("Packet Tranmission Rate (packets/s)") 2942307SN/A .precision(0) 2952307SN/A .prereq(txBytes) 2962307SN/A ; 2972307SN/A 2989444SAndreas.Sandberg@ARM.com rxPacketRate 2992307SN/A .name(name() + ".rxPPS") 3002307SN/A .desc("Packet Reception Rate (packets/s)") 3012307SN/A .precision(0) 3022307SN/A .prereq(rxBytes) 3032292SN/A ; 3042292SN/A 3052329SN/A postedSwi 3062329SN/A .name(name() + ".postedSwi") 3072292SN/A .desc("number of software interrupts posted to CPU") 3082329SN/A .precision(0) 3092329SN/A ; 3102292SN/A 3112292SN/A totalSwi 3122292SN/A .name(name() + ".totalSwi") 3132292SN/A .desc("number of total Swi written to ISR") 3142292SN/A .precision(0) 3152329SN/A ; 3162292SN/A 3172292SN/A coalescedSwi 3189936SFaissal.Sleiman@arm.com .name(name() + ".coalescedSwi") 3192292SN/A .desc("average number of Swi's coalesced into each post") 3202292SN/A .precision(0) 3212292SN/A ; 3222292SN/A 3232292SN/A postedRxIdle 3242292SN/A .name(name() + ".postedRxIdle") 3252329SN/A .desc("number of rxIdle interrupts posted to CPU") 3262329SN/A .precision(0) 3272329SN/A ; 3282292SN/A 3292292SN/A totalRxIdle 3302292SN/A .name(name() + ".totalRxIdle") 3312292SN/A .desc("number of total RxIdle written to ISR") 3322292SN/A .precision(0) 3332329SN/A ; 3342292SN/A 3359936SFaissal.Sleiman@arm.com coalescedRxIdle 3369936SFaissal.Sleiman@arm.com .name(name() + ".coalescedRxIdle") 3372292SN/A .desc("average number of RxIdle's coalesced into each post") 3382292SN/A .precision(0) 3392292SN/A ; 3402292SN/A 3412292SN/A postedRxOk 3422292SN/A .name(name() + ".postedRxOk") 3432292SN/A .desc("number of RxOk interrupts posted to CPU") 3442292SN/A .precision(0) 3452292SN/A ; 3462292SN/A 3472292SN/A totalRxOk 3482292SN/A .name(name() + ".totalRxOk") 3492292SN/A .desc("number of total RxOk written to ISR") 3502292SN/A .precision(0) 3512292SN/A ; 3522292SN/A 3532292SN/A coalescedRxOk 3542292SN/A .name(name() + ".coalescedRxOk") 3552292SN/A .desc("average number of RxOk's coalesced into each post") 3562292SN/A .precision(0) 3572292SN/A ; 3582292SN/A 3592292SN/A postedRxDesc 3602329SN/A .name(name() + ".postedRxDesc") 3612329SN/A .desc("number of RxDesc interrupts posted to CPU") 3622292SN/A .precision(0) 3637720Sgblack@eecs.umich.edu ; 3647720Sgblack@eecs.umich.edu 3652292SN/A totalRxDesc 3662292SN/A .name(name() + ".totalRxDesc") 3672292SN/A .desc("number of total RxDesc written to ISR") 3682292SN/A .precision(0) 3692292SN/A ; 3702292SN/A 3712292SN/A coalescedRxDesc 3722292SN/A .name(name() + ".coalescedRxDesc") 3732292SN/A .desc("average number of RxDesc's coalesced into each post") 3742292SN/A .precision(0) 3752292SN/A ; 3762292SN/A 3772292SN/A postedTxOk 3782292SN/A .name(name() + ".postedTxOk") 3792292SN/A .desc("number of TxOk interrupts posted to CPU") 3802292SN/A .precision(0) 3812292SN/A ; 3822292SN/A 3832292SN/A totalTxOk 3842292SN/A .name(name() + ".totalTxOk") 3852292SN/A .desc("number of total TxOk written to ISR") 3862292SN/A .precision(0) 3872292SN/A ; 3882292SN/A 3897720Sgblack@eecs.umich.edu coalescedTxOk 3907720Sgblack@eecs.umich.edu .name(name() + ".coalescedTxOk") 3912292SN/A .desc("average number of TxOk's coalesced into each post") 3922292SN/A .precision(0) 3932292SN/A ; 3942292SN/A 3952292SN/A postedTxIdle 3962292SN/A .name(name() + ".postedTxIdle") 3972292SN/A .desc("number of TxIdle interrupts posted to CPU") 3982292SN/A .precision(0) 3992292SN/A ; 4002292SN/A 4012292SN/A totalTxIdle 4022292SN/A .name(name() + ".totalTxIdle") 4032292SN/A .desc("number of total TxIdle written to ISR") 4042292SN/A .precision(0) 4052292SN/A ; 4062292SN/A 4072292SN/A coalescedTxIdle 4082292SN/A .name(name() + ".coalescedTxIdle") 4092292SN/A .desc("average number of TxIdle's coalesced into each post") 4102292SN/A .precision(0) 4112292SN/A ; 4122292SN/A 4132292SN/A postedTxDesc 4142292SN/A .name(name() + ".postedTxDesc") 41510239Sbinhpham@cs.rutgers.edu .desc("number of TxDesc interrupts posted to CPU") 4162292SN/A .precision(0) 41710239Sbinhpham@cs.rutgers.edu ; 41810239Sbinhpham@cs.rutgers.edu 41910239Sbinhpham@cs.rutgers.edu totalTxDesc 42010239Sbinhpham@cs.rutgers.edu .name(name() + ".totalTxDesc") 42110239Sbinhpham@cs.rutgers.edu .desc("number of total TxDesc written to ISR") 4222292SN/A .precision(0) 42310239Sbinhpham@cs.rutgers.edu ; 42410239Sbinhpham@cs.rutgers.edu 42510239Sbinhpham@cs.rutgers.edu coalescedTxDesc 42610239Sbinhpham@cs.rutgers.edu .name(name() + ".coalescedTxDesc") 42710239Sbinhpham@cs.rutgers.edu .desc("average number of TxDesc's coalesced into each post") 42810239Sbinhpham@cs.rutgers.edu .precision(0) 42910239Sbinhpham@cs.rutgers.edu ; 43010239Sbinhpham@cs.rutgers.edu 43110239Sbinhpham@cs.rutgers.edu postedRxOrn 43210239Sbinhpham@cs.rutgers.edu .name(name() + ".postedRxOrn") 4332292SN/A .desc("number of RxOrn posted to CPU") 4342292SN/A .precision(0) 4358545Ssaidi@eecs.umich.edu ; 4368545Ssaidi@eecs.umich.edu 4378545Ssaidi@eecs.umich.edu totalRxOrn 43811357Sstephan.diestelhorst@arm.com .name(name() + ".totalRxOrn") 43911357Sstephan.diestelhorst@arm.com .desc("number of total RxOrn written to ISR") 44011357Sstephan.diestelhorst@arm.com .precision(0) 4418545Ssaidi@eecs.umich.edu ; 44210030SAli.Saidi@ARM.com 4438545Ssaidi@eecs.umich.edu coalescedRxOrn 44411356Skrinat01@arm.com .name(name() + ".coalescedRxOrn") 44511356Skrinat01@arm.com .desc("average number of RxOrn's coalesced into each post") 44610030SAli.Saidi@ARM.com .precision(0) 4479383SAli.Saidi@ARM.com ; 4489383SAli.Saidi@ARM.com 4499383SAli.Saidi@ARM.com coalescedTotal 4509383SAli.Saidi@ARM.com .name(name() + ".coalescedTotal") 4519383SAli.Saidi@ARM.com .desc("average number of interrupts coalesced into each post") 4529383SAli.Saidi@ARM.com .precision(0) 4539383SAli.Saidi@ARM.com ; 45410030SAli.Saidi@ARM.com 45510030SAli.Saidi@ARM.com postedInterrupts 45610030SAli.Saidi@ARM.com .name(name() + ".postedInterrupts") 45710030SAli.Saidi@ARM.com .desc("number of posts to CPU") 45811097Songal@cs.wisc.edu .precision(0) 45911097Songal@cs.wisc.edu ; 46011097Songal@cs.wisc.edu 46110030SAli.Saidi@ARM.com droppedPackets 46211097Songal@cs.wisc.edu .name(name() + ".droppedPackets") 46311097Songal@cs.wisc.edu .desc("number of packets dropped") 46411097Songal@cs.wisc.edu .precision(0) 46510030SAli.Saidi@ARM.com ; 46610030SAli.Saidi@ARM.com 46710030SAli.Saidi@ARM.com coalescedSwi = totalSwi / postedInterrupts; 4688545Ssaidi@eecs.umich.edu coalescedRxIdle = totalRxIdle / postedInterrupts; 4698545Ssaidi@eecs.umich.edu coalescedRxOk = totalRxOk / postedInterrupts; 4708545Ssaidi@eecs.umich.edu coalescedRxDesc = totalRxDesc / postedInterrupts; 47110030SAli.Saidi@ARM.com coalescedTxOk = totalTxOk / postedInterrupts; 4728545Ssaidi@eecs.umich.edu coalescedTxIdle = totalTxIdle / postedInterrupts; 4738545Ssaidi@eecs.umich.edu coalescedTxDesc = totalTxDesc / postedInterrupts; 47410149Smarco.elver@ed.ac.uk coalescedRxOrn = totalRxOrn / postedInterrupts; 47510149Smarco.elver@ed.ac.uk 4768545Ssaidi@eecs.umich.edu coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + totalTxOk 4778545Ssaidi@eecs.umich.edu + totalTxIdle + totalTxDesc + totalRxOrn) / postedInterrupts; 4788545Ssaidi@eecs.umich.edu 47910824SAndreas.Sandberg@ARM.com txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4808545Ssaidi@eecs.umich.edu rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4818545Ssaidi@eecs.umich.edu totBandwidth = txBandwidth + rxBandwidth; 4828545Ssaidi@eecs.umich.edu totBytes = txBytes + rxBytes; 4838545Ssaidi@eecs.umich.edu totPackets = txPackets + rxPackets; 48411097Songal@cs.wisc.edu 48511097Songal@cs.wisc.edu txPacketRate = txPackets / simSeconds; 48611097Songal@cs.wisc.edu rxPacketRate = rxPackets / simSeconds; 4878545Ssaidi@eecs.umich.edu} 48811097Songal@cs.wisc.edu 4898545Ssaidi@eecs.umich.edu/** 49011097Songal@cs.wisc.edu * This is to read the PCI general configuration registers 49111097Songal@cs.wisc.edu */ 49210149Smarco.elver@ed.ac.ukvoid 49310149Smarco.elver@ed.ac.ukNSGigE::ReadConfig(int offset, int size, uint8_t *data) 49410149Smarco.elver@ed.ac.uk{ 49510149Smarco.elver@ed.ac.uk if (offset < PCI_DEVICE_SPECIFIC) 49610149Smarco.elver@ed.ac.uk PciDev::ReadConfig(offset, size, data); 49710149Smarco.elver@ed.ac.uk else 49810149Smarco.elver@ed.ac.uk panic("Device specific PCI config space not implemented!\n"); 4998545Ssaidi@eecs.umich.edu} 50010030SAli.Saidi@ARM.com 5018545Ssaidi@eecs.umich.edu/** 5028545Ssaidi@eecs.umich.edu * This is to write to the PCI general configuration registers 50310474Sandreas.hansson@arm.com */ 5048545Ssaidi@eecs.umich.eduvoid 50510030SAli.Saidi@ARM.comNSGigE::WriteConfig(int offset, int size, uint32_t data) 50610030SAli.Saidi@ARM.com{ 50710030SAli.Saidi@ARM.com if (offset < PCI_DEVICE_SPECIFIC) 50810030SAli.Saidi@ARM.com PciDev::WriteConfig(offset, size, data); 50910030SAli.Saidi@ARM.com else 51010030SAli.Saidi@ARM.com panic("Device specific PCI config space not implemented!\n"); 51110030SAli.Saidi@ARM.com 51210030SAli.Saidi@ARM.com // Need to catch writes to BARs to update the PIO interface 51310030SAli.Saidi@ARM.com switch (offset) { 5148545Ssaidi@eecs.umich.edu // seems to work fine without all these PCI settings, but i 5158545Ssaidi@eecs.umich.edu // put in the IO to double check, an assertion will fail if we 5168545Ssaidi@eecs.umich.edu // need to properly implement it 5179046SAli.Saidi@ARM.com case PCI_COMMAND: 5188545Ssaidi@eecs.umich.edu if (config.data[offset] & PCI_CMD_IOSE) 5198545Ssaidi@eecs.umich.edu ioEnable = true; 5208545Ssaidi@eecs.umich.edu else 5218545Ssaidi@eecs.umich.edu ioEnable = false; 5228545Ssaidi@eecs.umich.edu 5238545Ssaidi@eecs.umich.edu#if 0 5248545Ssaidi@eecs.umich.edu if (config.data[offset] & PCI_CMD_BME) { 5258545Ssaidi@eecs.umich.edu bmEnabled = true; 5262292SN/A } 5278199SAli.Saidi@ARM.com else { 5288199SAli.Saidi@ARM.com bmEnabled = false; 5298199SAli.Saidi@ARM.com } 5308199SAli.Saidi@ARM.com 5318199SAli.Saidi@ARM.com if (config.data[offset] & PCI_CMD_MSE) { 5328199SAli.Saidi@ARM.com memEnable = true; 5338199SAli.Saidi@ARM.com } 5348199SAli.Saidi@ARM.com else { 5358199SAli.Saidi@ARM.com memEnable = false; 5368199SAli.Saidi@ARM.com } 5378199SAli.Saidi@ARM.com#endif 5388199SAli.Saidi@ARM.com break; 53910824SAndreas.Sandberg@ARM.com 5408199SAli.Saidi@ARM.com case PCI0_BASE_ADDR0: 5418199SAli.Saidi@ARM.com if (BARAddrs[0] != 0) { 5428199SAli.Saidi@ARM.com if (pioInterface) 5438199SAli.Saidi@ARM.com pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 5448199SAli.Saidi@ARM.com 5458199SAli.Saidi@ARM.com BARAddrs[0] &= EV5::PAddrUncachedMask; 5468199SAli.Saidi@ARM.com } 5478199SAli.Saidi@ARM.com break; 5488272SAli.Saidi@ARM.com case PCI0_BASE_ADDR1: 5498545Ssaidi@eecs.umich.edu if (BARAddrs[1] != 0) { 5508545Ssaidi@eecs.umich.edu if (pioInterface) 5518545Ssaidi@eecs.umich.edu pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 5528545Ssaidi@eecs.umich.edu 5539046SAli.Saidi@ARM.com BARAddrs[1] &= EV5::PAddrUncachedMask; 5548545Ssaidi@eecs.umich.edu } 5558545Ssaidi@eecs.umich.edu break; 5568545Ssaidi@eecs.umich.edu } 5578592Sgblack@eecs.umich.edu} 5588592Sgblack@eecs.umich.edu 5598545Ssaidi@eecs.umich.edu/** 5608199SAli.Saidi@ARM.com * This reads the device registers, which are detailed in the NS83820 5618545Ssaidi@eecs.umich.edu * spec sheet 5628199SAli.Saidi@ARM.com */ 56310474Sandreas.hansson@arm.comFault 56410474Sandreas.hansson@arm.comNSGigE::read(MemReqPtr &req, uint8_t *data) 56510474Sandreas.hansson@arm.com{ 56610474Sandreas.hansson@arm.com assert(ioEnable); 5678545Ssaidi@eecs.umich.edu 5688545Ssaidi@eecs.umich.edu //The mask is to give you only the offset into the device register file 5698199SAli.Saidi@ARM.com Addr daddr = req->paddr & 0xfff; 5708545Ssaidi@eecs.umich.edu DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 5718545Ssaidi@eecs.umich.edu daddr, req->paddr, req->vaddr, req->size); 5729046SAli.Saidi@ARM.com 57310575SMarco.Elver@ARM.com 5748545Ssaidi@eecs.umich.edu // there are some reserved registers, you can see ns_gige_reg.h and 5758545Ssaidi@eecs.umich.edu // the spec sheet for details 5768545Ssaidi@eecs.umich.edu if (daddr > LAST && daddr <= RESERVED) { 5778545Ssaidi@eecs.umich.edu panic("Accessing reserved register"); 5788545Ssaidi@eecs.umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 5798545Ssaidi@eecs.umich.edu ReadConfig(daddr & 0xff, req->size, data); 5808545Ssaidi@eecs.umich.edu return No_Fault; 5818545Ssaidi@eecs.umich.edu } else if (daddr >= MIB_START && daddr <= MIB_END) { 5828545Ssaidi@eecs.umich.edu // don't implement all the MIB's. hopefully the kernel 5838592Sgblack@eecs.umich.edu // doesn't actually DEPEND upon their values 5848592Sgblack@eecs.umich.edu // MIB are just hardware stats keepers 5858592Sgblack@eecs.umich.edu uint32_t ® = *(uint32_t *) data; 5868545Ssaidi@eecs.umich.edu reg = 0; 5878545Ssaidi@eecs.umich.edu return No_Fault; 5888545Ssaidi@eecs.umich.edu } else if (daddr > 0x3FC) 5898545Ssaidi@eecs.umich.edu panic("Something is messed up!\n"); 59010474Sandreas.hansson@arm.com 59110474Sandreas.hansson@arm.com switch (req->size) { 59210474Sandreas.hansson@arm.com case sizeof(uint32_t): 59310474Sandreas.hansson@arm.com { 5948545Ssaidi@eecs.umich.edu uint32_t ® = *(uint32_t *)data; 5958199SAli.Saidi@ARM.com 5968199SAli.Saidi@ARM.com switch (daddr) { 5978199SAli.Saidi@ARM.com case CR: 5988199SAli.Saidi@ARM.com reg = regs.command; 5998199SAli.Saidi@ARM.com //these are supposed to be cleared on a read 6008199SAli.Saidi@ARM.com reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 6018199SAli.Saidi@ARM.com break; 6028199SAli.Saidi@ARM.com 6038199SAli.Saidi@ARM.com case CFGR: 6048199SAli.Saidi@ARM.com reg = regs.config; 6058199SAli.Saidi@ARM.com break; 6068199SAli.Saidi@ARM.com 6072292SN/A case MEAR: 6082292SN/A reg = regs.mear; 6094032Sktlim@umich.edu break; 6102292SN/A 6112292SN/A case PTSCR: 6122292SN/A reg = regs.ptscr; 6137720Sgblack@eecs.umich.edu break; 6147944SGiacomo.Gabrielli@arm.com 6152292SN/A case ISR: 6164032Sktlim@umich.edu reg = regs.isr; 6174032Sktlim@umich.edu devIntrClear(ISR_ALL); 6182669Sktlim@umich.edu break; 6192292SN/A 6207944SGiacomo.Gabrielli@arm.com case IMR: 6217944SGiacomo.Gabrielli@arm.com reg = regs.imr; 6227944SGiacomo.Gabrielli@arm.com break; 6237944SGiacomo.Gabrielli@arm.com 6247597Sminkyu.jeong@arm.com case IER: 6257597Sminkyu.jeong@arm.com reg = regs.ier; 62610231Ssteve.reinhardt@amd.com break; 6272329SN/A 62810824SAndreas.Sandberg@ARM.com case IHR: 62910824SAndreas.Sandberg@ARM.com reg = regs.ihr; 63010824SAndreas.Sandberg@ARM.com break; 63110231Ssteve.reinhardt@amd.com 6327848SAli.Saidi@ARM.com case TXDP: 6337600Sminkyu.jeong@arm.com reg = regs.txdp; 6347600Sminkyu.jeong@arm.com break; 6357600Sminkyu.jeong@arm.com 63610824SAndreas.Sandberg@ARM.com case TXDP_HI: 6373731Sktlim@umich.edu reg = regs.txdp_hi; 6382367SN/A break; 6392367SN/A 6402292SN/A case TX_CFG: 6412292SN/A reg = regs.txcfg; 64210333Smitch.hayenga@arm.com break; 6439046SAli.Saidi@ARM.com 6444032Sktlim@umich.edu case GPIOR: 6454032Sktlim@umich.edu reg = regs.gpior; 6464032Sktlim@umich.edu break; 6478199SAli.Saidi@ARM.com 6488199SAli.Saidi@ARM.com case RXDP: 6492292SN/A reg = regs.rxdp; 6502292SN/A break; 6512292SN/A 6522292SN/A case RXDP_HI: 6532292SN/A reg = regs.rxdp_hi; 6542292SN/A break; 6552292SN/A 6562292SN/A case RX_CFG: 6572292SN/A reg = regs.rxcfg; 6582292SN/A break; 6592292SN/A 6602292SN/A case PQCR: 6612292SN/A reg = regs.pqcr; 6622292SN/A break; 6632292SN/A 6647720Sgblack@eecs.umich.edu case WCSR: 6657720Sgblack@eecs.umich.edu reg = regs.wcsr; 6662292SN/A break; 6674032Sktlim@umich.edu 6684032Sktlim@umich.edu case PCR: 6692292SN/A reg = regs.pcr; 6702292SN/A break; 6712292SN/A 6722292SN/A // see the spec sheet for how RFCR and RFDR work 6732292SN/A // basically, you write to RFCR to tell the machine 6742292SN/A // what you want to do next, then you act upon RFDR, 6757944SGiacomo.Gabrielli@arm.com // and the device will be prepared b/c of what you 6767944SGiacomo.Gabrielli@arm.com // wrote to RFCR 6777944SGiacomo.Gabrielli@arm.com case RFCR: 6787944SGiacomo.Gabrielli@arm.com reg = regs.rfcr; 67910231Ssteve.reinhardt@amd.com break; 6807848SAli.Saidi@ARM.com 6817848SAli.Saidi@ARM.com case RFDR: 6822329SN/A switch (regs.rfcr & RFCR_RFADDR) { 6837782Sminkyu.jeong@arm.com case 0x000: 6847720Sgblack@eecs.umich.edu reg = rom.perfectMatch[1]; 6852292SN/A reg = reg << 8; 6862292SN/A reg += rom.perfectMatch[0]; 68710231Ssteve.reinhardt@amd.com break; 6887782Sminkyu.jeong@arm.com case 0x002: 6897782Sminkyu.jeong@arm.com reg = rom.perfectMatch[3] << 8; 6907782Sminkyu.jeong@arm.com reg += rom.perfectMatch[2]; 6912292SN/A break; 6922292SN/A case 0x004: 6932292SN/A reg = rom.perfectMatch[5] << 8; 6942292SN/A reg += rom.perfectMatch[4]; 6952336SN/A break; 6962336SN/A default: 6972336SN/A panic("reading RFDR for something other than PMATCH!\n"); 6982329SN/A // didn't implement other RFDR functionality b/c 6992292SN/A // driver didn't use it 7002329SN/A } 7012292SN/A break; 7022292SN/A 7038199SAli.Saidi@ARM.com case SRR: 7042292SN/A reg = regs.srr; 7052292SN/A break; 7062292SN/A 7072292SN/A case MIBC: 7082292SN/A reg = regs.mibc; 7092292SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 7102292SN/A break; 7112292SN/A 7122292SN/A case VRCR: 7137720Sgblack@eecs.umich.edu reg = regs.vrcr; 7147720Sgblack@eecs.umich.edu break; 7152292SN/A 7162292SN/A case VTCR: 7172292SN/A reg = regs.vtcr; 7182292SN/A break; 7192292SN/A 7202292SN/A case VDR: 7212292SN/A reg = regs.vdr; 7222292SN/A break; 7232292SN/A 7242292SN/A case CCSR: 7252292SN/A reg = regs.ccsr; 7262292SN/A break; 7272292SN/A 7282292SN/A case TBICR: 7292292SN/A reg = regs.tbicr; 7302292SN/A break; 7312292SN/A 7322292SN/A case TBISR: 7332292SN/A reg = regs.tbisr; 7342292SN/A break; 7352292SN/A 7362292SN/A case TANAR: 7372292SN/A reg = regs.tanar; 7382292SN/A break; 7392292SN/A 7402292SN/A case TANLPAR: 7412292SN/A reg = regs.tanlpar; 7422292SN/A break; 7432292SN/A 7442329SN/A case TANER: 7452329SN/A reg = regs.taner; 7462292SN/A break; 7472292SN/A 7482292SN/A case TESR: 7492292SN/A reg = regs.tesr; 7502292SN/A break; 7517720Sgblack@eecs.umich.edu 7527720Sgblack@eecs.umich.edu case M5REG: 7532292SN/A reg = params()->m5reg; 7542292SN/A break; 7552292SN/A 7562292SN/A default: 7572292SN/A panic("reading unimplemented register: addr=%#x", daddr); 7582292SN/A } 7592292SN/A 7602292SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 7612292SN/A daddr, reg, reg); 7622292SN/A } 7632292SN/A break; 7642292SN/A 7652292SN/A default: 7666974Stjones1@inf.ed.ac.uk panic("accessing register with invalid size: addr=%#x, size=%d", 7676974Stjones1@inf.ed.ac.uk daddr, req->size); 7686974Stjones1@inf.ed.ac.uk } 7696974Stjones1@inf.ed.ac.uk 7706974Stjones1@inf.ed.ac.uk return No_Fault; 7716974Stjones1@inf.ed.ac.uk} 7726974Stjones1@inf.ed.ac.uk 7736974Stjones1@inf.ed.ac.ukFault 7746974Stjones1@inf.ed.ac.ukNSGigE::write(MemReqPtr &req, const uint8_t *data) 7756974Stjones1@inf.ed.ac.uk{ 7766974Stjones1@inf.ed.ac.uk assert(ioEnable); 7776974Stjones1@inf.ed.ac.uk 7786974Stjones1@inf.ed.ac.uk Addr daddr = req->paddr & 0xfff; 7796974Stjones1@inf.ed.ac.uk DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 7806974Stjones1@inf.ed.ac.uk daddr, req->paddr, req->vaddr, req->size); 7816974Stjones1@inf.ed.ac.uk 7822292SN/A if (daddr > LAST && daddr <= RESERVED) { 7832292SN/A panic("Accessing reserved register"); 7846974Stjones1@inf.ed.ac.uk } else if (daddr > RESERVED && daddr <= 0x3FC) { 7856974Stjones1@inf.ed.ac.uk WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 7866974Stjones1@inf.ed.ac.uk return No_Fault; 7876974Stjones1@inf.ed.ac.uk } else if (daddr > 0x3FC) 7886974Stjones1@inf.ed.ac.uk panic("Something is messed up!\n"); 7896974Stjones1@inf.ed.ac.uk 7902292SN/A if (req->size == sizeof(uint32_t)) { 7912292SN/A uint32_t reg = *(uint32_t *)data; 7922292SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 7932292SN/A 7948727Snilay@cs.wisc.edu switch (daddr) { 7952292SN/A case CR: 7962292SN/A regs.command = reg; 79710333Smitch.hayenga@arm.com if (reg & CR_TXD) { 7982678Sktlim@umich.edu txEnable = false; 7992678Sktlim@umich.edu } else if (reg & CR_TXE) { 8002678Sktlim@umich.edu txEnable = true; 8012678Sktlim@umich.edu 8022678Sktlim@umich.edu // the kernel is enabling the transmit machine 8032329SN/A if (txState == txIdle) 8042329SN/A txKick(); 8052292SN/A } 8062292SN/A 8072292SN/A if (reg & CR_RXD) { 8082292SN/A rxEnable = false; 8092292SN/A } else if (reg & CR_RXE) { 8102292SN/A rxEnable = true; 8112292SN/A 8122678Sktlim@umich.edu if (rxState == rxIdle) 8132292SN/A rxKick(); 8142292SN/A } 8152292SN/A 8162292SN/A if (reg & CR_TXR) 8172292SN/A txReset(); 8182292SN/A 8192292SN/A if (reg & CR_RXR) 8202292SN/A rxReset(); 8212292SN/A 8222292SN/A if (reg & CR_SWI) 8232292SN/A devIntrPost(ISR_SWI); 8246974Stjones1@inf.ed.ac.uk 8256974Stjones1@inf.ed.ac.uk if (reg & CR_RST) { 8266974Stjones1@inf.ed.ac.uk txReset(); 8276974Stjones1@inf.ed.ac.uk rxReset(); 8286974Stjones1@inf.ed.ac.uk 8292669Sktlim@umich.edu regsReset(); 8302669Sktlim@umich.edu } 8312669Sktlim@umich.edu break; 8328481Sgblack@eecs.umich.edu 8338481Sgblack@eecs.umich.edu case CFGR: 8348481Sgblack@eecs.umich.edu if (reg & CFGR_LNKSTS || 8352292SN/A reg & CFGR_SPDSTS || 8362292SN/A reg & CFGR_DUPSTS || 8372669Sktlim@umich.edu reg & CFGR_RESERVED || 83810031SAli.Saidi@ARM.com reg & CFGR_T64ADDR || 8393772Sgblack@eecs.umich.edu reg & CFGR_PCI64_DET) 84010031SAli.Saidi@ARM.com panic("writing to read-only or reserved CFGR bits!\n"); 84110031SAli.Saidi@ARM.com 84210031SAli.Saidi@ARM.com regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 84310031SAli.Saidi@ARM.com CFGR_RESERVED | CFGR_T64ADDR | CFGR_PCI64_DET); 8442669Sktlim@umich.edu 8456974Stjones1@inf.ed.ac.uk// all these #if 0's are because i don't THINK the kernel needs to 8466974Stjones1@inf.ed.ac.uk// have these implemented. if there is a problem relating to one of 8472292SN/A// these, you may need to add functionality in. 8482678Sktlim@umich.edu#if 0 8492678Sktlim@umich.edu if (reg & CFGR_TBI_EN) ; 8502678Sktlim@umich.edu if (reg & CFGR_MODE_1000) ; 8512678Sktlim@umich.edu#endif 8526974Stjones1@inf.ed.ac.uk 8536974Stjones1@inf.ed.ac.uk if (reg & CFGR_AUTO_1000) 8546974Stjones1@inf.ed.ac.uk panic("CFGR_AUTO_1000 not implemented!\n"); 8556974Stjones1@inf.ed.ac.uk 85610342SCurtis.Dunham@arm.com#if 0 8576974Stjones1@inf.ed.ac.uk if (reg & CFGR_PINT_DUPSTS || 8586974Stjones1@inf.ed.ac.uk reg & CFGR_PINT_LNKSTS || 8596974Stjones1@inf.ed.ac.uk reg & CFGR_PINT_SPDSTS) 8606974Stjones1@inf.ed.ac.uk ; 86110342SCurtis.Dunham@arm.com 86210342SCurtis.Dunham@arm.com if (reg & CFGR_TMRTEST) ; 8636974Stjones1@inf.ed.ac.uk if (reg & CFGR_MRM_DIS) ; 8646974Stjones1@inf.ed.ac.uk if (reg & CFGR_MWI_DIS) ; 8656974Stjones1@inf.ed.ac.uk 8666974Stjones1@inf.ed.ac.uk if (reg & CFGR_T64ADDR) 8676974Stjones1@inf.ed.ac.uk panic("CFGR_T64ADDR is read only register!\n"); 8686974Stjones1@inf.ed.ac.uk 8696974Stjones1@inf.ed.ac.uk if (reg & CFGR_PCI64_DET) 8706974Stjones1@inf.ed.ac.uk panic("CFGR_PCI64_DET is read only register!\n"); 8716974Stjones1@inf.ed.ac.uk 8726974Stjones1@inf.ed.ac.uk if (reg & CFGR_DATA64_EN) ; 8736974Stjones1@inf.ed.ac.uk if (reg & CFGR_M64ADDR) ; 8746974Stjones1@inf.ed.ac.uk if (reg & CFGR_PHY_RST) ; 8756974Stjones1@inf.ed.ac.uk if (reg & CFGR_PHY_DIS) ; 8766974Stjones1@inf.ed.ac.uk#endif 8772678Sktlim@umich.edu 8787720Sgblack@eecs.umich.edu if (reg & CFGR_EXTSTS_EN) 8792292SN/A extstsEnable = true; 8807720Sgblack@eecs.umich.edu else 8813797Sgblack@eecs.umich.edu extstsEnable = false; 8823221Sktlim@umich.edu 8832292SN/A#if 0 8842693Sktlim@umich.edu if (reg & CFGR_REQALG) ; 8854350Sgblack@eecs.umich.edu if (reg & CFGR_SB) ; 8866974Stjones1@inf.ed.ac.uk if (reg & CFGR_POW) ; 8873326Sktlim@umich.edu if (reg & CFGR_EXD) ; 8883326Sktlim@umich.edu if (reg & CFGR_PESEL) ; 8893326Sktlim@umich.edu if (reg & CFGR_BROM_DIS) ; 8909046SAli.Saidi@ARM.com if (reg & CFGR_EXT_125) ; 89110030SAli.Saidi@ARM.com if (reg & CFGR_BEM) ; 8929046SAli.Saidi@ARM.com#endif 8933326Sktlim@umich.edu break; 8943326Sktlim@umich.edu 8953326Sktlim@umich.edu case MEAR: 8963326Sktlim@umich.edu regs.mear = reg; 8973326Sktlim@umich.edu // since phy is completely faked, MEAR_MD* don't matter 8983326Sktlim@umich.edu // and since the driver never uses MEAR_EE*, they don't 8993326Sktlim@umich.edu // matter 9007823Ssteve.reinhardt@amd.com#if 0 9018887Sgeoffrey.blake@arm.com if (reg & MEAR_EEDI) ; 9028887Sgeoffrey.blake@arm.com if (reg & MEAR_EEDO) ; // this one is read only 9038887Sgeoffrey.blake@arm.com if (reg & MEAR_EECLK) ; 9048887Sgeoffrey.blake@arm.com if (reg & MEAR_EESEL) ; 9058887Sgeoffrey.blake@arm.com if (reg & MEAR_MDIO) ; 9068887Sgeoffrey.blake@arm.com if (reg & MEAR_MDDIR) ; 9073326Sktlim@umich.edu if (reg & MEAR_MDC) ; 9083326Sktlim@umich.edu#endif 9093326Sktlim@umich.edu break; 9102693Sktlim@umich.edu 9112693Sktlim@umich.edu case PTSCR: 9122693Sktlim@umich.edu regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 9132693Sktlim@umich.edu // these control BISTs for various parts of chip - we 9142693Sktlim@umich.edu // don't care or do just fake that the BIST is done 9152693Sktlim@umich.edu if (reg & PTSCR_RBIST_EN) 9168481Sgblack@eecs.umich.edu regs.ptscr |= PTSCR_RBIST_DONE; 9178481Sgblack@eecs.umich.edu if (reg & PTSCR_EEBIST_EN) 9188481Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EEBIST_EN; 9198481Sgblack@eecs.umich.edu if (reg & PTSCR_EELOAD_EN) 9208481Sgblack@eecs.umich.edu regs.ptscr &= ~PTSCR_EELOAD_EN; 9218481Sgblack@eecs.umich.edu break; 9228481Sgblack@eecs.umich.edu 9238481Sgblack@eecs.umich.edu case ISR: /* writing to the ISR has no effect */ 9248481Sgblack@eecs.umich.edu panic("ISR is a read only register!\n"); 9258481Sgblack@eecs.umich.edu 9268481Sgblack@eecs.umich.edu case IMR: 9278481Sgblack@eecs.umich.edu regs.imr = reg; 9288481Sgblack@eecs.umich.edu devIntrChangeMask(); 9298481Sgblack@eecs.umich.edu break; 9308481Sgblack@eecs.umich.edu 9318481Sgblack@eecs.umich.edu case IER: 9328481Sgblack@eecs.umich.edu regs.ier = reg; 9338481Sgblack@eecs.umich.edu break; 9348481Sgblack@eecs.umich.edu 9358481Sgblack@eecs.umich.edu case IHR: 9368481Sgblack@eecs.umich.edu regs.ihr = reg; 9374032Sktlim@umich.edu /* not going to implement real interrupt holdoff */ 9383221Sktlim@umich.edu break; 9393221Sktlim@umich.edu 9406974Stjones1@inf.ed.ac.uk case TXDP: 9416974Stjones1@inf.ed.ac.uk regs.txdp = (reg & 0xFFFFFFFC); 9428481Sgblack@eecs.umich.edu assert(txState == txIdle); 9436974Stjones1@inf.ed.ac.uk CTDD = false; 9446974Stjones1@inf.ed.ac.uk break; 9456974Stjones1@inf.ed.ac.uk 9462669Sktlim@umich.edu case TXDP_HI: 9476974Stjones1@inf.ed.ac.uk regs.txdp_hi = reg; 9486974Stjones1@inf.ed.ac.uk break; 9498481Sgblack@eecs.umich.edu 9506974Stjones1@inf.ed.ac.uk case TX_CFG: 9516974Stjones1@inf.ed.ac.uk regs.txcfg = reg; 9526974Stjones1@inf.ed.ac.uk#if 0 9536974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_CSI) ; 9546974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_HBI) ; 9556974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_MLB) ; 9566974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_ATP) ; 9576974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_ECRETRY) { 9586974Stjones1@inf.ed.ac.uk /* 9596974Stjones1@inf.ed.ac.uk * this could easily be implemented, but considering 9606974Stjones1@inf.ed.ac.uk * the network is just a fake pipe, wouldn't make 9616974Stjones1@inf.ed.ac.uk * sense to do this 9626974Stjones1@inf.ed.ac.uk */ 9636974Stjones1@inf.ed.ac.uk } 9646974Stjones1@inf.ed.ac.uk 9656974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_BRST_DIS) ; 9666974Stjones1@inf.ed.ac.uk#endif 9676974Stjones1@inf.ed.ac.uk 9686974Stjones1@inf.ed.ac.uk#if 0 9696974Stjones1@inf.ed.ac.uk /* we handle our own DMA, ignore the kernel's exhortations */ 9706974Stjones1@inf.ed.ac.uk if (reg & TX_CFG_MXDMA) ; 9716974Stjones1@inf.ed.ac.uk#endif 9726974Stjones1@inf.ed.ac.uk 9736974Stjones1@inf.ed.ac.uk // also, we currently don't care about fill/drain 9742292SN/A // thresholds though this may change in the future with 9752292SN/A // more realistic networks or a driver which changes it 9762292SN/A // according to feedback 9772292SN/A 9782292SN/A break; 9792292SN/A 9802292SN/A case GPIOR: 9812292SN/A regs.gpior = reg; 9822292SN/A /* these just control general purpose i/o pins, don't matter */ 9832292SN/A break; 9842292SN/A 9852292SN/A case RXDP: 9862292SN/A regs.rxdp = reg; 9872292SN/A CRDD = false; 9882292SN/A break; 9892292SN/A 9902292SN/A case RXDP_HI: 9912292SN/A regs.rxdp_hi = reg; 9922292SN/A break; 9932292SN/A 9942292SN/A case RX_CFG: 9952292SN/A regs.rxcfg = reg; 9962292SN/A#if 0 9972292SN/A if (reg & RX_CFG_AEP) ; 9982292SN/A if (reg & RX_CFG_ARP) ; 9992292SN/A if (reg & RX_CFG_STRIPCRC) ; 10002292SN/A if (reg & RX_CFG_RX_RD) ; 10012292SN/A if (reg & RX_CFG_ALP) ; 10022329SN/A if (reg & RX_CFG_AIRL) ; 10032292SN/A 10042292SN/A /* we handle our own DMA, ignore what kernel says about it */ 10052292SN/A if (reg & RX_CFG_MXDMA) ; 10062292SN/A 10072292SN/A //also, we currently don't care about fill/drain thresholds 10087720Sgblack@eecs.umich.edu //though this may change in the future with more realistic 10092292SN/A //networks or a driver which changes it according to feedback 10107720Sgblack@eecs.umich.edu if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 10112292SN/A#endif 10122292SN/A break; 10132292SN/A 10142292SN/A case PQCR: 10152292SN/A /* there is no priority queueing used in the linux 2.6 driver */ 10162292SN/A regs.pqcr = reg; 10172292SN/A break; 10182292SN/A 10192329SN/A case WCSR: 10202731Sktlim@umich.edu /* not going to implement wake on LAN */ 10212292SN/A regs.wcsr = reg; 10222292SN/A break; 10232292SN/A 10242292SN/A case PCR: 10252292SN/A /* not going to implement pause control */ 10262292SN/A regs.pcr = reg; 10272292SN/A break; 10282727Sktlim@umich.edu 10292292SN/A case RFCR: 10302292SN/A regs.rfcr = reg; 10314032Sktlim@umich.edu 10324032Sktlim@umich.edu rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 10334032Sktlim@umich.edu acceptBroadcast = (reg & RFCR_AAB) ? true : false; 10344032Sktlim@umich.edu acceptMulticast = (reg & RFCR_AAM) ? true : false; 10352292SN/A acceptUnicast = (reg & RFCR_AAU) ? true : false; 10362292SN/A acceptPerfect = (reg & RFCR_APM) ? true : false; 10372292SN/A acceptArp = (reg & RFCR_AARP) ? true : false; 10382292SN/A 10392292SN/A#if 0 10402329SN/A if (reg & RFCR_APAT) 10412292SN/A panic("RFCR_APAT not implemented!\n"); 10422292SN/A#endif 10432292SN/A 10442292SN/A if (reg & RFCR_MHEN || reg & RFCR_UHEN) 10457720Sgblack@eecs.umich.edu panic("hash filtering not implemented!\n"); 10462292SN/A 10477720Sgblack@eecs.umich.edu if (reg & RFCR_ULM) 10482292SN/A panic("RFCR_ULM not implemented!\n"); 10492292SN/A 10502329SN/A break; 10512329SN/A 10522292SN/A case RFDR: 10532292SN/A panic("the driver never writes to RFDR, something is wrong!\n"); 10542292SN/A 10552292SN/A case BRAR: 10562292SN/A panic("the driver never uses BRAR, something is wrong!\n"); 10572292SN/A 10582292SN/A case BRDR: 10592329SN/A panic("the driver never uses BRDR, something is wrong!\n"); 10602731Sktlim@umich.edu 10612292SN/A case SRR: 10622292SN/A panic("SRR is read only register!\n"); 10632292SN/A 10644032Sktlim@umich.edu case MIBC: 10654032Sktlim@umich.edu panic("the driver never uses MIBC, something is wrong!\n"); 10664032Sktlim@umich.edu 10674032Sktlim@umich.edu case VRCR: 10686974Stjones1@inf.ed.ac.uk regs.vrcr = reg; 10696974Stjones1@inf.ed.ac.uk break; 10706974Stjones1@inf.ed.ac.uk 10716974Stjones1@inf.ed.ac.uk case VTCR: 10726974Stjones1@inf.ed.ac.uk regs.vtcr = reg; 10736974Stjones1@inf.ed.ac.uk break; 10746974Stjones1@inf.ed.ac.uk 10754032Sktlim@umich.edu case VDR: 10762292SN/A panic("the driver never uses VDR, something is wrong!\n"); 10772292SN/A break; 10782292SN/A 10792292SN/A case CCSR: 10802292SN/A /* not going to implement clockrun stuff */ 10812292SN/A regs.ccsr = reg; 10822292SN/A break; 10832727Sktlim@umich.edu 10842292SN/A case TBICR: 10852292SN/A regs.tbicr = reg; 10862292SN/A if (reg & TBICR_MR_LOOPBACK) 10872292SN/A panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 10882292SN/A 10893349Sbinkertn@umich.edu if (reg & TBICR_MR_AN_ENABLE) { 10902693Sktlim@umich.edu regs.tanlpar = regs.tanar; 10912693Sktlim@umich.edu regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 10922693Sktlim@umich.edu } 10932693Sktlim@umich.edu 10942693Sktlim@umich.edu#if 0 10952693Sktlim@umich.edu if (reg & TBICR_MR_RESTART_AN) ; 10962693Sktlim@umich.edu#endif 10972693Sktlim@umich.edu 10982693Sktlim@umich.edu break; 10992693Sktlim@umich.edu 11002693Sktlim@umich.edu case TBISR: 11012693Sktlim@umich.edu panic("TBISR is read only register!\n"); 11022693Sktlim@umich.edu 11032693Sktlim@umich.edu case TANAR: 11042693Sktlim@umich.edu regs.tanar = reg; 11052693Sktlim@umich.edu if (reg & TANAR_PS2) 11068887Sgeoffrey.blake@arm.com panic("this isn't used in driver, something wrong!\n"); 11072693Sktlim@umich.edu 11082732Sktlim@umich.edu if (reg & TANAR_PS1) 11092693Sktlim@umich.edu panic("this isn't used in driver, something wrong!\n"); 11102693Sktlim@umich.edu break; 11112693Sktlim@umich.edu 11128727Snilay@cs.wisc.edu case TANLPAR: 11138727Snilay@cs.wisc.edu panic("this should only be written to by the fake phy!\n"); 11148727Snilay@cs.wisc.edu 11158727Snilay@cs.wisc.edu case TANER: 11162693Sktlim@umich.edu panic("TANER is read only register!\n"); 11172693Sktlim@umich.edu 11182693Sktlim@umich.edu case TESR: 11192693Sktlim@umich.edu regs.tesr = reg; 11202693Sktlim@umich.edu break; 11212678Sktlim@umich.edu 11222678Sktlim@umich.edu default: 11232678Sktlim@umich.edu panic("invalid register access daddr=%#x", daddr); 11242678Sktlim@umich.edu } 11252678Sktlim@umich.edu } else { 11262678Sktlim@umich.edu panic("Invalid Request Size"); 11272678Sktlim@umich.edu } 11282727Sktlim@umich.edu 11292678Sktlim@umich.edu return No_Fault; 11302678Sktlim@umich.edu} 11312678Sktlim@umich.edu 11322678Sktlim@umich.eduvoid 11332678Sktlim@umich.eduNSGigE::devIntrPost(uint32_t interrupts) 11342678Sktlim@umich.edu{ 113510575SMarco.Elver@ARM.com if (interrupts & ISR_RESERVE) 113610575SMarco.Elver@ARM.com panic("Cannot set a reserved interrupt"); 113710575SMarco.Elver@ARM.com 113810575SMarco.Elver@ARM.com if (interrupts & ISR_NOIMPL) 113910575SMarco.Elver@ARM.com warn("interrupt not implemented %#x\n", interrupts); 114010575SMarco.Elver@ARM.com 114110575SMarco.Elver@ARM.com interrupts &= ~ISR_NOIMPL; 114210575SMarco.Elver@ARM.com regs.isr |= interrupts; 114310575SMarco.Elver@ARM.com 114410575SMarco.Elver@ARM.com if (interrupts & regs.imr) { 114510575SMarco.Elver@ARM.com if (interrupts & ISR_SWI) { 114610575SMarco.Elver@ARM.com totalSwi++; 114710575SMarco.Elver@ARM.com } 114810575SMarco.Elver@ARM.com if (interrupts & ISR_RXIDLE) { 11492678Sktlim@umich.edu totalRxIdle++; 11502678Sktlim@umich.edu } 11512678Sktlim@umich.edu if (interrupts & ISR_RXOK) { 11522678Sktlim@umich.edu totalRxOk++; 11532678Sktlim@umich.edu } 11542678Sktlim@umich.edu if (interrupts & ISR_RXDESC) { 11557598Sminkyu.jeong@arm.com totalRxDesc++; 11567598Sminkyu.jeong@arm.com } 11577598Sminkyu.jeong@arm.com if (interrupts & ISR_TXOK) { 11582678Sktlim@umich.edu totalTxOk++; 11592678Sktlim@umich.edu } 11602678Sktlim@umich.edu if (interrupts & ISR_TXIDLE) { 11612678Sktlim@umich.edu totalTxIdle++; 11622292SN/A } 11632292SN/A if (interrupts & ISR_TXDESC) { 11642292SN/A totalTxDesc++; 11652292SN/A } 11662292SN/A if (interrupts & ISR_RXORN) { 11672292SN/A totalRxOrn++; 11682292SN/A } 11692292SN/A } 11703126Sktlim@umich.edu 11712292SN/A DPRINTF(EthernetIntr, 11722292SN/A "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 11732292SN/A interrupts, regs.isr, regs.imr); 11742292SN/A 11752292SN/A if ((regs.isr & regs.imr)) { 11762292SN/A Tick when = curTick; 11772292SN/A if (!(regs.isr & regs.imr & ISR_NODELAY)) 11782292SN/A when += intrDelay; 11792292SN/A cpuIntrPost(when); 11802292SN/A } 11812292SN/A} 11822292SN/A 11832292SN/A/* writing this interrupt counting stats inside this means that this function 11842329SN/A is now limited to being used to clear all interrupts upon the kernel 11852329SN/A reading isr and servicing. just telling you in case you were thinking 11862329SN/A of expanding use. 11872292SN/A*/ 11889527SMatt.Horsnell@arm.comvoid 11899527SMatt.Horsnell@arm.comNSGigE::devIntrClear(uint32_t interrupts) 11909527SMatt.Horsnell@arm.com{ 11919527SMatt.Horsnell@arm.com if (interrupts & ISR_RESERVE) 11929527SMatt.Horsnell@arm.com panic("Cannot clear a reserved interrupt"); 11939527SMatt.Horsnell@arm.com 11949527SMatt.Horsnell@arm.com if (regs.isr & regs.imr & ISR_SWI) { 11952292SN/A postedSwi++; 11962292SN/A } 11972292SN/A if (regs.isr & regs.imr & ISR_RXIDLE) { 11982292SN/A postedRxIdle++; 11992292SN/A } 12002292SN/A if (regs.isr & regs.imr & ISR_RXOK) { 12012292SN/A postedRxOk++; 12022292SN/A } 12032292SN/A if (regs.isr & regs.imr & ISR_RXDESC) { 12042316SN/A postedRxDesc++; 12052316SN/A } 12062329SN/A if (regs.isr & regs.imr & ISR_TXOK) { 12078727Snilay@cs.wisc.edu postedTxOk++; 12088727Snilay@cs.wisc.edu } 12098727Snilay@cs.wisc.edu if (regs.isr & regs.imr & ISR_TXIDLE) { 12108727Snilay@cs.wisc.edu postedTxIdle++; 12112329SN/A } 12122329SN/A if (regs.isr & regs.imr & ISR_TXDESC) { 12132329SN/A postedTxDesc++; 12142316SN/A } 12152732Sktlim@umich.edu if (regs.isr & regs.imr & ISR_RXORN) { 12162316SN/A postedRxOrn++; 12172292SN/A } 12182292SN/A 12192292SN/A if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC | 12206974Stjones1@inf.ed.ac.uk ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) ) 12216974Stjones1@inf.ed.ac.uk postedInterrupts++; 12226974Stjones1@inf.ed.ac.uk 12238975Sandreas.hansson@arm.com interrupts &= ~ISR_NOIMPL; 12246974Stjones1@inf.ed.ac.uk regs.isr &= ~interrupts; 12256974Stjones1@inf.ed.ac.uk 12266974Stjones1@inf.ed.ac.uk DPRINTF(EthernetIntr, 12276974Stjones1@inf.ed.ac.uk "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 12286974Stjones1@inf.ed.ac.uk interrupts, regs.isr, regs.imr); 12296974Stjones1@inf.ed.ac.uk 12306974Stjones1@inf.ed.ac.uk if (!(regs.isr & regs.imr)) 12316974Stjones1@inf.ed.ac.uk cpuIntrClear(); 12326974Stjones1@inf.ed.ac.uk} 12336974Stjones1@inf.ed.ac.uk 12346974Stjones1@inf.ed.ac.ukvoid 12352693Sktlim@umich.eduNSGigE::devIntrChangeMask() 12362693Sktlim@umich.edu{ 12372693Sktlim@umich.edu DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 12382698Sktlim@umich.edu regs.isr, regs.imr, regs.isr & regs.imr); 12394985Sktlim@umich.edu 12402698Sktlim@umich.edu if (regs.isr & regs.imr) 12412693Sktlim@umich.edu cpuIntrPost(curTick); 12428587Snilay@cs.wisc.edu else 12438587Snilay@cs.wisc.edu cpuIntrClear(); 12448587Snilay@cs.wisc.edu} 12458975Sandreas.hansson@arm.com 12466974Stjones1@inf.ed.ac.ukvoid 12478133SAli.Saidi@ARM.comNSGigE::cpuIntrPost(Tick when) 12488133SAli.Saidi@ARM.com{ 12498133SAli.Saidi@ARM.com // If the interrupt you want to post is later than an interrupt 12506974Stjones1@inf.ed.ac.uk // already scheduled, just let it post in the coming one and don't 12516974Stjones1@inf.ed.ac.uk // schedule another. 12522699Sktlim@umich.edu // HOWEVER, must be sure that the scheduled intrTick is in the 12532693Sktlim@umich.edu // future (this was formerly the source of a bug) 12546974Stjones1@inf.ed.ac.uk /** 12556974Stjones1@inf.ed.ac.uk * @todo this warning should be removed and the intrTick code should 12566974Stjones1@inf.ed.ac.uk * be fixed. 12576974Stjones1@inf.ed.ac.uk */ 12586974Stjones1@inf.ed.ac.uk assert(when >= curTick); 12596974Stjones1@inf.ed.ac.uk assert(intrTick >= curTick || intrTick == 0); 12606974Stjones1@inf.ed.ac.uk if (when > intrTick && intrTick != 0) { 12616974Stjones1@inf.ed.ac.uk DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 12622693Sktlim@umich.edu intrTick); 12632693Sktlim@umich.edu return; 12642727Sktlim@umich.edu } 12652693Sktlim@umich.edu 12662693Sktlim@umich.edu intrTick = when; 12672693Sktlim@umich.edu if (intrTick < curTick) { 12682693Sktlim@umich.edu debug_break(); 12692693Sktlim@umich.edu intrTick = curTick; 12702292SN/A } 12719440SAndreas.Sandberg@ARM.com 12722292SN/A DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 12732292SN/A intrTick); 12742292SN/A 12752292SN/A if (intrEvent) 12762292SN/A intrEvent->squash(); 12772292SN/A intrEvent = new IntrEvent(this, true); 12782292SN/A intrEvent->schedule(intrTick); 12799440SAndreas.Sandberg@ARM.com} 12802292SN/A 12812292SN/Avoid 12822292SN/ANSGigE::cpuInterrupt() 12832292SN/A{ 12842292SN/A assert(intrTick == curTick); 12852292SN/A 12862292SN/A // Whether or not there's a pending interrupt, we don't care about 12879440SAndreas.Sandberg@ARM.com // it anymore 12882292SN/A intrEvent = 0; 12892292SN/A intrTick = 0; 12902292SN/A 12912292SN/A // Don't send an interrupt if there's already one 12922292SN/A if (cpuPendingIntr) { 12932292SN/A DPRINTF(EthernetIntr, 12942292SN/A "would send an interrupt now, but there's already pending\n"); 12959440SAndreas.Sandberg@ARM.com } else { 12962292SN/A // Send interrupt 12972292SN/A cpuPendingIntr = true; 12982292SN/A 12992292SN/A DPRINTF(EthernetIntr, "posting interrupt\n"); 13002329SN/A intrPost(); 13012329SN/A } 13022329SN/A} 13039440SAndreas.Sandberg@ARM.com 13042329SN/Avoid 13052329SN/ANSGigE::cpuIntrClear() 13062329SN/A{ 13072329SN/A if (!cpuPendingIntr) 13082329SN/A return; 13092329SN/A 13102329SN/A if (intrEvent) { 13112329SN/A intrEvent->squash(); 13129440SAndreas.Sandberg@ARM.com intrEvent = 0; 13139440SAndreas.Sandberg@ARM.com } 13142329SN/A 13152329SN/A intrTick = 0; 13162329SN/A 13179440SAndreas.Sandberg@ARM.com cpuPendingIntr = false; 13182329SN/A 13192329SN/A DPRINTF(EthernetIntr, "clearing interrupt\n"); 13202329SN/A intrClear(); 13212329SN/A} 13222329SN/A 13232329SN/Abool 13242329SN/ANSGigE::cpuIntrPending() const 13259440SAndreas.Sandberg@ARM.com{ return cpuPendingIntr; } 13269440SAndreas.Sandberg@ARM.com 13272329SN/Avoid 13282329SN/ANSGigE::txReset() 13292329SN/A{ 13302329SN/A 13312329SN/A DPRINTF(Ethernet, "transmit reset\n"); 13322329SN/A 13339944Smatt.horsnell@ARM.com CTDD = false; 13349944Smatt.horsnell@ARM.com txEnable = false;; 1335 txFragPtr = 0; 1336 assert(txDescCnt == 0); 1337 txFifo.clear(); 1338 txState = txIdle; 1339 assert(txDmaState == dmaIdle); 1340} 1341 1342void 1343NSGigE::rxReset() 1344{ 1345 DPRINTF(Ethernet, "receive reset\n"); 1346 1347 CRDD = false; 1348 assert(rxPktBytes == 0); 1349 rxEnable = false; 1350 rxFragPtr = 0; 1351 assert(rxDescCnt == 0); 1352 assert(rxDmaState == dmaIdle); 1353 rxFifo.clear(); 1354 rxState = rxIdle; 1355} 1356 1357void 1358NSGigE::regsReset() 1359{ 1360 memset(®s, 0, sizeof(regs)); 1361 regs.config = CFGR_LNKSTS; 1362 regs.mear = 0x22; 1363 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1364 // fill threshold to 32 bytes 1365 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1366 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1367 regs.mibc = MIBC_FRZ; 1368 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1369 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1370 1371 extstsEnable = false; 1372 acceptBroadcast = false; 1373 acceptMulticast = false; 1374 acceptUnicast = false; 1375 acceptPerfect = false; 1376 acceptArp = false; 1377} 1378 1379void 1380NSGigE::rxDmaReadCopy() 1381{ 1382 assert(rxDmaState == dmaReading); 1383 1384 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1385 rxDmaState = dmaIdle; 1386 1387 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1388 rxDmaAddr, rxDmaLen); 1389 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1390} 1391 1392bool 1393NSGigE::doRxDmaRead() 1394{ 1395 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1396 rxDmaState = dmaReading; 1397 1398 if (dmaInterface && !rxDmaFree) { 1399 if (dmaInterface->busy()) 1400 rxDmaState = dmaReadWaiting; 1401 else 1402 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1403 &rxDmaReadEvent, true); 1404 return true; 1405 } 1406 1407 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1408 rxDmaReadCopy(); 1409 return false; 1410 } 1411 1412 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1413 Tick start = curTick + dmaReadDelay + factor; 1414 rxDmaReadEvent.schedule(start); 1415 return true; 1416} 1417 1418void 1419NSGigE::rxDmaReadDone() 1420{ 1421 assert(rxDmaState == dmaReading); 1422 rxDmaReadCopy(); 1423 1424 // If the transmit state machine has a pending DMA, let it go first 1425 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1426 txKick(); 1427 1428 rxKick(); 1429} 1430 1431void 1432NSGigE::rxDmaWriteCopy() 1433{ 1434 assert(rxDmaState == dmaWriting); 1435 1436 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1437 rxDmaState = dmaIdle; 1438 1439 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1440 rxDmaAddr, rxDmaLen); 1441 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1442} 1443 1444bool 1445NSGigE::doRxDmaWrite() 1446{ 1447 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1448 rxDmaState = dmaWriting; 1449 1450 if (dmaInterface && !rxDmaFree) { 1451 if (dmaInterface->busy()) 1452 rxDmaState = dmaWriteWaiting; 1453 else 1454 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1455 &rxDmaWriteEvent, true); 1456 return true; 1457 } 1458 1459 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1460 rxDmaWriteCopy(); 1461 return false; 1462 } 1463 1464 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1465 Tick start = curTick + dmaWriteDelay + factor; 1466 rxDmaWriteEvent.schedule(start); 1467 return true; 1468} 1469 1470void 1471NSGigE::rxDmaWriteDone() 1472{ 1473 assert(rxDmaState == dmaWriting); 1474 rxDmaWriteCopy(); 1475 1476 // If the transmit state machine has a pending DMA, let it go first 1477 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1478 txKick(); 1479 1480 rxKick(); 1481} 1482 1483void 1484NSGigE::rxKick() 1485{ 1486 DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", 1487 NsRxStateStrings[rxState], rxFifo.size()); 1488 1489 if (rxKickTick > curTick) { 1490 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1491 rxKickTick); 1492 return; 1493 } 1494 1495 next: 1496 switch(rxDmaState) { 1497 case dmaReadWaiting: 1498 if (doRxDmaRead()) 1499 goto exit; 1500 break; 1501 case dmaWriteWaiting: 1502 if (doRxDmaWrite()) 1503 goto exit; 1504 break; 1505 default: 1506 break; 1507 } 1508 1509 // see state machine from spec for details 1510 // the way this works is, if you finish work on one state and can 1511 // go directly to another, you do that through jumping to the 1512 // label "next". however, if you have intermediate work, like DMA 1513 // so that you can't go to the next state yet, you go to exit and 1514 // exit the loop. however, when the DMA is done it will trigger 1515 // an event and come back to this loop. 1516 switch (rxState) { 1517 case rxIdle: 1518 if (!rxEnable) { 1519 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1520 goto exit; 1521 } 1522 1523 if (CRDD) { 1524 rxState = rxDescRefr; 1525 1526 rxDmaAddr = regs.rxdp & 0x3fffffff; 1527 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1528 rxDmaLen = sizeof(rxDescCache.link); 1529 rxDmaFree = dmaDescFree; 1530 1531 descDmaReads++; 1532 descDmaRdBytes += rxDmaLen; 1533 1534 if (doRxDmaRead()) 1535 goto exit; 1536 } else { 1537 rxState = rxDescRead; 1538 1539 rxDmaAddr = regs.rxdp & 0x3fffffff; 1540 rxDmaData = &rxDescCache; 1541 rxDmaLen = sizeof(ns_desc); 1542 rxDmaFree = dmaDescFree; 1543 1544 descDmaReads++; 1545 descDmaRdBytes += rxDmaLen; 1546 1547 if (doRxDmaRead()) 1548 goto exit; 1549 } 1550 break; 1551 1552 case rxDescRefr: 1553 if (rxDmaState != dmaIdle) 1554 goto exit; 1555 1556 rxState = rxAdvance; 1557 break; 1558 1559 case rxDescRead: 1560 if (rxDmaState != dmaIdle) 1561 goto exit; 1562 1563 DPRINTF(EthernetDesc, 1564 "rxDescCache: addr=%08x read descriptor\n", 1565 regs.rxdp & 0x3fffffff); 1566 DPRINTF(EthernetDesc, 1567 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1568 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1569 rxDescCache.extsts); 1570 1571 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1572 devIntrPost(ISR_RXIDLE); 1573 rxState = rxIdle; 1574 goto exit; 1575 } else { 1576 rxState = rxFifoBlock; 1577 rxFragPtr = rxDescCache.bufptr; 1578 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1579 } 1580 break; 1581 1582 case rxFifoBlock: 1583 if (!rxPacket) { 1584 /** 1585 * @todo in reality, we should be able to start processing 1586 * the packet as it arrives, and not have to wait for the 1587 * full packet ot be in the receive fifo. 1588 */ 1589 if (rxFifo.empty()) 1590 goto exit; 1591 1592 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1593 1594 // If we don't have a packet, grab a new one from the fifo. 1595 rxPacket = rxFifo.front(); 1596 rxPktBytes = rxPacket->length; 1597 rxPacketBufPtr = rxPacket->data; 1598 1599#if TRACING_ON 1600 if (DTRACE(Ethernet)) { 1601 IpPtr ip(rxPacket); 1602 if (ip) { 1603 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1604 TcpPtr tcp(ip); 1605 if (tcp) { 1606 DPRINTF(Ethernet, 1607 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1608 tcp->sport(), tcp->dport(), tcp->seq(), 1609 tcp->ack()); 1610 } 1611 } 1612 } 1613#endif 1614 1615 // sanity check - i think the driver behaves like this 1616 assert(rxDescCnt >= rxPktBytes); 1617 rxFifo.pop(); 1618 } 1619 1620 1621 // dont' need the && rxDescCnt > 0 if driver sanity check 1622 // above holds 1623 if (rxPktBytes > 0) { 1624 rxState = rxFragWrite; 1625 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1626 // check holds 1627 rxXferLen = rxPktBytes; 1628 1629 rxDmaAddr = rxFragPtr & 0x3fffffff; 1630 rxDmaData = rxPacketBufPtr; 1631 rxDmaLen = rxXferLen; 1632 rxDmaFree = dmaDataFree; 1633 1634 if (doRxDmaWrite()) 1635 goto exit; 1636 1637 } else { 1638 rxState = rxDescWrite; 1639 1640 //if (rxPktBytes == 0) { /* packet is done */ 1641 assert(rxPktBytes == 0); 1642 DPRINTF(EthernetSM, "done with receiving packet\n"); 1643 1644 rxDescCache.cmdsts |= CMDSTS_OWN; 1645 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1646 rxDescCache.cmdsts |= CMDSTS_OK; 1647 rxDescCache.cmdsts &= 0xffff0000; 1648 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1649 1650#if 0 1651 /* 1652 * all the driver uses these are for its own stats keeping 1653 * which we don't care about, aren't necessary for 1654 * functionality and doing this would just slow us down. 1655 * if they end up using this in a later version for 1656 * functional purposes, just undef 1657 */ 1658 if (rxFilterEnable) { 1659 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1660 const EthAddr &dst = rxFifoFront()->dst(); 1661 if (dst->unicast()) 1662 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1663 if (dst->multicast()) 1664 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1665 if (dst->broadcast()) 1666 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1667 } 1668#endif 1669 1670 IpPtr ip(rxPacket); 1671 if (extstsEnable && ip) { 1672 rxDescCache.extsts |= EXTSTS_IPPKT; 1673 rxIpChecksums++; 1674 if (cksum(ip) != 0) { 1675 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1676 rxDescCache.extsts |= EXTSTS_IPERR; 1677 } 1678 TcpPtr tcp(ip); 1679 UdpPtr udp(ip); 1680 if (tcp) { 1681 rxDescCache.extsts |= EXTSTS_TCPPKT; 1682 rxTcpChecksums++; 1683 if (cksum(tcp) != 0) { 1684 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1685 rxDescCache.extsts |= EXTSTS_TCPERR; 1686 1687 } 1688 } else if (udp) { 1689 rxDescCache.extsts |= EXTSTS_UDPPKT; 1690 rxUdpChecksums++; 1691 if (cksum(udp) != 0) { 1692 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1693 rxDescCache.extsts |= EXTSTS_UDPERR; 1694 } 1695 } 1696 } 1697 rxPacket = 0; 1698 1699 /* 1700 * the driver seems to always receive into desc buffers 1701 * of size 1514, so you never have a pkt that is split 1702 * into multiple descriptors on the receive side, so 1703 * i don't implement that case, hence the assert above. 1704 */ 1705 1706 DPRINTF(EthernetDesc, 1707 "rxDescCache: addr=%08x writeback cmdsts extsts\n", 1708 regs.rxdp & 0x3fffffff); 1709 DPRINTF(EthernetDesc, 1710 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1711 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1712 rxDescCache.extsts); 1713 1714 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1715 rxDmaData = &(rxDescCache.cmdsts); 1716 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1717 rxDmaFree = dmaDescFree; 1718 1719 descDmaWrites++; 1720 descDmaWrBytes += rxDmaLen; 1721 1722 if (doRxDmaWrite()) 1723 goto exit; 1724 } 1725 break; 1726 1727 case rxFragWrite: 1728 if (rxDmaState != dmaIdle) 1729 goto exit; 1730 1731 rxPacketBufPtr += rxXferLen; 1732 rxFragPtr += rxXferLen; 1733 rxPktBytes -= rxXferLen; 1734 1735 rxState = rxFifoBlock; 1736 break; 1737 1738 case rxDescWrite: 1739 if (rxDmaState != dmaIdle) 1740 goto exit; 1741 1742 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1743 1744 assert(rxPacket == 0); 1745 devIntrPost(ISR_RXOK); 1746 1747 if (rxDescCache.cmdsts & CMDSTS_INTR) 1748 devIntrPost(ISR_RXDESC); 1749 1750 if (!rxEnable) { 1751 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1752 rxState = rxIdle; 1753 goto exit; 1754 } else 1755 rxState = rxAdvance; 1756 break; 1757 1758 case rxAdvance: 1759 if (rxDescCache.link == 0) { 1760 devIntrPost(ISR_RXIDLE); 1761 rxState = rxIdle; 1762 CRDD = true; 1763 goto exit; 1764 } else { 1765 rxState = rxDescRead; 1766 regs.rxdp = rxDescCache.link; 1767 CRDD = false; 1768 1769 rxDmaAddr = regs.rxdp & 0x3fffffff; 1770 rxDmaData = &rxDescCache; 1771 rxDmaLen = sizeof(ns_desc); 1772 rxDmaFree = dmaDescFree; 1773 1774 if (doRxDmaRead()) 1775 goto exit; 1776 } 1777 break; 1778 1779 default: 1780 panic("Invalid rxState!"); 1781 } 1782 1783 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1784 NsRxStateStrings[rxState]); 1785 1786 goto next; 1787 1788 exit: 1789 /** 1790 * @todo do we want to schedule a future kick? 1791 */ 1792 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1793 NsRxStateStrings[rxState]); 1794} 1795 1796void 1797NSGigE::transmit() 1798{ 1799 if (txFifo.empty()) { 1800 DPRINTF(Ethernet, "nothing to transmit\n"); 1801 return; 1802 } 1803 1804 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1805 txFifo.size()); 1806 if (interface->sendPacket(txFifo.front())) { 1807#if TRACING_ON 1808 if (DTRACE(Ethernet)) { 1809 IpPtr ip(txFifo.front()); 1810 if (ip) { 1811 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1812 TcpPtr tcp(ip); 1813 if (tcp) { 1814 DPRINTF(Ethernet, 1815 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1816 tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack()); 1817 } 1818 } 1819 } 1820#endif 1821 1822 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1823 txBytes += txFifo.front()->length; 1824 txPackets++; 1825 1826 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1827 txFifo.avail()); 1828 txFifo.pop(); 1829 1830 /* 1831 * normally do a writeback of the descriptor here, and ONLY 1832 * after that is done, send this interrupt. but since our 1833 * stuff never actually fails, just do this interrupt here, 1834 * otherwise the code has to stray from this nice format. 1835 * besides, it's functionally the same. 1836 */ 1837 devIntrPost(ISR_TXOK); 1838 } 1839 1840 if (!txFifo.empty() && !txEvent.scheduled()) { 1841 DPRINTF(Ethernet, "reschedule transmit\n"); 1842 txEvent.schedule(curTick + retryTime); 1843 } 1844} 1845 1846void 1847NSGigE::txDmaReadCopy() 1848{ 1849 assert(txDmaState == dmaReading); 1850 1851 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 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 1859bool 1860NSGigE::doTxDmaRead() 1861{ 1862 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1863 txDmaState = dmaReading; 1864 1865 if (dmaInterface && !txDmaFree) { 1866 if (dmaInterface->busy()) 1867 txDmaState = dmaReadWaiting; 1868 else 1869 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1870 &txDmaReadEvent, true); 1871 return true; 1872 } 1873 1874 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1875 txDmaReadCopy(); 1876 return false; 1877 } 1878 1879 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1880 Tick start = curTick + dmaReadDelay + factor; 1881 txDmaReadEvent.schedule(start); 1882 return true; 1883} 1884 1885void 1886NSGigE::txDmaReadDone() 1887{ 1888 assert(txDmaState == dmaReading); 1889 txDmaReadCopy(); 1890 1891 // If the receive state machine has a pending DMA, let it go first 1892 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1893 rxKick(); 1894 1895 txKick(); 1896} 1897 1898void 1899NSGigE::txDmaWriteCopy() 1900{ 1901 assert(txDmaState == dmaWriting); 1902 1903 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1904 txDmaState = dmaIdle; 1905 1906 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1907 txDmaAddr, txDmaLen); 1908 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1909} 1910 1911bool 1912NSGigE::doTxDmaWrite() 1913{ 1914 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1915 txDmaState = dmaWriting; 1916 1917 if (dmaInterface && !txDmaFree) { 1918 if (dmaInterface->busy()) 1919 txDmaState = dmaWriteWaiting; 1920 else 1921 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1922 &txDmaWriteEvent, true); 1923 return true; 1924 } 1925 1926 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1927 txDmaWriteCopy(); 1928 return false; 1929 } 1930 1931 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1932 Tick start = curTick + dmaWriteDelay + factor; 1933 txDmaWriteEvent.schedule(start); 1934 return true; 1935} 1936 1937void 1938NSGigE::txDmaWriteDone() 1939{ 1940 assert(txDmaState == dmaWriting); 1941 txDmaWriteCopy(); 1942 1943 // If the receive state machine has a pending DMA, let it go first 1944 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1945 rxKick(); 1946 1947 txKick(); 1948} 1949 1950void 1951NSGigE::txKick() 1952{ 1953 DPRINTF(EthernetSM, "transmit kick txState=%s\n", 1954 NsTxStateStrings[txState]); 1955 1956 if (txKickTick > curTick) { 1957 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1958 txKickTick); 1959 1960 return; 1961 } 1962 1963 next: 1964 switch(txDmaState) { 1965 case dmaReadWaiting: 1966 if (doTxDmaRead()) 1967 goto exit; 1968 break; 1969 case dmaWriteWaiting: 1970 if (doTxDmaWrite()) 1971 goto exit; 1972 break; 1973 default: 1974 break; 1975 } 1976 1977 switch (txState) { 1978 case txIdle: 1979 if (!txEnable) { 1980 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1981 goto exit; 1982 } 1983 1984 if (CTDD) { 1985 txState = txDescRefr; 1986 1987 txDmaAddr = regs.txdp & 0x3fffffff; 1988 txDmaData = &txDescCache + offsetof(ns_desc, link); 1989 txDmaLen = sizeof(txDescCache.link); 1990 txDmaFree = dmaDescFree; 1991 1992 descDmaReads++; 1993 descDmaRdBytes += txDmaLen; 1994 1995 if (doTxDmaRead()) 1996 goto exit; 1997 1998 } else { 1999 txState = txDescRead; 2000 2001 txDmaAddr = regs.txdp & 0x3fffffff; 2002 txDmaData = &txDescCache; 2003 txDmaLen = sizeof(ns_desc); 2004 txDmaFree = dmaDescFree; 2005 2006 descDmaReads++; 2007 descDmaRdBytes += txDmaLen; 2008 2009 if (doTxDmaRead()) 2010 goto exit; 2011 } 2012 break; 2013 2014 case txDescRefr: 2015 if (txDmaState != dmaIdle) 2016 goto exit; 2017 2018 txState = txAdvance; 2019 break; 2020 2021 case txDescRead: 2022 if (txDmaState != dmaIdle) 2023 goto exit; 2024 2025 DPRINTF(EthernetDesc, 2026 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 2027 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 2028 txDescCache.extsts); 2029 2030 if (txDescCache.cmdsts & CMDSTS_OWN) { 2031 txState = txFifoBlock; 2032 txFragPtr = txDescCache.bufptr; 2033 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 2034 } else { 2035 devIntrPost(ISR_TXIDLE); 2036 txState = txIdle; 2037 goto exit; 2038 } 2039 break; 2040 2041 case txFifoBlock: 2042 if (!txPacket) { 2043 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2044 txPacket = new PacketData(16384); 2045 txPacketBufPtr = txPacket->data; 2046 } 2047 2048 if (txDescCnt == 0) { 2049 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 2050 if (txDescCache.cmdsts & CMDSTS_MORE) { 2051 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2052 txState = txDescWrite; 2053 2054 txDescCache.cmdsts &= ~CMDSTS_OWN; 2055 2056 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2057 txDmaAddr &= 0x3fffffff; 2058 txDmaData = &(txDescCache.cmdsts); 2059 txDmaLen = sizeof(txDescCache.cmdsts); 2060 txDmaFree = dmaDescFree; 2061 2062 if (doTxDmaWrite()) 2063 goto exit; 2064 2065 } else { /* this packet is totally done */ 2066 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2067 /* deal with the the packet that just finished */ 2068 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2069 IpPtr ip(txPacket); 2070 if (txDescCache.extsts & EXTSTS_UDPPKT) { 2071 UdpPtr udp(ip); 2072 udp->sum(0); 2073 udp->sum(cksum(udp)); 2074 txUdpChecksums++; 2075 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 2076 TcpPtr tcp(ip); 2077 tcp->sum(0); 2078 tcp->sum(cksum(tcp)); 2079 txTcpChecksums++; 2080 } 2081 if (txDescCache.extsts & EXTSTS_IPPKT) { 2082 ip->sum(0); 2083 ip->sum(cksum(ip)); 2084 txIpChecksums++; 2085 } 2086 } 2087 2088 txPacket->length = txPacketBufPtr - txPacket->data; 2089 // this is just because the receive can't handle a 2090 // packet bigger want to make sure 2091 assert(txPacket->length <= 1514); 2092#ifndef NDEBUG 2093 bool success = 2094#endif 2095 txFifo.push(txPacket); 2096 assert(success); 2097 2098 /* 2099 * this following section is not tqo spec, but 2100 * functionally shouldn't be any different. normally, 2101 * the chip will wait til the transmit has occurred 2102 * before writing back the descriptor because it has 2103 * to wait to see that it was successfully transmitted 2104 * to decide whether to set CMDSTS_OK or not. 2105 * however, in the simulator since it is always 2106 * successfully transmitted, and writing it exactly to 2107 * spec would complicate the code, we just do it here 2108 */ 2109 2110 txDescCache.cmdsts &= ~CMDSTS_OWN; 2111 txDescCache.cmdsts |= CMDSTS_OK; 2112 2113 DPRINTF(EthernetDesc, 2114 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2115 txDescCache.cmdsts, txDescCache.extsts); 2116 2117 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2118 txDmaAddr &= 0x3fffffff; 2119 txDmaData = &(txDescCache.cmdsts); 2120 txDmaLen = sizeof(txDescCache.cmdsts) + 2121 sizeof(txDescCache.extsts); 2122 txDmaFree = dmaDescFree; 2123 2124 descDmaWrites++; 2125 descDmaWrBytes += txDmaLen; 2126 2127 transmit(); 2128 txPacket = 0; 2129 2130 if (!txEnable) { 2131 DPRINTF(EthernetSM, "halting TX state machine\n"); 2132 txState = txIdle; 2133 goto exit; 2134 } else 2135 txState = txAdvance; 2136 2137 if (doTxDmaWrite()) 2138 goto exit; 2139 } 2140 } else { 2141 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2142 if (!txFifo.full()) { 2143 txState = txFragRead; 2144 2145 /* 2146 * The number of bytes transferred is either whatever 2147 * is left in the descriptor (txDescCnt), or if there 2148 * is not enough room in the fifo, just whatever room 2149 * is left in the fifo 2150 */ 2151 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2152 2153 txDmaAddr = txFragPtr & 0x3fffffff; 2154 txDmaData = txPacketBufPtr; 2155 txDmaLen = txXferLen; 2156 txDmaFree = dmaDataFree; 2157 2158 if (doTxDmaRead()) 2159 goto exit; 2160 } else { 2161 txState = txFifoBlock; 2162 transmit(); 2163 2164 goto exit; 2165 } 2166 2167 } 2168 break; 2169 2170 case txFragRead: 2171 if (txDmaState != dmaIdle) 2172 goto exit; 2173 2174 txPacketBufPtr += txXferLen; 2175 txFragPtr += txXferLen; 2176 txDescCnt -= txXferLen; 2177 txFifo.reserve(txXferLen); 2178 2179 txState = txFifoBlock; 2180 break; 2181 2182 case txDescWrite: 2183 if (txDmaState != dmaIdle) 2184 goto exit; 2185 2186 if (txDescCache.cmdsts & CMDSTS_INTR) 2187 devIntrPost(ISR_TXDESC); 2188 2189 txState = txAdvance; 2190 break; 2191 2192 case txAdvance: 2193 if (txDescCache.link == 0) { 2194 devIntrPost(ISR_TXIDLE); 2195 txState = txIdle; 2196 goto exit; 2197 } else { 2198 txState = txDescRead; 2199 regs.txdp = txDescCache.link; 2200 CTDD = false; 2201 2202 txDmaAddr = txDescCache.link & 0x3fffffff; 2203 txDmaData = &txDescCache; 2204 txDmaLen = sizeof(ns_desc); 2205 txDmaFree = dmaDescFree; 2206 2207 if (doTxDmaRead()) 2208 goto exit; 2209 } 2210 break; 2211 2212 default: 2213 panic("invalid state"); 2214 } 2215 2216 DPRINTF(EthernetSM, "entering next txState=%s\n", 2217 NsTxStateStrings[txState]); 2218 2219 goto next; 2220 2221 exit: 2222 /** 2223 * @todo do we want to schedule a future kick? 2224 */ 2225 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2226 NsTxStateStrings[txState]); 2227} 2228 2229void 2230NSGigE::transferDone() 2231{ 2232 if (txFifo.empty()) { 2233 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2234 return; 2235 } 2236 2237 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2238 2239 if (txEvent.scheduled()) 2240 txEvent.reschedule(curTick + cycles(1)); 2241 else 2242 txEvent.schedule(curTick + cycles(1)); 2243} 2244 2245bool 2246NSGigE::rxFilter(const PacketPtr &packet) 2247{ 2248 EthPtr eth = packet; 2249 bool drop = true; 2250 string type; 2251 2252 const EthAddr &dst = eth->dst(); 2253 if (dst.unicast()) { 2254 // If we're accepting all unicast addresses 2255 if (acceptUnicast) 2256 drop = false; 2257 2258 // If we make a perfect match 2259 if (acceptPerfect && dst == rom.perfectMatch) 2260 drop = false; 2261 2262 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2263 drop = false; 2264 2265 } else if (dst.broadcast()) { 2266 // if we're accepting broadcasts 2267 if (acceptBroadcast) 2268 drop = false; 2269 2270 } else if (dst.multicast()) { 2271 // if we're accepting all multicasts 2272 if (acceptMulticast) 2273 drop = false; 2274 2275 } 2276 2277 if (drop) { 2278 DPRINTF(Ethernet, "rxFilter drop\n"); 2279 DDUMP(EthernetData, packet->data, packet->length); 2280 } 2281 2282 return drop; 2283} 2284 2285bool 2286NSGigE::recvPacket(PacketPtr packet) 2287{ 2288 rxBytes += packet->length; 2289 rxPackets++; 2290 2291 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2292 rxFifo.avail()); 2293 2294 if (!rxEnable) { 2295 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2296 debug_break(); 2297 interface->recvDone(); 2298 return true; 2299 } 2300 2301 if (rxFilterEnable && rxFilter(packet)) { 2302 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2303 interface->recvDone(); 2304 return true; 2305 } 2306 2307 if (rxFifo.avail() < packet->length) { 2308#if TRACING_ON 2309 IpPtr ip(packet); 2310 TcpPtr tcp(ip); 2311 if (ip) { 2312 DPRINTF(Ethernet, 2313 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2314 ip->id()); 2315 if (tcp) { 2316 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2317 } 2318 } 2319#endif 2320 droppedPackets++; 2321 devIntrPost(ISR_RXORN); 2322 return false; 2323 } 2324 2325 rxFifo.push(packet); 2326 interface->recvDone(); 2327 2328 rxKick(); 2329 return true; 2330} 2331 2332//===================================================================== 2333// 2334// 2335void 2336NSGigE::serialize(ostream &os) 2337{ 2338 // Serialize the PciDev base class 2339 PciDev::serialize(os); 2340 2341 /* 2342 * Finalize any DMA events now. 2343 */ 2344 if (rxDmaReadEvent.scheduled()) 2345 rxDmaReadCopy(); 2346 if (rxDmaWriteEvent.scheduled()) 2347 rxDmaWriteCopy(); 2348 if (txDmaReadEvent.scheduled()) 2349 txDmaReadCopy(); 2350 if (txDmaWriteEvent.scheduled()) 2351 txDmaWriteCopy(); 2352 2353 /* 2354 * Serialize the device registers 2355 */ 2356 SERIALIZE_SCALAR(regs.command); 2357 SERIALIZE_SCALAR(regs.config); 2358 SERIALIZE_SCALAR(regs.mear); 2359 SERIALIZE_SCALAR(regs.ptscr); 2360 SERIALIZE_SCALAR(regs.isr); 2361 SERIALIZE_SCALAR(regs.imr); 2362 SERIALIZE_SCALAR(regs.ier); 2363 SERIALIZE_SCALAR(regs.ihr); 2364 SERIALIZE_SCALAR(regs.txdp); 2365 SERIALIZE_SCALAR(regs.txdp_hi); 2366 SERIALIZE_SCALAR(regs.txcfg); 2367 SERIALIZE_SCALAR(regs.gpior); 2368 SERIALIZE_SCALAR(regs.rxdp); 2369 SERIALIZE_SCALAR(regs.rxdp_hi); 2370 SERIALIZE_SCALAR(regs.rxcfg); 2371 SERIALIZE_SCALAR(regs.pqcr); 2372 SERIALIZE_SCALAR(regs.wcsr); 2373 SERIALIZE_SCALAR(regs.pcr); 2374 SERIALIZE_SCALAR(regs.rfcr); 2375 SERIALIZE_SCALAR(regs.rfdr); 2376 SERIALIZE_SCALAR(regs.srr); 2377 SERIALIZE_SCALAR(regs.mibc); 2378 SERIALIZE_SCALAR(regs.vrcr); 2379 SERIALIZE_SCALAR(regs.vtcr); 2380 SERIALIZE_SCALAR(regs.vdr); 2381 SERIALIZE_SCALAR(regs.ccsr); 2382 SERIALIZE_SCALAR(regs.tbicr); 2383 SERIALIZE_SCALAR(regs.tbisr); 2384 SERIALIZE_SCALAR(regs.tanar); 2385 SERIALIZE_SCALAR(regs.tanlpar); 2386 SERIALIZE_SCALAR(regs.taner); 2387 SERIALIZE_SCALAR(regs.tesr); 2388 2389 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2390 2391 SERIALIZE_SCALAR(ioEnable); 2392 2393 /* 2394 * Serialize the data Fifos 2395 */ 2396 rxFifo.serialize("rxFifo", os); 2397 txFifo.serialize("txFifo", os); 2398 2399 /* 2400 * Serialize the various helper variables 2401 */ 2402 bool txPacketExists = txPacket; 2403 SERIALIZE_SCALAR(txPacketExists); 2404 if (txPacketExists) { 2405 txPacket->length = txPacketBufPtr - txPacket->data; 2406 txPacket->serialize("txPacket", os); 2407 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2408 SERIALIZE_SCALAR(txPktBufPtr); 2409 } 2410 2411 bool rxPacketExists = rxPacket; 2412 SERIALIZE_SCALAR(rxPacketExists); 2413 if (rxPacketExists) { 2414 rxPacket->serialize("rxPacket", os); 2415 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2416 SERIALIZE_SCALAR(rxPktBufPtr); 2417 } 2418 2419 SERIALIZE_SCALAR(txXferLen); 2420 SERIALIZE_SCALAR(rxXferLen); 2421 2422 /* 2423 * Serialize DescCaches 2424 */ 2425 SERIALIZE_SCALAR(txDescCache.link); 2426 SERIALIZE_SCALAR(txDescCache.bufptr); 2427 SERIALIZE_SCALAR(txDescCache.cmdsts); 2428 SERIALIZE_SCALAR(txDescCache.extsts); 2429 SERIALIZE_SCALAR(rxDescCache.link); 2430 SERIALIZE_SCALAR(rxDescCache.bufptr); 2431 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2432 SERIALIZE_SCALAR(rxDescCache.extsts); 2433 2434 /* 2435 * Serialize tx state machine 2436 */ 2437 int txState = this->txState; 2438 SERIALIZE_SCALAR(txState); 2439 SERIALIZE_SCALAR(txEnable); 2440 SERIALIZE_SCALAR(CTDD); 2441 SERIALIZE_SCALAR(txFragPtr); 2442 SERIALIZE_SCALAR(txDescCnt); 2443 int txDmaState = this->txDmaState; 2444 SERIALIZE_SCALAR(txDmaState); 2445 2446 /* 2447 * Serialize rx state machine 2448 */ 2449 int rxState = this->rxState; 2450 SERIALIZE_SCALAR(rxState); 2451 SERIALIZE_SCALAR(rxEnable); 2452 SERIALIZE_SCALAR(CRDD); 2453 SERIALIZE_SCALAR(rxPktBytes); 2454 SERIALIZE_SCALAR(rxFragPtr); 2455 SERIALIZE_SCALAR(rxDescCnt); 2456 int rxDmaState = this->rxDmaState; 2457 SERIALIZE_SCALAR(rxDmaState); 2458 2459 SERIALIZE_SCALAR(extstsEnable); 2460 2461 /* 2462 * If there's a pending transmit, store the time so we can 2463 * reschedule it later 2464 */ 2465 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2466 SERIALIZE_SCALAR(transmitTick); 2467 2468 /* 2469 * receive address filter settings 2470 */ 2471 SERIALIZE_SCALAR(rxFilterEnable); 2472 SERIALIZE_SCALAR(acceptBroadcast); 2473 SERIALIZE_SCALAR(acceptMulticast); 2474 SERIALIZE_SCALAR(acceptUnicast); 2475 SERIALIZE_SCALAR(acceptPerfect); 2476 SERIALIZE_SCALAR(acceptArp); 2477 2478 /* 2479 * Keep track of pending interrupt status. 2480 */ 2481 SERIALIZE_SCALAR(intrTick); 2482 SERIALIZE_SCALAR(cpuPendingIntr); 2483 Tick intrEventTick = 0; 2484 if (intrEvent) 2485 intrEventTick = intrEvent->when(); 2486 SERIALIZE_SCALAR(intrEventTick); 2487 2488} 2489 2490void 2491NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2492{ 2493 // Unserialize the PciDev base class 2494 PciDev::unserialize(cp, section); 2495 2496 UNSERIALIZE_SCALAR(regs.command); 2497 UNSERIALIZE_SCALAR(regs.config); 2498 UNSERIALIZE_SCALAR(regs.mear); 2499 UNSERIALIZE_SCALAR(regs.ptscr); 2500 UNSERIALIZE_SCALAR(regs.isr); 2501 UNSERIALIZE_SCALAR(regs.imr); 2502 UNSERIALIZE_SCALAR(regs.ier); 2503 UNSERIALIZE_SCALAR(regs.ihr); 2504 UNSERIALIZE_SCALAR(regs.txdp); 2505 UNSERIALIZE_SCALAR(regs.txdp_hi); 2506 UNSERIALIZE_SCALAR(regs.txcfg); 2507 UNSERIALIZE_SCALAR(regs.gpior); 2508 UNSERIALIZE_SCALAR(regs.rxdp); 2509 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2510 UNSERIALIZE_SCALAR(regs.rxcfg); 2511 UNSERIALIZE_SCALAR(regs.pqcr); 2512 UNSERIALIZE_SCALAR(regs.wcsr); 2513 UNSERIALIZE_SCALAR(regs.pcr); 2514 UNSERIALIZE_SCALAR(regs.rfcr); 2515 UNSERIALIZE_SCALAR(regs.rfdr); 2516 UNSERIALIZE_SCALAR(regs.srr); 2517 UNSERIALIZE_SCALAR(regs.mibc); 2518 UNSERIALIZE_SCALAR(regs.vrcr); 2519 UNSERIALIZE_SCALAR(regs.vtcr); 2520 UNSERIALIZE_SCALAR(regs.vdr); 2521 UNSERIALIZE_SCALAR(regs.ccsr); 2522 UNSERIALIZE_SCALAR(regs.tbicr); 2523 UNSERIALIZE_SCALAR(regs.tbisr); 2524 UNSERIALIZE_SCALAR(regs.tanar); 2525 UNSERIALIZE_SCALAR(regs.tanlpar); 2526 UNSERIALIZE_SCALAR(regs.taner); 2527 UNSERIALIZE_SCALAR(regs.tesr); 2528 2529 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2530 2531 UNSERIALIZE_SCALAR(ioEnable); 2532 2533 /* 2534 * unserialize the data fifos 2535 */ 2536 rxFifo.unserialize("rxFifo", cp, section); 2537 txFifo.unserialize("txFifo", cp, section); 2538 2539 /* 2540 * unserialize the various helper variables 2541 */ 2542 bool txPacketExists; 2543 UNSERIALIZE_SCALAR(txPacketExists); 2544 if (txPacketExists) { 2545 txPacket = new PacketData(16384); 2546 txPacket->unserialize("txPacket", cp, section); 2547 uint32_t txPktBufPtr; 2548 UNSERIALIZE_SCALAR(txPktBufPtr); 2549 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2550 } else 2551 txPacket = 0; 2552 2553 bool rxPacketExists; 2554 UNSERIALIZE_SCALAR(rxPacketExists); 2555 rxPacket = 0; 2556 if (rxPacketExists) { 2557 rxPacket = new PacketData(16384); 2558 rxPacket->unserialize("rxPacket", cp, section); 2559 uint32_t rxPktBufPtr; 2560 UNSERIALIZE_SCALAR(rxPktBufPtr); 2561 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2562 } else 2563 rxPacket = 0; 2564 2565 UNSERIALIZE_SCALAR(txXferLen); 2566 UNSERIALIZE_SCALAR(rxXferLen); 2567 2568 /* 2569 * Unserialize DescCaches 2570 */ 2571 UNSERIALIZE_SCALAR(txDescCache.link); 2572 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2573 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2574 UNSERIALIZE_SCALAR(txDescCache.extsts); 2575 UNSERIALIZE_SCALAR(rxDescCache.link); 2576 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2577 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2578 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2579 2580 /* 2581 * unserialize tx state machine 2582 */ 2583 int txState; 2584 UNSERIALIZE_SCALAR(txState); 2585 this->txState = (TxState) txState; 2586 UNSERIALIZE_SCALAR(txEnable); 2587 UNSERIALIZE_SCALAR(CTDD); 2588 UNSERIALIZE_SCALAR(txFragPtr); 2589 UNSERIALIZE_SCALAR(txDescCnt); 2590 int txDmaState; 2591 UNSERIALIZE_SCALAR(txDmaState); 2592 this->txDmaState = (DmaState) txDmaState; 2593 2594 /* 2595 * unserialize rx state machine 2596 */ 2597 int rxState; 2598 UNSERIALIZE_SCALAR(rxState); 2599 this->rxState = (RxState) rxState; 2600 UNSERIALIZE_SCALAR(rxEnable); 2601 UNSERIALIZE_SCALAR(CRDD); 2602 UNSERIALIZE_SCALAR(rxPktBytes); 2603 UNSERIALIZE_SCALAR(rxFragPtr); 2604 UNSERIALIZE_SCALAR(rxDescCnt); 2605 int rxDmaState; 2606 UNSERIALIZE_SCALAR(rxDmaState); 2607 this->rxDmaState = (DmaState) rxDmaState; 2608 2609 UNSERIALIZE_SCALAR(extstsEnable); 2610 2611 /* 2612 * If there's a pending transmit, reschedule it now 2613 */ 2614 Tick transmitTick; 2615 UNSERIALIZE_SCALAR(transmitTick); 2616 if (transmitTick) 2617 txEvent.schedule(curTick + transmitTick); 2618 2619 /* 2620 * unserialize receive address filter settings 2621 */ 2622 UNSERIALIZE_SCALAR(rxFilterEnable); 2623 UNSERIALIZE_SCALAR(acceptBroadcast); 2624 UNSERIALIZE_SCALAR(acceptMulticast); 2625 UNSERIALIZE_SCALAR(acceptUnicast); 2626 UNSERIALIZE_SCALAR(acceptPerfect); 2627 UNSERIALIZE_SCALAR(acceptArp); 2628 2629 /* 2630 * Keep track of pending interrupt status. 2631 */ 2632 UNSERIALIZE_SCALAR(intrTick); 2633 UNSERIALIZE_SCALAR(cpuPendingIntr); 2634 Tick intrEventTick; 2635 UNSERIALIZE_SCALAR(intrEventTick); 2636 if (intrEventTick) { 2637 intrEvent = new IntrEvent(this, true); 2638 intrEvent->schedule(intrEventTick); 2639 } 2640 2641 /* 2642 * re-add addrRanges to bus bridges 2643 */ 2644 if (pioInterface) { 2645 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 2646 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 2647 } 2648} 2649 2650Tick 2651NSGigE::cacheAccess(MemReqPtr &req) 2652{ 2653 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2654 req->paddr, req->paddr - addr); 2655 return curTick + pioLatency; 2656} 2657 2658BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2659 2660 SimObjectParam<EtherInt *> peer; 2661 SimObjectParam<NSGigE *> device; 2662 2663END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2664 2665BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2666 2667 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2668 INIT_PARAM(device, "Ethernet device of this interface") 2669 2670END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2671 2672CREATE_SIM_OBJECT(NSGigEInt) 2673{ 2674 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2675 2676 EtherInt *p = (EtherInt *)peer; 2677 if (p) { 2678 dev_int->setPeer(p); 2679 p->setPeer(dev_int); 2680 } 2681 2682 return dev_int; 2683} 2684 2685REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2686 2687 2688BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2689 2690 Param<Addr> addr; 2691 Param<Tick> clock; 2692 Param<Tick> tx_delay; 2693 Param<Tick> rx_delay; 2694 Param<Tick> intr_delay; 2695 SimObjectParam<MemoryController *> mmu; 2696 SimObjectParam<PhysicalMemory *> physmem; 2697 Param<bool> rx_filter; 2698 Param<string> hardware_address; 2699 SimObjectParam<Bus*> io_bus; 2700 SimObjectParam<Bus*> payload_bus; 2701 SimObjectParam<HierParams *> hier; 2702 Param<Tick> pio_latency; 2703 Param<bool> dma_desc_free; 2704 Param<bool> dma_data_free; 2705 Param<Tick> dma_read_delay; 2706 Param<Tick> dma_write_delay; 2707 Param<Tick> dma_read_factor; 2708 Param<Tick> dma_write_factor; 2709 SimObjectParam<PciConfigAll *> configspace; 2710 SimObjectParam<PciConfigData *> configdata; 2711 SimObjectParam<Platform *> platform; 2712 Param<uint32_t> pci_bus; 2713 Param<uint32_t> pci_dev; 2714 Param<uint32_t> pci_func; 2715 Param<uint32_t> tx_fifo_size; 2716 Param<uint32_t> rx_fifo_size; 2717 Param<uint32_t> m5reg; 2718 Param<bool> dma_no_allocate; 2719 2720END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2721 2722BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2723 2724 INIT_PARAM(addr, "Device Address"), 2725 INIT_PARAM(clock, "State machine processor frequency"), 2726 INIT_PARAM(tx_delay, "Transmit Delay"), 2727 INIT_PARAM(rx_delay, "Receive Delay"), 2728 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2729 INIT_PARAM(mmu, "Memory Controller"), 2730 INIT_PARAM(physmem, "Physical Memory"), 2731 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2732 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2733 "00:99:00:00:00:01"), 2734 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), 2735 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2736 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2737 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2738 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2739 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2740 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2741 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2742 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2743 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2744 INIT_PARAM(configspace, "PCI Configspace"), 2745 INIT_PARAM(configdata, "PCI Config data"), 2746 INIT_PARAM(platform, "Platform"), 2747 INIT_PARAM(pci_bus, "PCI bus"), 2748 INIT_PARAM(pci_dev, "PCI device number"), 2749 INIT_PARAM(pci_func, "PCI function code"), 2750 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2751 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072), 2752 INIT_PARAM(m5reg, "m5 register"), 2753 INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true) 2754 2755END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2756 2757 2758CREATE_SIM_OBJECT(NSGigE) 2759{ 2760 NSGigE::Params *params = new NSGigE::Params; 2761 2762 params->name = getInstanceName(); 2763 params->mmu = mmu; 2764 params->configSpace = configspace; 2765 params->configData = configdata; 2766 params->plat = platform; 2767 params->busNum = pci_bus; 2768 params->deviceNum = pci_dev; 2769 params->functionNum = pci_func; 2770 2771 params->clock = clock; 2772 params->intr_delay = intr_delay; 2773 params->pmem = physmem; 2774 params->tx_delay = tx_delay; 2775 params->rx_delay = rx_delay; 2776 params->hier = hier; 2777 params->header_bus = io_bus; 2778 params->payload_bus = payload_bus; 2779 params->pio_latency = pio_latency; 2780 params->dma_desc_free = dma_desc_free; 2781 params->dma_data_free = dma_data_free; 2782 params->dma_read_delay = dma_read_delay; 2783 params->dma_write_delay = dma_write_delay; 2784 params->dma_read_factor = dma_read_factor; 2785 params->dma_write_factor = dma_write_factor; 2786 params->rx_filter = rx_filter; 2787 params->eaddr = hardware_address; 2788 params->tx_fifo_size = tx_fifo_size; 2789 params->rx_fifo_size = rx_fifo_size; 2790 params->m5reg = m5reg; 2791 params->dma_no_allocate = dma_no_allocate; 2792 return new NSGigE(params); 2793} 2794 2795REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2796