ns_gige.cc revision 1690
12292SN/A/* 29383SAli.Saidi@ARM.com * Copyright (c) 2004 The Regents of The University of Michigan 37597Sminkyu.jeong@arm.com * All rights reserved. 47597Sminkyu.jeong@arm.com * 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 142292SN/A * this software without specific prior written permission. 152292SN/A * 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" 392689Sktlim@umich.edu#include "dev/dma.hh" 402689Sktlim@umich.edu#include "dev/etherlink.hh" 412689Sktlim@umich.edu#include "dev/ns_gige.hh" 422292SN/A#include "dev/pciconfigall.hh" 432292SN/A#include "mem/bus/bus.hh" 448591Sgblack@eecs.umich.edu#include "mem/bus/dma_interface.hh" 453326Sktlim@umich.edu#include "mem/bus/pio_interface.hh" 468229Snate@binkert.org#include "mem/bus/pio_interface_impl.hh" 476658Snate@binkert.org#include "mem/functional_mem/memory_control.hh" 488887Sgeoffrey.blake@arm.com#include "mem/functional_mem/physical_memory.hh" 492907Sktlim@umich.edu#include "sim/builder.hh" 502292SN/A#include "sim/debug.hh" 518232Snate@binkert.org#include "sim/host.hh" 528232Snate@binkert.org#include "sim/stats.hh" 538232Snate@binkert.org#include "targetarch/vtophys.hh" 542722Sktlim@umich.edu 552669Sktlim@umich.educonst char *NsRxStateStrings[] = 562292SN/A{ 572669Sktlim@umich.edu "rxIdle", 582678Sktlim@umich.edu "rxDescRefr", 592678Sktlim@umich.edu "rxDescRead", 608581Ssteve.reinhardt@amd.com "rxFifoBlock", 618581Ssteve.reinhardt@amd.com "rxFragWrite", 622292SN/A "rxDescWrite", 632292SN/A "rxAdvance" 642292SN/A}; 652669Sktlim@umich.edu 662292SN/Aconst char *NsTxStateStrings[] = 672678Sktlim@umich.edu{ 682292SN/A "txIdle", 699444SAndreas.Sandberg@ARM.com "txDescRefr", 709444SAndreas.Sandberg@ARM.com "txDescRead", 719444SAndreas.Sandberg@ARM.com "txFifoBlock", 724319Sktlim@umich.edu "txFragRead", 734319Sktlim@umich.edu "txDescWrite", 744319Sktlim@umich.edu "txAdvance" 754319Sktlim@umich.edu}; 764319Sktlim@umich.edu 772678Sktlim@umich.educonst char *NsDmaState[] = 782678Sktlim@umich.edu{ 792292SN/A "dmaIdle", 802678Sktlim@umich.edu "dmaReading", 812678Sktlim@umich.edu "dmaWriting", 825336Shines@cs.fsu.edu "dmaReadWaiting", 832678Sktlim@umich.edu "dmaWriteWaiting" 844873Sstever@eecs.umich.edu}; 852678Sktlim@umich.edu 862292SN/Ausing namespace std; 872678Sktlim@umich.eduusing namespace Net; 882678Sktlim@umich.edu 892678Sktlim@umich.edu/////////////////////////////////////////////////////////////////////// 902678Sktlim@umich.edu// 912678Sktlim@umich.edu// NSGigE PCI Device 922678Sktlim@umich.edu// 937852SMatt.Horsnell@arm.comNSGigE::NSGigE(Params *p) 947852SMatt.Horsnell@arm.com : PciDev(p), ioEnable(false), 952344SN/A txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 962678Sktlim@umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 972678Sktlim@umich.edu txXferLen(0), rxXferLen(0), cycleTime(p->cycle_time), 986974Stjones1@inf.ed.ac.uk txState(txIdle), txEnable(false), CTDD(false), 996974Stjones1@inf.ed.ac.uk txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 1006974Stjones1@inf.ed.ac.uk rxEnable(false), CRDD(false), rxPktBytes(0), 1016974Stjones1@inf.ed.ac.uk rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1026974Stjones1@inf.ed.ac.uk rxDmaReadEvent(this), rxDmaWriteEvent(this), 1036974Stjones1@inf.ed.ac.uk txDmaReadEvent(this), txDmaWriteEvent(this), 1046974Stjones1@inf.ed.ac.uk dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1059444SAndreas.Sandberg@ARM.com txDelay(p->tx_delay), rxDelay(p->rx_delay), 1069444SAndreas.Sandberg@ARM.com rxKickTick(0), txKickTick(0), 1072820Sktlim@umich.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1082678Sktlim@umich.edu acceptMulticast(false), acceptUnicast(false), 1092678Sktlim@umich.edu acceptPerfect(false), acceptArp(false), 1106974Stjones1@inf.ed.ac.uk physmem(p->pmem), intrTick(0), cpuPendingIntr(false), 1116974Stjones1@inf.ed.ac.uk intrEvent(0), interface(0) 1126974Stjones1@inf.ed.ac.uk{ 1136974Stjones1@inf.ed.ac.uk if (p->header_bus) { 1146974Stjones1@inf.ed.ac.uk pioInterface = newPioInterface(name(), p->hier, 1156974Stjones1@inf.ed.ac.uk p->header_bus, this, 1162678Sktlim@umich.edu &NSGigE::cacheAccess); 1172678Sktlim@umich.edu 1182678Sktlim@umich.edu pioLatency = p->pio_latency * p->header_bus->clockRatio; 1192678Sktlim@umich.edu 1202678Sktlim@umich.edu if (p->payload_bus) 1212344SN/A dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1222307SN/A p->header_bus, 1236974Stjones1@inf.ed.ac.uk p->payload_bus, 1, 1246974Stjones1@inf.ed.ac.uk p->dma_no_allocate); 1256974Stjones1@inf.ed.ac.uk else 1266974Stjones1@inf.ed.ac.uk dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1272678Sktlim@umich.edu p->header_bus, 1284032Sktlim@umich.edu p->header_bus, 1, 1292678Sktlim@umich.edu p->dma_no_allocate); 1302292SN/A } else if (p->payload_bus) { 1312292SN/A pioInterface = newPioInterface(name(), p->hier, 1322292SN/A p->payload_bus, this, 1332292SN/A &NSGigE::cacheAccess); 1348545Ssaidi@eecs.umich.edu 1352678Sktlim@umich.edu pioLatency = p->pio_latency * p->payload_bus->clockRatio; 1368727Snilay@cs.wisc.edu 1372292SN/A dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1382292SN/A p->payload_bus, 1392292SN/A p->payload_bus, 1, 1402292SN/A p->dma_no_allocate); 1412292SN/A } 1425529Snate@binkert.org 1435529Snate@binkert.org 1445529Snate@binkert.org intrDelay = p->intr_delay; 1452292SN/A dmaReadDelay = p->dma_read_delay; 1464329Sktlim@umich.edu dmaWriteDelay = p->dma_write_delay; 1474329Sktlim@umich.edu dmaReadFactor = p->dma_read_factor; 1484329Sktlim@umich.edu dmaWriteFactor = p->dma_write_factor; 1494329Sktlim@umich.edu 1502292SN/A regsReset(); 1512907Sktlim@umich.edu memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 1522907Sktlim@umich.edu} 1532292SN/A 1542292SN/ANSGigE::~NSGigE() 1552329SN/A{} 1562329SN/A 1572329SN/Avoid 1582292SN/ANSGigE::regStats() 1592292SN/A{ 1602292SN/A txBytes 1612292SN/A .name(name() + ".txBytes") 1628199SAli.Saidi@ARM.com .desc("Bytes Transmitted") 1638199SAli.Saidi@ARM.com .prereq(txBytes) 1649444SAndreas.Sandberg@ARM.com ; 1659444SAndreas.Sandberg@ARM.com 1669444SAndreas.Sandberg@ARM.com rxBytes 1679444SAndreas.Sandberg@ARM.com .name(name() + ".rxBytes") 1689444SAndreas.Sandberg@ARM.com .desc("Bytes Received") 1699444SAndreas.Sandberg@ARM.com .prereq(rxBytes) 1709444SAndreas.Sandberg@ARM.com ; 1719444SAndreas.Sandberg@ARM.com 1729444SAndreas.Sandberg@ARM.com txPackets 1739444SAndreas.Sandberg@ARM.com .name(name() + ".txPackets") 1749444SAndreas.Sandberg@ARM.com .desc("Number of Packets Transmitted") 1759444SAndreas.Sandberg@ARM.com .prereq(txBytes) 1768199SAli.Saidi@ARM.com ; 1772292SN/A 1782292SN/A rxPackets 1792292SN/A .name(name() + ".rxPackets") 1802292SN/A .desc("Number of Packets Received") 1812292SN/A .prereq(rxBytes) 1822292SN/A ; 1833492Sktlim@umich.edu 1842329SN/A txIpChecksums 1852292SN/A .name(name() + ".txIpChecksums") 1862292SN/A .desc("Number of tx IP Checksums done by device") 1879444SAndreas.Sandberg@ARM.com .precision(0) 1889444SAndreas.Sandberg@ARM.com .prereq(txBytes) 1899444SAndreas.Sandberg@ARM.com ; 1909444SAndreas.Sandberg@ARM.com 1919444SAndreas.Sandberg@ARM.com rxIpChecksums 1929444SAndreas.Sandberg@ARM.com .name(name() + ".rxIpChecksums") 1932292SN/A .desc("Number of rx IP Checksums done by device") 1942292SN/A .precision(0) 1952292SN/A .prereq(rxBytes) 1962292SN/A ; 1972292SN/A 1982292SN/A txTcpChecksums 1992292SN/A .name(name() + ".txTcpChecksums") 2002292SN/A .desc("Number of tx TCP Checksums done by device") 2012292SN/A .precision(0) 2028247Snate@binkert.org .prereq(txBytes) 2032292SN/A ; 2042292SN/A 2052292SN/A rxTcpChecksums 2062292SN/A .name(name() + ".rxTcpChecksums") 2072292SN/A .desc("Number of rx TCP Checksums done by device") 2082727Sktlim@umich.edu .precision(0) 2092727Sktlim@umich.edu .prereq(rxBytes) 2102727Sktlim@umich.edu ; 2112727Sktlim@umich.edu 2122727Sktlim@umich.edu txUdpChecksums 2132727Sktlim@umich.edu .name(name() + ".txUdpChecksums") 2142727Sktlim@umich.edu .desc("Number of tx UDP Checksums done by device") 2152727Sktlim@umich.edu .precision(0) 2162727Sktlim@umich.edu .prereq(txBytes) 2172727Sktlim@umich.edu ; 2182727Sktlim@umich.edu 2192727Sktlim@umich.edu rxUdpChecksums 2202727Sktlim@umich.edu .name(name() + ".rxUdpChecksums") 2212727Sktlim@umich.edu .desc("Number of rx UDP Checksums done by device") 2222727Sktlim@umich.edu .precision(0) 2232727Sktlim@umich.edu .prereq(rxBytes) 2242727Sktlim@umich.edu ; 2252727Sktlim@umich.edu 2262361SN/A descDmaReads 2272361SN/A .name(name() + ".descDMAReads") 2282361SN/A .desc("Number of descriptors the device read w/ DMA") 2292361SN/A .precision(0) 2302727Sktlim@umich.edu ; 2312727Sktlim@umich.edu 2322727Sktlim@umich.edu descDmaWrites 2332727Sktlim@umich.edu .name(name() + ".descDMAWrites") 2342727Sktlim@umich.edu .desc("Number of descriptors the device wrote w/ DMA") 2352727Sktlim@umich.edu .precision(0) 2362727Sktlim@umich.edu ; 2372727Sktlim@umich.edu 2382727Sktlim@umich.edu descDmaRdBytes 2392727Sktlim@umich.edu .name(name() + ".descDmaReadBytes") 2402727Sktlim@umich.edu .desc("number of descriptor bytes read w/ DMA") 2412727Sktlim@umich.edu .precision(0) 2422727Sktlim@umich.edu ; 2432727Sktlim@umich.edu 2442727Sktlim@umich.edu descDmaWrBytes 2452727Sktlim@umich.edu .name(name() + ".descDmaWriteBytes") 2462727Sktlim@umich.edu .desc("number of descriptor bytes write w/ DMA") 2472727Sktlim@umich.edu .precision(0) 2482727Sktlim@umich.edu ; 2492727Sktlim@umich.edu 2502727Sktlim@umich.edu txBandwidth 2512727Sktlim@umich.edu .name(name() + ".txBandwidth") 2522727Sktlim@umich.edu .desc("Transmit Bandwidth (bits/s)") 2538922Swilliam.wang@arm.com .precision(0) 2544329Sktlim@umich.edu .prereq(txBytes) 2554329Sktlim@umich.edu ; 2564329Sktlim@umich.edu 2574329Sktlim@umich.edu rxBandwidth 2584329Sktlim@umich.edu .name(name() + ".rxBandwidth") 2594329Sktlim@umich.edu .desc("Receive Bandwidth (bits/s)") 2602292SN/A .precision(0) 2612292SN/A .prereq(rxBytes) 2622292SN/A ; 2632292SN/A 2642292SN/A totBandwidth 2652292SN/A .name(name() + ".totBandwidth") 2662292SN/A .desc("Total Bandwidth (bits/s)") 2672292SN/A .precision(0) 2682292SN/A .prereq(totBytes) 2692292SN/A ; 2702292SN/A 2712292SN/A totPackets 2722292SN/A .name(name() + ".totPackets") 2732292SN/A .desc("Total Packets") 2749444SAndreas.Sandberg@ARM.com .precision(0) 2752307SN/A .prereq(totBytes) 2769444SAndreas.Sandberg@ARM.com ; 2772367SN/A 2782307SN/A totBytes 2792329SN/A .name(name() + ".totBytes") 2809444SAndreas.Sandberg@ARM.com .desc("Total Bytes") 2812307SN/A .precision(0) 2822307SN/A .prereq(totBytes) 2832307SN/A ; 2842307SN/A 2852307SN/A totPacketRate 2862307SN/A .name(name() + ".totPPS") 2879444SAndreas.Sandberg@ARM.com .desc("Total Tranmission Rate (packets/s)") 2882307SN/A .precision(0) 2892307SN/A .prereq(totBytes) 2902307SN/A ; 2912307SN/A 2922292SN/A txPacketRate 2932292SN/A .name(name() + ".txPPS") 2942329SN/A .desc("Packet Tranmission Rate (packets/s)") 2952329SN/A .precision(0) 2962292SN/A .prereq(txBytes) 2972329SN/A ; 2982329SN/A 2992292SN/A rxPacketRate 3002292SN/A .name(name() + ".rxPPS") 3012292SN/A .desc("Packet Reception Rate (packets/s)") 3022292SN/A .precision(0) 3032292SN/A .prereq(rxBytes) 3042329SN/A ; 3052292SN/A 3062292SN/A postedSwi 3072292SN/A .name(name() + ".postedSwi") 3082292SN/A .desc("number of software interrupts posted to CPU") 3092292SN/A .precision(0) 3102292SN/A ; 3112292SN/A 3122292SN/A totalSwi 3132329SN/A .name(name() + ".totalSwi") 3142329SN/A .desc("number of total Swi written to ISR") 3152329SN/A .precision(0) 3162292SN/A ; 3172292SN/A 3182292SN/A coalescedSwi 3192292SN/A .name(name() + ".coalescedSwi") 3202292SN/A .desc("average number of Swi's coalesced into each post") 3212329SN/A .precision(0) 3222292SN/A ; 3232292SN/A 3242292SN/A postedRxIdle 3252292SN/A .name(name() + ".postedRxIdle") 3262292SN/A .desc("number of rxIdle interrupts posted to CPU") 3272292SN/A .precision(0) 3282292SN/A ; 3292292SN/A 3302292SN/A totalRxIdle 3312292SN/A .name(name() + ".totalRxIdle") 3322292SN/A .desc("number of total RxIdle written to ISR") 3332292SN/A .precision(0) 3342292SN/A ; 3352292SN/A 3362292SN/A coalescedRxIdle 3372292SN/A .name(name() + ".coalescedRxIdle") 3382292SN/A .desc("average number of RxIdle's coalesced into each post") 3392292SN/A .precision(0) 3402292SN/A ; 3412292SN/A 3422292SN/A postedRxOk 3432292SN/A .name(name() + ".postedRxOk") 3442292SN/A .desc("number of RxOk interrupts posted to CPU") 3452292SN/A .precision(0) 3462329SN/A ; 3472329SN/A 3482292SN/A totalRxOk 3497720Sgblack@eecs.umich.edu .name(name() + ".totalRxOk") 3507720Sgblack@eecs.umich.edu .desc("number of total RxOk written to ISR") 3512292SN/A .precision(0) 3522292SN/A ; 3532292SN/A 3542292SN/A coalescedRxOk 3552292SN/A .name(name() + ".coalescedRxOk") 3562292SN/A .desc("average number of RxOk's coalesced into each post") 3572292SN/A .precision(0) 3582292SN/A ; 3592292SN/A 3602292SN/A postedRxDesc 3612292SN/A .name(name() + ".postedRxDesc") 3622292SN/A .desc("number of RxDesc interrupts posted to CPU") 3632292SN/A .precision(0) 3642292SN/A ; 3652292SN/A 3662292SN/A totalRxDesc 3672292SN/A .name(name() + ".totalRxDesc") 3682292SN/A .desc("number of total RxDesc written to ISR") 3692292SN/A .precision(0) 3702292SN/A ; 3712292SN/A 3722292SN/A coalescedRxDesc 3732292SN/A .name(name() + ".coalescedRxDesc") 3742292SN/A .desc("average number of RxDesc's coalesced into each post") 3757720Sgblack@eecs.umich.edu .precision(0) 3767720Sgblack@eecs.umich.edu ; 3772292SN/A 3782292SN/A postedTxOk 3792292SN/A .name(name() + ".postedTxOk") 3802292SN/A .desc("number of TxOk interrupts posted to CPU") 3812292SN/A .precision(0) 3822292SN/A ; 3832292SN/A 3842292SN/A totalTxOk 3852292SN/A .name(name() + ".totalTxOk") 3862292SN/A .desc("number of total TxOk written to ISR") 3872292SN/A .precision(0) 3882292SN/A ; 3892292SN/A 3902292SN/A coalescedTxOk 3912292SN/A .name(name() + ".coalescedTxOk") 3922292SN/A .desc("average number of TxOk's coalesced into each post") 3932292SN/A .precision(0) 3942292SN/A ; 3952292SN/A 3962292SN/A postedTxIdle 3972292SN/A .name(name() + ".postedTxIdle") 3982292SN/A .desc("number of TxIdle interrupts posted to CPU") 3992292SN/A .precision(0) 4002292SN/A ; 4012292SN/A 4022292SN/A totalTxIdle 4032292SN/A .name(name() + ".totalTxIdle") 4042292SN/A .desc("number of total TxIdle written to ISR") 4052292SN/A .precision(0) 4062292SN/A ; 4072292SN/A 4082292SN/A coalescedTxIdle 4092292SN/A .name(name() + ".coalescedTxIdle") 4102292SN/A .desc("average number of TxIdle's coalesced into each post") 4112292SN/A .precision(0) 4122292SN/A ; 4132292SN/A 4142292SN/A postedTxDesc 4152292SN/A .name(name() + ".postedTxDesc") 4168545Ssaidi@eecs.umich.edu .desc("number of TxDesc interrupts posted to CPU") 4178545Ssaidi@eecs.umich.edu .precision(0) 4188545Ssaidi@eecs.umich.edu ; 4198545Ssaidi@eecs.umich.edu 4208545Ssaidi@eecs.umich.edu totalTxDesc 4218545Ssaidi@eecs.umich.edu .name(name() + ".totalTxDesc") 4228545Ssaidi@eecs.umich.edu .desc("number of total TxDesc written to ISR") 4238545Ssaidi@eecs.umich.edu .precision(0) 4248545Ssaidi@eecs.umich.edu ; 4258545Ssaidi@eecs.umich.edu 4268545Ssaidi@eecs.umich.edu coalescedTxDesc 4278545Ssaidi@eecs.umich.edu .name(name() + ".coalescedTxDesc") 4288545Ssaidi@eecs.umich.edu .desc("average number of TxDesc's coalesced into each post") 4298545Ssaidi@eecs.umich.edu .precision(0) 4308545Ssaidi@eecs.umich.edu ; 4319383SAli.Saidi@ARM.com 4329383SAli.Saidi@ARM.com postedRxOrn 4339383SAli.Saidi@ARM.com .name(name() + ".postedRxOrn") 4349383SAli.Saidi@ARM.com .desc("number of RxOrn posted to CPU") 4359383SAli.Saidi@ARM.com .precision(0) 4369383SAli.Saidi@ARM.com ; 4379383SAli.Saidi@ARM.com 4389383SAli.Saidi@ARM.com totalRxOrn 4399383SAli.Saidi@ARM.com .name(name() + ".totalRxOrn") 4409383SAli.Saidi@ARM.com .desc("number of total RxOrn written to ISR") 4419383SAli.Saidi@ARM.com .precision(0) 4429383SAli.Saidi@ARM.com ; 4438545Ssaidi@eecs.umich.edu 4448545Ssaidi@eecs.umich.edu coalescedRxOrn 4458545Ssaidi@eecs.umich.edu .name(name() + ".coalescedRxOrn") 4468545Ssaidi@eecs.umich.edu .desc("average number of RxOrn's coalesced into each post") 4478545Ssaidi@eecs.umich.edu .precision(0) 4488545Ssaidi@eecs.umich.edu ; 4498545Ssaidi@eecs.umich.edu 4508545Ssaidi@eecs.umich.edu coalescedTotal 4518545Ssaidi@eecs.umich.edu .name(name() + ".coalescedTotal") 4528545Ssaidi@eecs.umich.edu .desc("average number of interrupts coalesced into each post") 4539046SAli.Saidi@ARM.com .precision(0) 4548545Ssaidi@eecs.umich.edu ; 4558545Ssaidi@eecs.umich.edu 4568545Ssaidi@eecs.umich.edu postedInterrupts 4578545Ssaidi@eecs.umich.edu .name(name() + ".postedInterrupts") 4588545Ssaidi@eecs.umich.edu .desc("number of posts to CPU") 4598545Ssaidi@eecs.umich.edu .precision(0) 4608545Ssaidi@eecs.umich.edu ; 4618545Ssaidi@eecs.umich.edu 4628545Ssaidi@eecs.umich.edu droppedPackets 4639046SAli.Saidi@ARM.com .name(name() + ".droppedPackets") 4648545Ssaidi@eecs.umich.edu .desc("number of packets dropped") 4658545Ssaidi@eecs.umich.edu .precision(0) 4668545Ssaidi@eecs.umich.edu ; 4678545Ssaidi@eecs.umich.edu 4688545Ssaidi@eecs.umich.edu coalescedSwi = totalSwi / postedInterrupts; 4698545Ssaidi@eecs.umich.edu coalescedRxIdle = totalRxIdle / postedInterrupts; 4708545Ssaidi@eecs.umich.edu coalescedRxOk = totalRxOk / postedInterrupts; 4718545Ssaidi@eecs.umich.edu coalescedRxDesc = totalRxDesc / postedInterrupts; 4728545Ssaidi@eecs.umich.edu coalescedTxOk = totalTxOk / postedInterrupts; 4739046SAli.Saidi@ARM.com coalescedTxIdle = totalTxIdle / postedInterrupts; 4748545Ssaidi@eecs.umich.edu coalescedTxDesc = totalTxDesc / postedInterrupts; 4758545Ssaidi@eecs.umich.edu coalescedRxOrn = totalRxOrn / postedInterrupts; 4768545Ssaidi@eecs.umich.edu 4778545Ssaidi@eecs.umich.edu coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + totalTxOk 4788545Ssaidi@eecs.umich.edu + totalTxIdle + totalTxDesc + totalRxOrn) / postedInterrupts; 4798545Ssaidi@eecs.umich.edu 4808545Ssaidi@eecs.umich.edu txBandwidth = txBytes * Stats::constant(8) / simSeconds; 4818545Ssaidi@eecs.umich.edu rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 4822292SN/A totBandwidth = txBandwidth + rxBandwidth; 4838199SAli.Saidi@ARM.com totBytes = txBytes + rxBytes; 4848199SAli.Saidi@ARM.com totPackets = txPackets + rxPackets; 4858199SAli.Saidi@ARM.com 4868199SAli.Saidi@ARM.com txPacketRate = txPackets / simSeconds; 4878199SAli.Saidi@ARM.com rxPacketRate = rxPackets / simSeconds; 4888199SAli.Saidi@ARM.com} 4898199SAli.Saidi@ARM.com 4908199SAli.Saidi@ARM.com/** 4918199SAli.Saidi@ARM.com * This is to read the PCI general configuration registers 4928199SAli.Saidi@ARM.com */ 4938199SAli.Saidi@ARM.comvoid 4948199SAli.Saidi@ARM.comNSGigE::ReadConfig(int offset, int size, uint8_t *data) 4959046SAli.Saidi@ARM.com{ 4968199SAli.Saidi@ARM.com if (offset < PCI_DEVICE_SPECIFIC) 4978199SAli.Saidi@ARM.com PciDev::ReadConfig(offset, size, data); 4988199SAli.Saidi@ARM.com else 4998199SAli.Saidi@ARM.com panic("Device specific PCI config space not implemented!\n"); 5008199SAli.Saidi@ARM.com} 5018199SAli.Saidi@ARM.com 5028199SAli.Saidi@ARM.com/** 5038199SAli.Saidi@ARM.com * This is to write to the PCI general configuration registers 5048272SAli.Saidi@ARM.com */ 5058545Ssaidi@eecs.umich.eduvoid 5068545Ssaidi@eecs.umich.eduNSGigE::WriteConfig(int offset, int size, uint32_t data) 5078545Ssaidi@eecs.umich.edu{ 5088545Ssaidi@eecs.umich.edu if (offset < PCI_DEVICE_SPECIFIC) 5099046SAli.Saidi@ARM.com PciDev::WriteConfig(offset, size, data); 5108545Ssaidi@eecs.umich.edu else 5118545Ssaidi@eecs.umich.edu panic("Device specific PCI config space not implemented!\n"); 5128545Ssaidi@eecs.umich.edu 5138592Sgblack@eecs.umich.edu // Need to catch writes to BARs to update the PIO interface 5148592Sgblack@eecs.umich.edu switch (offset) { 5158545Ssaidi@eecs.umich.edu // seems to work fine without all these PCI settings, but i 5168199SAli.Saidi@ARM.com // put in the IO to double check, an assertion will fail if we 5178545Ssaidi@eecs.umich.edu // need to properly implement it 5188199SAli.Saidi@ARM.com case PCI_COMMAND: 5198591Sgblack@eecs.umich.edu if (config.data[offset] & PCI_CMD_IOSE) 5208591Sgblack@eecs.umich.edu ioEnable = true; 5218591Sgblack@eecs.umich.edu else 5228591Sgblack@eecs.umich.edu ioEnable = false; 5238545Ssaidi@eecs.umich.edu 5248545Ssaidi@eecs.umich.edu#if 0 5258199SAli.Saidi@ARM.com if (config.data[offset] & PCI_CMD_BME) { 5268545Ssaidi@eecs.umich.edu bmEnabled = true; 5278545Ssaidi@eecs.umich.edu } 5289046SAli.Saidi@ARM.com else { 5298545Ssaidi@eecs.umich.edu bmEnabled = false; 5308545Ssaidi@eecs.umich.edu } 5318545Ssaidi@eecs.umich.edu 5328545Ssaidi@eecs.umich.edu if (config.data[offset] & PCI_CMD_MSE) { 5338545Ssaidi@eecs.umich.edu memEnable = true; 5348545Ssaidi@eecs.umich.edu } 5358545Ssaidi@eecs.umich.edu else { 5368545Ssaidi@eecs.umich.edu memEnable = false; 5378545Ssaidi@eecs.umich.edu } 5388545Ssaidi@eecs.umich.edu#endif 5398592Sgblack@eecs.umich.edu break; 5408592Sgblack@eecs.umich.edu 5418592Sgblack@eecs.umich.edu case PCI0_BASE_ADDR0: 5428545Ssaidi@eecs.umich.edu if (BARAddrs[0] != 0) { 5438545Ssaidi@eecs.umich.edu if (pioInterface) 5448545Ssaidi@eecs.umich.edu pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 5458545Ssaidi@eecs.umich.edu 5468591Sgblack@eecs.umich.edu BARAddrs[0] &= EV5::PAddrUncachedMask; 5478591Sgblack@eecs.umich.edu } 5488591Sgblack@eecs.umich.edu break; 5498545Ssaidi@eecs.umich.edu case PCI0_BASE_ADDR1: 5508199SAli.Saidi@ARM.com if (BARAddrs[1] != 0) { 5518199SAli.Saidi@ARM.com if (pioInterface) 5528199SAli.Saidi@ARM.com pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 5538199SAli.Saidi@ARM.com 5548199SAli.Saidi@ARM.com BARAddrs[1] &= EV5::PAddrUncachedMask; 5558199SAli.Saidi@ARM.com } 5568199SAli.Saidi@ARM.com break; 5578199SAli.Saidi@ARM.com } 5588199SAli.Saidi@ARM.com} 5598199SAli.Saidi@ARM.com 5608199SAli.Saidi@ARM.com/** 5618199SAli.Saidi@ARM.com * This reads the device registers, which are detailed in the NS83820 5622292SN/A * spec sheet 5632292SN/A */ 5644032Sktlim@umich.eduFault 5652292SN/ANSGigE::read(MemReqPtr &req, uint8_t *data) 5662292SN/A{ 5672292SN/A assert(ioEnable); 5687720Sgblack@eecs.umich.edu 5697944SGiacomo.Gabrielli@arm.com //The mask is to give you only the offset into the device register file 5702292SN/A Addr daddr = req->paddr & 0xfff; 5714032Sktlim@umich.edu DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 5724032Sktlim@umich.edu daddr, req->paddr, req->vaddr, req->size); 5732669Sktlim@umich.edu 5742292SN/A 5757944SGiacomo.Gabrielli@arm.com // there are some reserved registers, you can see ns_gige_reg.h and 5767944SGiacomo.Gabrielli@arm.com // the spec sheet for details 5777944SGiacomo.Gabrielli@arm.com if (daddr > LAST && daddr <= RESERVED) { 5787944SGiacomo.Gabrielli@arm.com panic("Accessing reserved register"); 5797597Sminkyu.jeong@arm.com } else if (daddr > RESERVED && daddr <= 0x3FC) { 5807597Sminkyu.jeong@arm.com ReadConfig(daddr & 0xff, req->size, data); 5817597Sminkyu.jeong@arm.com return No_Fault; 5822329SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 5832329SN/A // don't implement all the MIB's. hopefully the kernel 5842367SN/A // doesn't actually DEPEND upon their values 5852367SN/A // MIB are just hardware stats keepers 5867848SAli.Saidi@ARM.com uint32_t ® = *(uint32_t *) data; 5877848SAli.Saidi@ARM.com reg = 0; 5887600Sminkyu.jeong@arm.com return No_Fault; 5897600Sminkyu.jeong@arm.com } else if (daddr > 0x3FC) 5907600Sminkyu.jeong@arm.com panic("Something is messed up!\n"); 5914032Sktlim@umich.edu 5923731Sktlim@umich.edu switch (req->size) { 5932367SN/A case sizeof(uint32_t): 5942367SN/A { 5952292SN/A uint32_t ® = *(uint32_t *)data; 5962292SN/A 5974032Sktlim@umich.edu switch (daddr) { 5989046SAli.Saidi@ARM.com case CR: 5994032Sktlim@umich.edu reg = regs.command; 6004032Sktlim@umich.edu //these are supposed to be cleared on a read 6014032Sktlim@umich.edu reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 6028199SAli.Saidi@ARM.com break; 6038199SAli.Saidi@ARM.com 6042292SN/A case CFGR: 6052292SN/A reg = regs.config; 6062292SN/A break; 6072292SN/A 6082292SN/A case MEAR: 6092292SN/A reg = regs.mear; 6102292SN/A break; 6112292SN/A 6122292SN/A case PTSCR: 6132292SN/A reg = regs.ptscr; 6142292SN/A break; 6152292SN/A 6162292SN/A case ISR: 6172292SN/A reg = regs.isr; 6182292SN/A devIntrClear(ISR_ALL); 6197720Sgblack@eecs.umich.edu break; 6207720Sgblack@eecs.umich.edu 6212292SN/A case IMR: 6224032Sktlim@umich.edu reg = regs.imr; 6234032Sktlim@umich.edu break; 6242292SN/A 6252292SN/A case IER: 6262292SN/A reg = regs.ier; 6272292SN/A break; 6282292SN/A 6292292SN/A case IHR: 6307944SGiacomo.Gabrielli@arm.com reg = regs.ihr; 6317944SGiacomo.Gabrielli@arm.com break; 6327944SGiacomo.Gabrielli@arm.com 6337944SGiacomo.Gabrielli@arm.com case TXDP: 6347848SAli.Saidi@ARM.com reg = regs.txdp; 6357848SAli.Saidi@ARM.com break; 6367848SAli.Saidi@ARM.com 6372329SN/A case TXDP_HI: 6387782Sminkyu.jeong@arm.com reg = regs.txdp_hi; 6397720Sgblack@eecs.umich.edu break; 6402292SN/A 6412292SN/A case TX_CFG: 6427782Sminkyu.jeong@arm.com reg = regs.txcfg; 6437782Sminkyu.jeong@arm.com break; 6447782Sminkyu.jeong@arm.com 6457782Sminkyu.jeong@arm.com case GPIOR: 6462292SN/A reg = regs.gpior; 6472292SN/A break; 6482292SN/A 6492292SN/A case RXDP: 6502336SN/A reg = regs.rxdp; 6512336SN/A break; 6522336SN/A 6532329SN/A case RXDP_HI: 6542292SN/A reg = regs.rxdp_hi; 6552329SN/A break; 6562292SN/A 6572292SN/A case RX_CFG: 6588199SAli.Saidi@ARM.com reg = regs.rxcfg; 6592292SN/A break; 6602292SN/A 6612292SN/A case PQCR: 6622292SN/A reg = regs.pqcr; 6632292SN/A break; 6642292SN/A 6652292SN/A case WCSR: 6662292SN/A reg = regs.wcsr; 6672292SN/A break; 6687720Sgblack@eecs.umich.edu 6697720Sgblack@eecs.umich.edu case PCR: 6702292SN/A reg = regs.pcr; 6712292SN/A break; 6722292SN/A 6732292SN/A // see the spec sheet for how RFCR and RFDR work 6742292SN/A // basically, you write to RFCR to tell the machine 6752292SN/A // what you want to do next, then you act upon RFDR, 6762292SN/A // and the device will be prepared b/c of what you 6772292SN/A // wrote to RFCR 6782292SN/A case RFCR: 6792292SN/A reg = regs.rfcr; 6802292SN/A break; 6812292SN/A 6822292SN/A case RFDR: 6832292SN/A switch (regs.rfcr & RFCR_RFADDR) { 6842292SN/A case 0x000: 6852292SN/A reg = rom.perfectMatch[1]; 6862292SN/A reg = reg << 8; 6872292SN/A reg += rom.perfectMatch[0]; 6882292SN/A break; 6892292SN/A case 0x002: 6902292SN/A reg = rom.perfectMatch[3] << 8; 6912292SN/A reg += rom.perfectMatch[2]; 6922292SN/A break; 6932292SN/A case 0x004: 6942292SN/A reg = rom.perfectMatch[5] << 8; 6952292SN/A reg += rom.perfectMatch[4]; 6962292SN/A break; 6972292SN/A default: 6982292SN/A panic("reading RFDR for something other than PMATCH!\n"); 6992329SN/A // didn't implement other RFDR functionality b/c 7002329SN/A // driver didn't use it 7012292SN/A } 7022292SN/A break; 7032292SN/A 7042292SN/A case SRR: 7052292SN/A reg = regs.srr; 7067720Sgblack@eecs.umich.edu break; 7077720Sgblack@eecs.umich.edu 7082292SN/A case MIBC: 7092292SN/A reg = regs.mibc; 7102292SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 7112292SN/A break; 7122292SN/A 7132292SN/A case VRCR: 7142292SN/A reg = regs.vrcr; 7152292SN/A break; 7162292SN/A 7172292SN/A case VTCR: 7182292SN/A reg = regs.vtcr; 7192292SN/A break; 7202292SN/A 7216974Stjones1@inf.ed.ac.uk case VDR: 7226974Stjones1@inf.ed.ac.uk reg = regs.vdr; 7236974Stjones1@inf.ed.ac.uk break; 7246974Stjones1@inf.ed.ac.uk 7256974Stjones1@inf.ed.ac.uk case CCSR: 7266974Stjones1@inf.ed.ac.uk reg = regs.ccsr; 7276974Stjones1@inf.ed.ac.uk break; 7286974Stjones1@inf.ed.ac.uk 7296974Stjones1@inf.ed.ac.uk case TBICR: 7306974Stjones1@inf.ed.ac.uk reg = regs.tbicr; 7316974Stjones1@inf.ed.ac.uk break; 7326974Stjones1@inf.ed.ac.uk 7336974Stjones1@inf.ed.ac.uk case TBISR: 7346974Stjones1@inf.ed.ac.uk reg = regs.tbisr; 7356974Stjones1@inf.ed.ac.uk break; 7366974Stjones1@inf.ed.ac.uk 7372292SN/A case TANAR: 7382292SN/A reg = regs.tanar; 7396974Stjones1@inf.ed.ac.uk break; 7406974Stjones1@inf.ed.ac.uk 7416974Stjones1@inf.ed.ac.uk case TANLPAR: 7426974Stjones1@inf.ed.ac.uk reg = regs.tanlpar; 7436974Stjones1@inf.ed.ac.uk break; 7446974Stjones1@inf.ed.ac.uk 7452292SN/A case TANER: 7462292SN/A reg = regs.taner; 7472292SN/A break; 7482292SN/A 7498727Snilay@cs.wisc.edu case TESR: 7502292SN/A reg = regs.tesr; 7512292SN/A break; 7522907Sktlim@umich.edu 7532678Sktlim@umich.edu case M5REG: 7542678Sktlim@umich.edu reg = params()->m5reg; 7552678Sktlim@umich.edu break; 7562678Sktlim@umich.edu 7572678Sktlim@umich.edu default: 7582329SN/A panic("reading unimplemented register: addr=%#x", daddr); 7592329SN/A } 7602292SN/A 7612292SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 7622292SN/A daddr, reg, reg); 7632292SN/A } 7642292SN/A break; 7652292SN/A 7662292SN/A default: 7672678Sktlim@umich.edu panic("accessing register with invalid size: addr=%#x, size=%d", 7682292SN/A daddr, req->size); 7692292SN/A } 7702292SN/A 7712292SN/A return No_Fault; 7722292SN/A} 7732292SN/A 7742292SN/AFault 7752292SN/ANSGigE::write(MemReqPtr &req, const uint8_t *data) 7762292SN/A{ 7772292SN/A assert(ioEnable); 7782292SN/A 7796974Stjones1@inf.ed.ac.uk Addr daddr = req->paddr & 0xfff; 7806974Stjones1@inf.ed.ac.uk DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 7816974Stjones1@inf.ed.ac.uk daddr, req->paddr, req->vaddr, req->size); 7826974Stjones1@inf.ed.ac.uk 7836974Stjones1@inf.ed.ac.uk if (daddr > LAST && daddr <= RESERVED) { 7842669Sktlim@umich.edu panic("Accessing reserved register"); 7852669Sktlim@umich.edu } else if (daddr > RESERVED && daddr <= 0x3FC) { 7862669Sktlim@umich.edu WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 7878481Sgblack@eecs.umich.edu return No_Fault; 7888481Sgblack@eecs.umich.edu } else if (daddr > 0x3FC) 7898481Sgblack@eecs.umich.edu panic("Something is messed up!\n"); 7902292SN/A 7912292SN/A if (req->size == sizeof(uint32_t)) { 7922669Sktlim@umich.edu uint32_t reg = *(uint32_t *)data; 7932669Sktlim@umich.edu DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 7943772Sgblack@eecs.umich.edu 7954326Sgblack@eecs.umich.edu switch (daddr) { 7962669Sktlim@umich.edu case CR: 7974878Sstever@eecs.umich.edu regs.command = reg; 7984878Sstever@eecs.umich.edu if (reg & CR_TXD) { 7996102Sgblack@eecs.umich.edu txEnable = false; 8006974Stjones1@inf.ed.ac.uk } else if (reg & CR_TXE) { 8016974Stjones1@inf.ed.ac.uk txEnable = true; 8022292SN/A 8032678Sktlim@umich.edu // the kernel is enabling the transmit machine 8042678Sktlim@umich.edu if (txState == txIdle) 8052678Sktlim@umich.edu txKick(); 8062678Sktlim@umich.edu } 8076974Stjones1@inf.ed.ac.uk 8086974Stjones1@inf.ed.ac.uk if (reg & CR_RXD) { 8096974Stjones1@inf.ed.ac.uk rxEnable = false; 8106974Stjones1@inf.ed.ac.uk } else if (reg & CR_RXE) { 8118949Sandreas.hansson@arm.com rxEnable = true; 8126974Stjones1@inf.ed.ac.uk 8136974Stjones1@inf.ed.ac.uk if (rxState == rxIdle) 8146974Stjones1@inf.ed.ac.uk rxKick(); 8156974Stjones1@inf.ed.ac.uk } 8168949Sandreas.hansson@arm.com 8178949Sandreas.hansson@arm.com if (reg & CR_TXR) 8186974Stjones1@inf.ed.ac.uk txReset(); 8196974Stjones1@inf.ed.ac.uk 8206974Stjones1@inf.ed.ac.uk if (reg & CR_RXR) 8216974Stjones1@inf.ed.ac.uk rxReset(); 8226974Stjones1@inf.ed.ac.uk 8236974Stjones1@inf.ed.ac.uk if (reg & CR_SWI) 8246974Stjones1@inf.ed.ac.uk devIntrPost(ISR_SWI); 8256974Stjones1@inf.ed.ac.uk 8266974Stjones1@inf.ed.ac.uk if (reg & CR_RST) { 8276974Stjones1@inf.ed.ac.uk txReset(); 8286974Stjones1@inf.ed.ac.uk rxReset(); 8296974Stjones1@inf.ed.ac.uk 8306974Stjones1@inf.ed.ac.uk regsReset(); 8316974Stjones1@inf.ed.ac.uk } 8322678Sktlim@umich.edu break; 8337720Sgblack@eecs.umich.edu 8342292SN/A case CFGR: 8357720Sgblack@eecs.umich.edu if (reg & CFGR_LNKSTS || 8363797Sgblack@eecs.umich.edu reg & CFGR_SPDSTS || 8373221Sktlim@umich.edu reg & CFGR_DUPSTS || 8382292SN/A reg & CFGR_RESERVED || 8392693Sktlim@umich.edu reg & CFGR_T64ADDR || 8404350Sgblack@eecs.umich.edu reg & CFGR_PCI64_DET) 8416974Stjones1@inf.ed.ac.uk panic("writing to read-only or reserved CFGR bits!\n"); 8423326Sktlim@umich.edu 8433326Sktlim@umich.edu regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 8443326Sktlim@umich.edu CFGR_RESERVED | CFGR_T64ADDR | CFGR_PCI64_DET); 8459046SAli.Saidi@ARM.com 8463326Sktlim@umich.edu// all these #if 0's are because i don't THINK the kernel needs to 8479046SAli.Saidi@ARM.com// have these implemented. if there is a problem relating to one of 8483326Sktlim@umich.edu// these, you may need to add functionality in. 8493326Sktlim@umich.edu#if 0 8503326Sktlim@umich.edu if (reg & CFGR_TBI_EN) ; 8513326Sktlim@umich.edu if (reg & CFGR_MODE_1000) ; 8523326Sktlim@umich.edu#endif 8533326Sktlim@umich.edu 8543326Sktlim@umich.edu if (reg & CFGR_AUTO_1000) 8557823Ssteve.reinhardt@amd.com panic("CFGR_AUTO_1000 not implemented!\n"); 8568887Sgeoffrey.blake@arm.com 8578887Sgeoffrey.blake@arm.com#if 0 8588887Sgeoffrey.blake@arm.com if (reg & CFGR_PINT_DUPSTS || 8598887Sgeoffrey.blake@arm.com reg & CFGR_PINT_LNKSTS || 8608887Sgeoffrey.blake@arm.com reg & CFGR_PINT_SPDSTS) 8618887Sgeoffrey.blake@arm.com ; 8623326Sktlim@umich.edu 8633326Sktlim@umich.edu if (reg & CFGR_TMRTEST) ; 8643326Sktlim@umich.edu if (reg & CFGR_MRM_DIS) ; 8652693Sktlim@umich.edu if (reg & CFGR_MWI_DIS) ; 8662693Sktlim@umich.edu 8672693Sktlim@umich.edu if (reg & CFGR_T64ADDR) 8682693Sktlim@umich.edu panic("CFGR_T64ADDR is read only register!\n"); 8692693Sktlim@umich.edu 8702693Sktlim@umich.edu if (reg & CFGR_PCI64_DET) 8718481Sgblack@eecs.umich.edu panic("CFGR_PCI64_DET is read only register!\n"); 8728481Sgblack@eecs.umich.edu 8738481Sgblack@eecs.umich.edu if (reg & CFGR_DATA64_EN) ; 8748481Sgblack@eecs.umich.edu if (reg & CFGR_M64ADDR) ; 8758481Sgblack@eecs.umich.edu if (reg & CFGR_PHY_RST) ; 8768481Sgblack@eecs.umich.edu if (reg & CFGR_PHY_DIS) ; 8778481Sgblack@eecs.umich.edu#endif 8788481Sgblack@eecs.umich.edu 8798481Sgblack@eecs.umich.edu if (reg & CFGR_EXTSTS_EN) 8808481Sgblack@eecs.umich.edu extstsEnable = true; 8818481Sgblack@eecs.umich.edu else 8828481Sgblack@eecs.umich.edu extstsEnable = false; 8838481Sgblack@eecs.umich.edu 8848481Sgblack@eecs.umich.edu#if 0 8858481Sgblack@eecs.umich.edu if (reg & CFGR_REQALG) ; 8868481Sgblack@eecs.umich.edu if (reg & CFGR_SB) ; 8878481Sgblack@eecs.umich.edu if (reg & CFGR_POW) ; 8888481Sgblack@eecs.umich.edu if (reg & CFGR_EXD) ; 8898481Sgblack@eecs.umich.edu if (reg & CFGR_PESEL) ; 8908481Sgblack@eecs.umich.edu if (reg & CFGR_BROM_DIS) ; 8918481Sgblack@eecs.umich.edu if (reg & CFGR_EXT_125) ; 8924032Sktlim@umich.edu if (reg & CFGR_BEM) ; 8933221Sktlim@umich.edu#endif 8943221Sktlim@umich.edu break; 8956974Stjones1@inf.ed.ac.uk 8966974Stjones1@inf.ed.ac.uk case MEAR: 8978481Sgblack@eecs.umich.edu regs.mear = reg; 8986974Stjones1@inf.ed.ac.uk // since phy is completely faked, MEAR_MD* don't matter 8996974Stjones1@inf.ed.ac.uk // and since the driver never uses MEAR_EE*, they don't 9006974Stjones1@inf.ed.ac.uk // matter 9012669Sktlim@umich.edu#if 0 9026974Stjones1@inf.ed.ac.uk if (reg & MEAR_EEDI) ; 9036974Stjones1@inf.ed.ac.uk if (reg & MEAR_EEDO) ; // this one is read only 9048481Sgblack@eecs.umich.edu if (reg & MEAR_EECLK) ; 9056974Stjones1@inf.ed.ac.uk if (reg & MEAR_EESEL) ; 9066974Stjones1@inf.ed.ac.uk if (reg & MEAR_MDIO) ; 9076974Stjones1@inf.ed.ac.uk if (reg & MEAR_MDDIR) ; 9086974Stjones1@inf.ed.ac.uk if (reg & MEAR_MDC) ; 9096974Stjones1@inf.ed.ac.uk#endif 9106974Stjones1@inf.ed.ac.uk break; 9116974Stjones1@inf.ed.ac.uk 9126974Stjones1@inf.ed.ac.uk case PTSCR: 9136974Stjones1@inf.ed.ac.uk regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 9146974Stjones1@inf.ed.ac.uk // these control BISTs for various parts of chip - we 9156974Stjones1@inf.ed.ac.uk // don't care or do just fake that the BIST is done 9166974Stjones1@inf.ed.ac.uk if (reg & PTSCR_RBIST_EN) 9176974Stjones1@inf.ed.ac.uk regs.ptscr |= PTSCR_RBIST_DONE; 9186974Stjones1@inf.ed.ac.uk if (reg & PTSCR_EEBIST_EN) 9196974Stjones1@inf.ed.ac.uk regs.ptscr &= ~PTSCR_EEBIST_EN; 9206974Stjones1@inf.ed.ac.uk if (reg & PTSCR_EELOAD_EN) 9216974Stjones1@inf.ed.ac.uk regs.ptscr &= ~PTSCR_EELOAD_EN; 9226974Stjones1@inf.ed.ac.uk break; 9236974Stjones1@inf.ed.ac.uk 9246974Stjones1@inf.ed.ac.uk case ISR: /* writing to the ISR has no effect */ 9256974Stjones1@inf.ed.ac.uk panic("ISR is a read only register!\n"); 9266974Stjones1@inf.ed.ac.uk 9276974Stjones1@inf.ed.ac.uk case IMR: 9286974Stjones1@inf.ed.ac.uk regs.imr = reg; 9292292SN/A devIntrChangeMask(); 9302292SN/A break; 9312292SN/A 9322292SN/A case IER: 9332292SN/A regs.ier = reg; 9342292SN/A break; 9352292SN/A 9362292SN/A case IHR: 9372292SN/A regs.ihr = reg; 9382292SN/A /* not going to implement real interrupt holdoff */ 9392292SN/A break; 9402292SN/A 9412292SN/A case TXDP: 9422292SN/A regs.txdp = (reg & 0xFFFFFFFC); 9432292SN/A assert(txState == txIdle); 9442292SN/A CTDD = false; 9452292SN/A break; 9462292SN/A 9472292SN/A case TXDP_HI: 9482292SN/A regs.txdp_hi = reg; 9492292SN/A break; 9502292SN/A 9512292SN/A case TX_CFG: 9522292SN/A regs.txcfg = reg; 9532292SN/A#if 0 9542292SN/A if (reg & TX_CFG_CSI) ; 9552292SN/A if (reg & TX_CFG_HBI) ; 9562292SN/A if (reg & TX_CFG_MLB) ; 9572329SN/A if (reg & TX_CFG_ATP) ; 9582292SN/A if (reg & TX_CFG_ECRETRY) { 9592292SN/A /* 9602292SN/A * this could easily be implemented, but considering 9612292SN/A * the network is just a fake pipe, wouldn't make 9622292SN/A * sense to do this 9637720Sgblack@eecs.umich.edu */ 9642292SN/A } 9657720Sgblack@eecs.umich.edu 9662292SN/A if (reg & TX_CFG_BRST_DIS) ; 9672292SN/A#endif 9682292SN/A 9692292SN/A#if 0 9702292SN/A /* we handle our own DMA, ignore the kernel's exhortations */ 9712292SN/A if (reg & TX_CFG_MXDMA) ; 9722292SN/A#endif 9732292SN/A 9742329SN/A // also, we currently don't care about fill/drain 9752731Sktlim@umich.edu // thresholds though this may change in the future with 9762292SN/A // more realistic networks or a driver which changes it 9772292SN/A // according to feedback 9782292SN/A 9792292SN/A break; 9802292SN/A 9812292SN/A case GPIOR: 9822292SN/A regs.gpior = reg; 9832727Sktlim@umich.edu /* these just control general purpose i/o pins, don't matter */ 9842292SN/A break; 9852292SN/A 9862292SN/A case RXDP: 9872292SN/A regs.rxdp = reg; 9882292SN/A CRDD = false; 9892292SN/A break; 9902292SN/A 9912292SN/A case RXDP_HI: 9922292SN/A regs.rxdp_hi = reg; 9932292SN/A break; 9944032Sktlim@umich.edu 9954032Sktlim@umich.edu case RX_CFG: 9964032Sktlim@umich.edu regs.rxcfg = reg; 9974032Sktlim@umich.edu#if 0 9982292SN/A if (reg & RX_CFG_AEP) ; 9992292SN/A if (reg & RX_CFG_ARP) ; 10002292SN/A if (reg & RX_CFG_STRIPCRC) ; 10012292SN/A if (reg & RX_CFG_RX_RD) ; 10022292SN/A if (reg & RX_CFG_ALP) ; 10032329SN/A if (reg & RX_CFG_AIRL) ; 10042292SN/A 10052292SN/A /* we handle our own DMA, ignore what kernel says about it */ 10062292SN/A if (reg & RX_CFG_MXDMA) ; 10072292SN/A 10087720Sgblack@eecs.umich.edu //also, we currently don't care about fill/drain thresholds 10092292SN/A //though this may change in the future with more realistic 10107720Sgblack@eecs.umich.edu //networks or a driver which changes it according to feedback 10112292SN/A if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 10122292SN/A#endif 10132329SN/A break; 10142329SN/A 10152292SN/A case PQCR: 10162292SN/A /* there is no priority queueing used in the linux 2.6 driver */ 10172292SN/A regs.pqcr = reg; 10182292SN/A break; 10192292SN/A 10202292SN/A case WCSR: 10212292SN/A /* not going to implement wake on LAN */ 10222329SN/A regs.wcsr = reg; 10232731Sktlim@umich.edu break; 10242292SN/A 10252292SN/A case PCR: 10262292SN/A /* not going to implement pause control */ 10274032Sktlim@umich.edu regs.pcr = reg; 10284032Sktlim@umich.edu break; 10294032Sktlim@umich.edu 10304032Sktlim@umich.edu case RFCR: 10316974Stjones1@inf.ed.ac.uk regs.rfcr = reg; 10326974Stjones1@inf.ed.ac.uk 10336974Stjones1@inf.ed.ac.uk rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 10346974Stjones1@inf.ed.ac.uk acceptBroadcast = (reg & RFCR_AAB) ? true : false; 10356974Stjones1@inf.ed.ac.uk acceptMulticast = (reg & RFCR_AAM) ? true : false; 10366974Stjones1@inf.ed.ac.uk acceptUnicast = (reg & RFCR_AAU) ? true : false; 10376974Stjones1@inf.ed.ac.uk acceptPerfect = (reg & RFCR_APM) ? true : false; 10384032Sktlim@umich.edu acceptArp = (reg & RFCR_AARP) ? true : false; 10392292SN/A 10402292SN/A#if 0 10412292SN/A if (reg & RFCR_APAT) 10422292SN/A panic("RFCR_APAT not implemented!\n"); 10432292SN/A#endif 10442292SN/A 10452292SN/A if (reg & RFCR_MHEN || reg & RFCR_UHEN) 10462727Sktlim@umich.edu panic("hash filtering not implemented!\n"); 10472292SN/A 10482292SN/A if (reg & RFCR_ULM) 10492292SN/A panic("RFCR_ULM not implemented!\n"); 10502292SN/A 10512292SN/A break; 10523349Sbinkertn@umich.edu 10532693Sktlim@umich.edu case RFDR: 10542693Sktlim@umich.edu panic("the driver never writes to RFDR, something is wrong!\n"); 10552693Sktlim@umich.edu 10562693Sktlim@umich.edu case BRAR: 10572693Sktlim@umich.edu panic("the driver never uses BRAR, something is wrong!\n"); 10582693Sktlim@umich.edu 10592693Sktlim@umich.edu case BRDR: 10602693Sktlim@umich.edu panic("the driver never uses BRDR, something is wrong!\n"); 10612693Sktlim@umich.edu 10622693Sktlim@umich.edu case SRR: 10632693Sktlim@umich.edu panic("SRR is read only register!\n"); 10642693Sktlim@umich.edu 10652693Sktlim@umich.edu case MIBC: 10662693Sktlim@umich.edu panic("the driver never uses MIBC, something is wrong!\n"); 10672693Sktlim@umich.edu 10682693Sktlim@umich.edu case VRCR: 10698887Sgeoffrey.blake@arm.com regs.vrcr = reg; 10702693Sktlim@umich.edu break; 10712732Sktlim@umich.edu 10722693Sktlim@umich.edu case VTCR: 10732693Sktlim@umich.edu regs.vtcr = reg; 10742693Sktlim@umich.edu break; 10758727Snilay@cs.wisc.edu 10768727Snilay@cs.wisc.edu case VDR: 10778727Snilay@cs.wisc.edu panic("the driver never uses VDR, something is wrong!\n"); 10788727Snilay@cs.wisc.edu break; 10792693Sktlim@umich.edu 10802693Sktlim@umich.edu case CCSR: 10812693Sktlim@umich.edu /* not going to implement clockrun stuff */ 10822693Sktlim@umich.edu regs.ccsr = reg; 10832693Sktlim@umich.edu break; 10842678Sktlim@umich.edu 10852678Sktlim@umich.edu case TBICR: 10862678Sktlim@umich.edu regs.tbicr = reg; 10872678Sktlim@umich.edu if (reg & TBICR_MR_LOOPBACK) 10882678Sktlim@umich.edu panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 10892678Sktlim@umich.edu 10902927Sktlim@umich.edu if (reg & TBICR_MR_AN_ENABLE) { 10912678Sktlim@umich.edu regs.tanlpar = regs.tanar; 10922727Sktlim@umich.edu regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 10932678Sktlim@umich.edu } 10942678Sktlim@umich.edu 10952678Sktlim@umich.edu#if 0 10962678Sktlim@umich.edu if (reg & TBICR_MR_RESTART_AN) ; 10972678Sktlim@umich.edu#endif 10982678Sktlim@umich.edu 10992678Sktlim@umich.edu break; 11002678Sktlim@umich.edu 11012678Sktlim@umich.edu case TBISR: 11022678Sktlim@umich.edu panic("TBISR is read only register!\n"); 11032678Sktlim@umich.edu 11042678Sktlim@umich.edu case TANAR: 11052678Sktlim@umich.edu regs.tanar = reg; 11062678Sktlim@umich.edu if (reg & TANAR_PS2) 11077598Sminkyu.jeong@arm.com panic("this isn't used in driver, something wrong!\n"); 11087598Sminkyu.jeong@arm.com 11097598Sminkyu.jeong@arm.com if (reg & TANAR_PS1) 11102678Sktlim@umich.edu panic("this isn't used in driver, something wrong!\n"); 11112678Sktlim@umich.edu break; 11122678Sktlim@umich.edu 11132678Sktlim@umich.edu case TANLPAR: 11142292SN/A panic("this should only be written to by the fake phy!\n"); 11152292SN/A 11162292SN/A case TANER: 11172292SN/A panic("TANER is read only register!\n"); 11182292SN/A 11192292SN/A case TESR: 11202292SN/A regs.tesr = reg; 11212292SN/A break; 11223126Sktlim@umich.edu 11232292SN/A default: 11242292SN/A panic("invalid register access daddr=%#x", daddr); 11252292SN/A } 11262292SN/A } else { 11272292SN/A panic("Invalid Request Size"); 11282292SN/A } 11292292SN/A 11302292SN/A return No_Fault; 11312292SN/A} 11322292SN/A 11332292SN/Avoid 11342292SN/ANSGigE::devIntrPost(uint32_t interrupts) 11352292SN/A{ 11362329SN/A if (interrupts & ISR_RESERVE) 11372329SN/A panic("Cannot set a reserved interrupt"); 11382329SN/A 11392292SN/A if (interrupts & ISR_NOIMPL) 11402292SN/A warn("interrupt not implemented %#x\n", interrupts); 11412292SN/A 11422292SN/A interrupts &= ~ISR_NOIMPL; 11432292SN/A regs.isr |= interrupts; 11442292SN/A 11452292SN/A if (interrupts & regs.imr) { 11462292SN/A if (interrupts & ISR_SWI) { 11472292SN/A totalSwi++; 11482292SN/A } 11492316SN/A if (interrupts & ISR_RXIDLE) { 11502316SN/A totalRxIdle++; 11512329SN/A } 11528727Snilay@cs.wisc.edu if (interrupts & ISR_RXOK) { 11538727Snilay@cs.wisc.edu totalRxOk++; 11548727Snilay@cs.wisc.edu } 11558727Snilay@cs.wisc.edu if (interrupts & ISR_RXDESC) { 11562329SN/A totalRxDesc++; 11572329SN/A } 11582329SN/A if (interrupts & ISR_TXOK) { 11592316SN/A totalTxOk++; 11602732Sktlim@umich.edu } 11612316SN/A if (interrupts & ISR_TXIDLE) { 11622292SN/A totalTxIdle++; 11632292SN/A } 11642292SN/A if (interrupts & ISR_TXDESC) { 11656974Stjones1@inf.ed.ac.uk totalTxDesc++; 11666974Stjones1@inf.ed.ac.uk } 11676974Stjones1@inf.ed.ac.uk if (interrupts & ISR_RXORN) { 11688975Sandreas.hansson@arm.com totalRxOrn++; 11696974Stjones1@inf.ed.ac.uk } 11706974Stjones1@inf.ed.ac.uk } 11716974Stjones1@inf.ed.ac.uk 11726974Stjones1@inf.ed.ac.uk DPRINTF(EthernetIntr, 11736974Stjones1@inf.ed.ac.uk "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 11746974Stjones1@inf.ed.ac.uk interrupts, regs.isr, regs.imr); 11756974Stjones1@inf.ed.ac.uk 11766974Stjones1@inf.ed.ac.uk if ((regs.isr & regs.imr)) { 11776974Stjones1@inf.ed.ac.uk Tick when = curTick; 11786974Stjones1@inf.ed.ac.uk if (!(regs.isr & regs.imr & ISR_NODELAY)) 11796974Stjones1@inf.ed.ac.uk when += intrDelay; 11806974Stjones1@inf.ed.ac.uk cpuIntrPost(when); 11812693Sktlim@umich.edu } 11822693Sktlim@umich.edu} 11832693Sktlim@umich.edu 11842698Sktlim@umich.edu/* writing this interrupt counting stats inside this means that this function 11854985Sktlim@umich.edu is now limited to being used to clear all interrupts upon the kernel 11862698Sktlim@umich.edu reading isr and servicing. just telling you in case you were thinking 11872693Sktlim@umich.edu of expanding use. 11888587Snilay@cs.wisc.edu*/ 11898587Snilay@cs.wisc.eduvoid 11908587Snilay@cs.wisc.eduNSGigE::devIntrClear(uint32_t interrupts) 11918975Sandreas.hansson@arm.com{ 11926974Stjones1@inf.ed.ac.uk if (interrupts & ISR_RESERVE) 11938133SAli.Saidi@ARM.com panic("Cannot clear a reserved interrupt"); 11948133SAli.Saidi@ARM.com 11958133SAli.Saidi@ARM.com if (regs.isr & regs.imr & ISR_SWI) { 11966974Stjones1@inf.ed.ac.uk postedSwi++; 11976974Stjones1@inf.ed.ac.uk } 11982699Sktlim@umich.edu if (regs.isr & regs.imr & ISR_RXIDLE) { 11992693Sktlim@umich.edu postedRxIdle++; 12006221Snate@binkert.org } 12016974Stjones1@inf.ed.ac.uk if (regs.isr & regs.imr & ISR_RXOK) { 12026974Stjones1@inf.ed.ac.uk postedRxOk++; 12036974Stjones1@inf.ed.ac.uk } 12046974Stjones1@inf.ed.ac.uk if (regs.isr & regs.imr & ISR_RXDESC) { 12056974Stjones1@inf.ed.ac.uk postedRxDesc++; 12066974Stjones1@inf.ed.ac.uk } 12076974Stjones1@inf.ed.ac.uk if (regs.isr & regs.imr & ISR_TXOK) { 12086974Stjones1@inf.ed.ac.uk postedTxOk++; 12092693Sktlim@umich.edu } 12102693Sktlim@umich.edu if (regs.isr & regs.imr & ISR_TXIDLE) { 12112727Sktlim@umich.edu postedTxIdle++; 12122907Sktlim@umich.edu } 12132693Sktlim@umich.edu if (regs.isr & regs.imr & ISR_TXDESC) { 12142693Sktlim@umich.edu postedTxDesc++; 12152693Sktlim@umich.edu } 12162693Sktlim@umich.edu if (regs.isr & regs.imr & ISR_RXORN) { 12172693Sktlim@umich.edu postedRxOrn++; 12182693Sktlim@umich.edu } 12192693Sktlim@umich.edu 12202693Sktlim@umich.edu if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC | 12212693Sktlim@umich.edu ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) ) 12222693Sktlim@umich.edu postedInterrupts++; 12232292SN/A 12249440SAndreas.Sandberg@ARM.com interrupts &= ~ISR_NOIMPL; 12252292SN/A regs.isr &= ~interrupts; 12262292SN/A 12272292SN/A DPRINTF(EthernetIntr, 12282292SN/A "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 12292292SN/A interrupts, regs.isr, regs.imr); 12302292SN/A 12312292SN/A if (!(regs.isr & regs.imr)) 12329440SAndreas.Sandberg@ARM.com cpuIntrClear(); 12332292SN/A} 12342292SN/A 12352292SN/Avoid 12362292SN/ANSGigE::devIntrChangeMask() 12372292SN/A{ 12382292SN/A DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 12392292SN/A regs.isr, regs.imr, regs.isr & regs.imr); 12409440SAndreas.Sandberg@ARM.com 12412292SN/A if (regs.isr & regs.imr) 12422292SN/A cpuIntrPost(curTick); 12432292SN/A else 12442292SN/A cpuIntrClear(); 12452292SN/A} 12462292SN/A 12472292SN/Avoid 12489440SAndreas.Sandberg@ARM.comNSGigE::cpuIntrPost(Tick when) 12492292SN/A{ 12502292SN/A // If the interrupt you want to post is later than an interrupt 12512292SN/A // already scheduled, just let it post in the coming one and don't 12522292SN/A // schedule another. 12532329SN/A // HOWEVER, must be sure that the scheduled intrTick is in the 12542329SN/A // future (this was formerly the source of a bug) 12552329SN/A /** 12569440SAndreas.Sandberg@ARM.com * @todo this warning should be removed and the intrTick code should 12572329SN/A * be fixed. 12582329SN/A */ 12592329SN/A assert(when >= curTick); 12602329SN/A assert(intrTick >= curTick || intrTick == 0); 12612329SN/A if (when > intrTick && intrTick != 0) { 12622329SN/A DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 12632329SN/A intrTick); 12642329SN/A return; 12659440SAndreas.Sandberg@ARM.com } 12669440SAndreas.Sandberg@ARM.com 12672329SN/A intrTick = when; 12682329SN/A if (intrTick < curTick) { 12692329SN/A debug_break(); 12709440SAndreas.Sandberg@ARM.com intrTick = curTick; 12712329SN/A } 12722329SN/A 12732329SN/A DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 12742329SN/A intrTick); 12752329SN/A 12762329SN/A if (intrEvent) 12772329SN/A intrEvent->squash(); 12789440SAndreas.Sandberg@ARM.com intrEvent = new IntrEvent(this, true); 12799440SAndreas.Sandberg@ARM.com intrEvent->schedule(intrTick); 12802329SN/A} 12812329SN/A 12822329SN/Avoid 12832329SN/ANSGigE::cpuInterrupt() 12842329SN/A{ 12852329SN/A assert(intrTick == curTick); 1286 1287 // Whether or not there's a pending interrupt, we don't care about 1288 // it anymore 1289 intrEvent = 0; 1290 intrTick = 0; 1291 1292 // Don't send an interrupt if there's already one 1293 if (cpuPendingIntr) { 1294 DPRINTF(EthernetIntr, 1295 "would send an interrupt now, but there's already pending\n"); 1296 } else { 1297 // Send interrupt 1298 cpuPendingIntr = true; 1299 1300 DPRINTF(EthernetIntr, "posting interrupt\n"); 1301 intrPost(); 1302 } 1303} 1304 1305void 1306NSGigE::cpuIntrClear() 1307{ 1308 if (!cpuPendingIntr) 1309 return; 1310 1311 if (intrEvent) { 1312 intrEvent->squash(); 1313 intrEvent = 0; 1314 } 1315 1316 intrTick = 0; 1317 1318 cpuPendingIntr = false; 1319 1320 DPRINTF(EthernetIntr, "clearing interrupt\n"); 1321 intrClear(); 1322} 1323 1324bool 1325NSGigE::cpuIntrPending() const 1326{ return cpuPendingIntr; } 1327 1328void 1329NSGigE::txReset() 1330{ 1331 1332 DPRINTF(Ethernet, "transmit reset\n"); 1333 1334 CTDD = false; 1335 txEnable = false;; 1336 txFragPtr = 0; 1337 assert(txDescCnt == 0); 1338 txFifo.clear(); 1339 txState = txIdle; 1340 assert(txDmaState == dmaIdle); 1341} 1342 1343void 1344NSGigE::rxReset() 1345{ 1346 DPRINTF(Ethernet, "receive reset\n"); 1347 1348 CRDD = false; 1349 assert(rxPktBytes == 0); 1350 rxEnable = false; 1351 rxFragPtr = 0; 1352 assert(rxDescCnt == 0); 1353 assert(rxDmaState == dmaIdle); 1354 rxFifo.clear(); 1355 rxState = rxIdle; 1356} 1357 1358void 1359NSGigE::regsReset() 1360{ 1361 memset(®s, 0, sizeof(regs)); 1362 regs.config = CFGR_LNKSTS; 1363 regs.mear = 0x22; 1364 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1365 // fill threshold to 32 bytes 1366 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1367 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1368 regs.mibc = MIBC_FRZ; 1369 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1370 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1371 1372 extstsEnable = false; 1373 acceptBroadcast = false; 1374 acceptMulticast = false; 1375 acceptUnicast = false; 1376 acceptPerfect = false; 1377 acceptArp = false; 1378} 1379 1380void 1381NSGigE::rxDmaReadCopy() 1382{ 1383 assert(rxDmaState == dmaReading); 1384 1385 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1386 rxDmaState = dmaIdle; 1387 1388 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1389 rxDmaAddr, rxDmaLen); 1390 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1391} 1392 1393bool 1394NSGigE::doRxDmaRead() 1395{ 1396 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1397 rxDmaState = dmaReading; 1398 1399 if (dmaInterface && !rxDmaFree) { 1400 if (dmaInterface->busy()) 1401 rxDmaState = dmaReadWaiting; 1402 else 1403 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1404 &rxDmaReadEvent, true); 1405 return true; 1406 } 1407 1408 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1409 rxDmaReadCopy(); 1410 return false; 1411 } 1412 1413 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1414 Tick start = curTick + dmaReadDelay + factor; 1415 rxDmaReadEvent.schedule(start); 1416 return true; 1417} 1418 1419void 1420NSGigE::rxDmaReadDone() 1421{ 1422 assert(rxDmaState == dmaReading); 1423 rxDmaReadCopy(); 1424 1425 // If the transmit state machine has a pending DMA, let it go first 1426 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1427 txKick(); 1428 1429 rxKick(); 1430} 1431 1432void 1433NSGigE::rxDmaWriteCopy() 1434{ 1435 assert(rxDmaState == dmaWriting); 1436 1437 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1438 rxDmaState = dmaIdle; 1439 1440 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1441 rxDmaAddr, rxDmaLen); 1442 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1443} 1444 1445bool 1446NSGigE::doRxDmaWrite() 1447{ 1448 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1449 rxDmaState = dmaWriting; 1450 1451 if (dmaInterface && !rxDmaFree) { 1452 if (dmaInterface->busy()) 1453 rxDmaState = dmaWriteWaiting; 1454 else 1455 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1456 &rxDmaWriteEvent, true); 1457 return true; 1458 } 1459 1460 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1461 rxDmaWriteCopy(); 1462 return false; 1463 } 1464 1465 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1466 Tick start = curTick + dmaWriteDelay + factor; 1467 rxDmaWriteEvent.schedule(start); 1468 return true; 1469} 1470 1471void 1472NSGigE::rxDmaWriteDone() 1473{ 1474 assert(rxDmaState == dmaWriting); 1475 rxDmaWriteCopy(); 1476 1477 // If the transmit state machine has a pending DMA, let it go first 1478 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1479 txKick(); 1480 1481 rxKick(); 1482} 1483 1484void 1485NSGigE::rxKick() 1486{ 1487 DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", 1488 NsRxStateStrings[rxState], rxFifo.size()); 1489 1490 if (rxKickTick > curTick) { 1491 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1492 rxKickTick); 1493 return; 1494 } 1495 1496 next: 1497 switch(rxDmaState) { 1498 case dmaReadWaiting: 1499 if (doRxDmaRead()) 1500 goto exit; 1501 break; 1502 case dmaWriteWaiting: 1503 if (doRxDmaWrite()) 1504 goto exit; 1505 break; 1506 default: 1507 break; 1508 } 1509 1510 // see state machine from spec for details 1511 // the way this works is, if you finish work on one state and can 1512 // go directly to another, you do that through jumping to the 1513 // label "next". however, if you have intermediate work, like DMA 1514 // so that you can't go to the next state yet, you go to exit and 1515 // exit the loop. however, when the DMA is done it will trigger 1516 // an event and come back to this loop. 1517 switch (rxState) { 1518 case rxIdle: 1519 if (!rxEnable) { 1520 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1521 goto exit; 1522 } 1523 1524 if (CRDD) { 1525 rxState = rxDescRefr; 1526 1527 rxDmaAddr = regs.rxdp & 0x3fffffff; 1528 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1529 rxDmaLen = sizeof(rxDescCache.link); 1530 rxDmaFree = dmaDescFree; 1531 1532 descDmaReads++; 1533 descDmaRdBytes += rxDmaLen; 1534 1535 if (doRxDmaRead()) 1536 goto exit; 1537 } else { 1538 rxState = rxDescRead; 1539 1540 rxDmaAddr = regs.rxdp & 0x3fffffff; 1541 rxDmaData = &rxDescCache; 1542 rxDmaLen = sizeof(ns_desc); 1543 rxDmaFree = dmaDescFree; 1544 1545 descDmaReads++; 1546 descDmaRdBytes += rxDmaLen; 1547 1548 if (doRxDmaRead()) 1549 goto exit; 1550 } 1551 break; 1552 1553 case rxDescRefr: 1554 if (rxDmaState != dmaIdle) 1555 goto exit; 1556 1557 rxState = rxAdvance; 1558 break; 1559 1560 case rxDescRead: 1561 if (rxDmaState != dmaIdle) 1562 goto exit; 1563 1564 DPRINTF(EthernetDesc, 1565 "rxDescCache: addr=%08x read descriptor\n", 1566 regs.rxdp & 0x3fffffff); 1567 DPRINTF(EthernetDesc, 1568 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1569 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1570 rxDescCache.extsts); 1571 1572 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1573 devIntrPost(ISR_RXIDLE); 1574 rxState = rxIdle; 1575 goto exit; 1576 } else { 1577 rxState = rxFifoBlock; 1578 rxFragPtr = rxDescCache.bufptr; 1579 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1580 } 1581 break; 1582 1583 case rxFifoBlock: 1584 if (!rxPacket) { 1585 /** 1586 * @todo in reality, we should be able to start processing 1587 * the packet as it arrives, and not have to wait for the 1588 * full packet ot be in the receive fifo. 1589 */ 1590 if (rxFifo.empty()) 1591 goto exit; 1592 1593 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1594 1595 // If we don't have a packet, grab a new one from the fifo. 1596 rxPacket = rxFifo.front(); 1597 rxPktBytes = rxPacket->length; 1598 rxPacketBufPtr = rxPacket->data; 1599 1600#if TRACING_ON 1601 if (DTRACE(Ethernet)) { 1602 IpPtr ip(rxPacket); 1603 if (ip) { 1604 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1605 TcpPtr tcp(ip); 1606 if (tcp) { 1607 DPRINTF(Ethernet, 1608 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1609 tcp->sport(), tcp->dport(), tcp->seq(), 1610 tcp->ack()); 1611 } 1612 } 1613 } 1614#endif 1615 1616 // sanity check - i think the driver behaves like this 1617 assert(rxDescCnt >= rxPktBytes); 1618 rxFifo.pop(); 1619 } 1620 1621 1622 // dont' need the && rxDescCnt > 0 if driver sanity check 1623 // above holds 1624 if (rxPktBytes > 0) { 1625 rxState = rxFragWrite; 1626 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1627 // check holds 1628 rxXferLen = rxPktBytes; 1629 1630 rxDmaAddr = rxFragPtr & 0x3fffffff; 1631 rxDmaData = rxPacketBufPtr; 1632 rxDmaLen = rxXferLen; 1633 rxDmaFree = dmaDataFree; 1634 1635 if (doRxDmaWrite()) 1636 goto exit; 1637 1638 } else { 1639 rxState = rxDescWrite; 1640 1641 //if (rxPktBytes == 0) { /* packet is done */ 1642 assert(rxPktBytes == 0); 1643 DPRINTF(EthernetSM, "done with receiving packet\n"); 1644 1645 rxDescCache.cmdsts |= CMDSTS_OWN; 1646 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1647 rxDescCache.cmdsts |= CMDSTS_OK; 1648 rxDescCache.cmdsts &= 0xffff0000; 1649 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1650 1651#if 0 1652 /* 1653 * all the driver uses these are for its own stats keeping 1654 * which we don't care about, aren't necessary for 1655 * functionality and doing this would just slow us down. 1656 * if they end up using this in a later version for 1657 * functional purposes, just undef 1658 */ 1659 if (rxFilterEnable) { 1660 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1661 const EthAddr &dst = rxFifoFront()->dst(); 1662 if (dst->unicast()) 1663 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1664 if (dst->multicast()) 1665 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1666 if (dst->broadcast()) 1667 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1668 } 1669#endif 1670 1671 IpPtr ip(rxPacket); 1672 if (extstsEnable && ip) { 1673 rxDescCache.extsts |= EXTSTS_IPPKT; 1674 rxIpChecksums++; 1675 if (cksum(ip) != 0) { 1676 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1677 rxDescCache.extsts |= EXTSTS_IPERR; 1678 } 1679 TcpPtr tcp(ip); 1680 UdpPtr udp(ip); 1681 if (tcp) { 1682 rxDescCache.extsts |= EXTSTS_TCPPKT; 1683 rxTcpChecksums++; 1684 if (cksum(tcp) != 0) { 1685 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1686 rxDescCache.extsts |= EXTSTS_TCPERR; 1687 1688 } 1689 } else if (udp) { 1690 rxDescCache.extsts |= EXTSTS_UDPPKT; 1691 rxUdpChecksums++; 1692 if (cksum(udp) != 0) { 1693 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1694 rxDescCache.extsts |= EXTSTS_UDPERR; 1695 } 1696 } 1697 } 1698 rxPacket = 0; 1699 1700 /* 1701 * the driver seems to always receive into desc buffers 1702 * of size 1514, so you never have a pkt that is split 1703 * into multiple descriptors on the receive side, so 1704 * i don't implement that case, hence the assert above. 1705 */ 1706 1707 DPRINTF(EthernetDesc, 1708 "rxDescCache: addr=%08x writeback cmdsts extsts\n", 1709 regs.rxdp & 0x3fffffff); 1710 DPRINTF(EthernetDesc, 1711 "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 1712 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1713 rxDescCache.extsts); 1714 1715 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1716 rxDmaData = &(rxDescCache.cmdsts); 1717 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1718 rxDmaFree = dmaDescFree; 1719 1720 descDmaWrites++; 1721 descDmaWrBytes += rxDmaLen; 1722 1723 if (doRxDmaWrite()) 1724 goto exit; 1725 } 1726 break; 1727 1728 case rxFragWrite: 1729 if (rxDmaState != dmaIdle) 1730 goto exit; 1731 1732 rxPacketBufPtr += rxXferLen; 1733 rxFragPtr += rxXferLen; 1734 rxPktBytes -= rxXferLen; 1735 1736 rxState = rxFifoBlock; 1737 break; 1738 1739 case rxDescWrite: 1740 if (rxDmaState != dmaIdle) 1741 goto exit; 1742 1743 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1744 1745 assert(rxPacket == 0); 1746 devIntrPost(ISR_RXOK); 1747 1748 if (rxDescCache.cmdsts & CMDSTS_INTR) 1749 devIntrPost(ISR_RXDESC); 1750 1751 if (!rxEnable) { 1752 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1753 rxState = rxIdle; 1754 goto exit; 1755 } else 1756 rxState = rxAdvance; 1757 break; 1758 1759 case rxAdvance: 1760 if (rxDescCache.link == 0) { 1761 devIntrPost(ISR_RXIDLE); 1762 rxState = rxIdle; 1763 CRDD = true; 1764 goto exit; 1765 } else { 1766 rxState = rxDescRead; 1767 regs.rxdp = rxDescCache.link; 1768 CRDD = false; 1769 1770 rxDmaAddr = regs.rxdp & 0x3fffffff; 1771 rxDmaData = &rxDescCache; 1772 rxDmaLen = sizeof(ns_desc); 1773 rxDmaFree = dmaDescFree; 1774 1775 if (doRxDmaRead()) 1776 goto exit; 1777 } 1778 break; 1779 1780 default: 1781 panic("Invalid rxState!"); 1782 } 1783 1784 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1785 NsRxStateStrings[rxState]); 1786 1787 goto next; 1788 1789 exit: 1790 /** 1791 * @todo do we want to schedule a future kick? 1792 */ 1793 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1794 NsRxStateStrings[rxState]); 1795} 1796 1797void 1798NSGigE::transmit() 1799{ 1800 if (txFifo.empty()) { 1801 DPRINTF(Ethernet, "nothing to transmit\n"); 1802 return; 1803 } 1804 1805 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1806 txFifo.size()); 1807 if (interface->sendPacket(txFifo.front())) { 1808#if TRACING_ON 1809 if (DTRACE(Ethernet)) { 1810 IpPtr ip(txFifo.front()); 1811 if (ip) { 1812 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1813 TcpPtr tcp(ip); 1814 if (tcp) { 1815 DPRINTF(Ethernet, 1816 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1817 tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack()); 1818 } 1819 } 1820 } 1821#endif 1822 1823 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1824 txBytes += txFifo.front()->length; 1825 txPackets++; 1826 1827 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1828 txFifo.avail()); 1829 txFifo.pop(); 1830 1831 /* 1832 * normally do a writeback of the descriptor here, and ONLY 1833 * after that is done, send this interrupt. but since our 1834 * stuff never actually fails, just do this interrupt here, 1835 * otherwise the code has to stray from this nice format. 1836 * besides, it's functionally the same. 1837 */ 1838 devIntrPost(ISR_TXOK); 1839 } 1840 1841 if (!txFifo.empty() && !txEvent.scheduled()) { 1842 DPRINTF(Ethernet, "reschedule transmit\n"); 1843 txEvent.schedule(curTick + retryTime); 1844 } 1845} 1846 1847void 1848NSGigE::txDmaReadCopy() 1849{ 1850 assert(txDmaState == dmaReading); 1851 1852 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1853 txDmaState = dmaIdle; 1854 1855 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1856 txDmaAddr, txDmaLen); 1857 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1858} 1859 1860bool 1861NSGigE::doTxDmaRead() 1862{ 1863 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1864 txDmaState = dmaReading; 1865 1866 if (dmaInterface && !txDmaFree) { 1867 if (dmaInterface->busy()) 1868 txDmaState = dmaReadWaiting; 1869 else 1870 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1871 &txDmaReadEvent, true); 1872 return true; 1873 } 1874 1875 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1876 txDmaReadCopy(); 1877 return false; 1878 } 1879 1880 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1881 Tick start = curTick + dmaReadDelay + factor; 1882 txDmaReadEvent.schedule(start); 1883 return true; 1884} 1885 1886void 1887NSGigE::txDmaReadDone() 1888{ 1889 assert(txDmaState == dmaReading); 1890 txDmaReadCopy(); 1891 1892 // If the receive state machine has a pending DMA, let it go first 1893 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1894 rxKick(); 1895 1896 txKick(); 1897} 1898 1899void 1900NSGigE::txDmaWriteCopy() 1901{ 1902 assert(txDmaState == dmaWriting); 1903 1904 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1905 txDmaState = dmaIdle; 1906 1907 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1908 txDmaAddr, txDmaLen); 1909 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1910} 1911 1912bool 1913NSGigE::doTxDmaWrite() 1914{ 1915 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1916 txDmaState = dmaWriting; 1917 1918 if (dmaInterface && !txDmaFree) { 1919 if (dmaInterface->busy()) 1920 txDmaState = dmaWriteWaiting; 1921 else 1922 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1923 &txDmaWriteEvent, true); 1924 return true; 1925 } 1926 1927 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1928 txDmaWriteCopy(); 1929 return false; 1930 } 1931 1932 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1933 Tick start = curTick + dmaWriteDelay + factor; 1934 txDmaWriteEvent.schedule(start); 1935 return true; 1936} 1937 1938void 1939NSGigE::txDmaWriteDone() 1940{ 1941 assert(txDmaState == dmaWriting); 1942 txDmaWriteCopy(); 1943 1944 // If the receive state machine has a pending DMA, let it go first 1945 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1946 rxKick(); 1947 1948 txKick(); 1949} 1950 1951void 1952NSGigE::txKick() 1953{ 1954 DPRINTF(EthernetSM, "transmit kick txState=%s\n", 1955 NsTxStateStrings[txState]); 1956 1957 if (txKickTick > curTick) { 1958 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1959 txKickTick); 1960 1961 return; 1962 } 1963 1964 next: 1965 switch(txDmaState) { 1966 case dmaReadWaiting: 1967 if (doTxDmaRead()) 1968 goto exit; 1969 break; 1970 case dmaWriteWaiting: 1971 if (doTxDmaWrite()) 1972 goto exit; 1973 break; 1974 default: 1975 break; 1976 } 1977 1978 switch (txState) { 1979 case txIdle: 1980 if (!txEnable) { 1981 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1982 goto exit; 1983 } 1984 1985 if (CTDD) { 1986 txState = txDescRefr; 1987 1988 txDmaAddr = regs.txdp & 0x3fffffff; 1989 txDmaData = &txDescCache + offsetof(ns_desc, link); 1990 txDmaLen = sizeof(txDescCache.link); 1991 txDmaFree = dmaDescFree; 1992 1993 descDmaReads++; 1994 descDmaRdBytes += txDmaLen; 1995 1996 if (doTxDmaRead()) 1997 goto exit; 1998 1999 } else { 2000 txState = txDescRead; 2001 2002 txDmaAddr = regs.txdp & 0x3fffffff; 2003 txDmaData = &txDescCache; 2004 txDmaLen = sizeof(ns_desc); 2005 txDmaFree = dmaDescFree; 2006 2007 descDmaReads++; 2008 descDmaRdBytes += txDmaLen; 2009 2010 if (doTxDmaRead()) 2011 goto exit; 2012 } 2013 break; 2014 2015 case txDescRefr: 2016 if (txDmaState != dmaIdle) 2017 goto exit; 2018 2019 txState = txAdvance; 2020 break; 2021 2022 case txDescRead: 2023 if (txDmaState != dmaIdle) 2024 goto exit; 2025 2026 DPRINTF(EthernetDesc, 2027 "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", 2028 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 2029 txDescCache.extsts); 2030 2031 if (txDescCache.cmdsts & CMDSTS_OWN) { 2032 txState = txFifoBlock; 2033 txFragPtr = txDescCache.bufptr; 2034 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 2035 } else { 2036 devIntrPost(ISR_TXIDLE); 2037 txState = txIdle; 2038 goto exit; 2039 } 2040 break; 2041 2042 case txFifoBlock: 2043 if (!txPacket) { 2044 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2045 txPacket = new PacketData(16384); 2046 txPacketBufPtr = txPacket->data; 2047 } 2048 2049 if (txDescCnt == 0) { 2050 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 2051 if (txDescCache.cmdsts & CMDSTS_MORE) { 2052 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2053 txState = txDescWrite; 2054 2055 txDescCache.cmdsts &= ~CMDSTS_OWN; 2056 2057 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2058 txDmaAddr &= 0x3fffffff; 2059 txDmaData = &(txDescCache.cmdsts); 2060 txDmaLen = sizeof(txDescCache.cmdsts); 2061 txDmaFree = dmaDescFree; 2062 2063 if (doTxDmaWrite()) 2064 goto exit; 2065 2066 } else { /* this packet is totally done */ 2067 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2068 /* deal with the the packet that just finished */ 2069 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2070 IpPtr ip(txPacket); 2071 if (txDescCache.extsts & EXTSTS_UDPPKT) { 2072 UdpPtr udp(ip); 2073 udp->sum(0); 2074 udp->sum(cksum(udp)); 2075 txUdpChecksums++; 2076 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 2077 TcpPtr tcp(ip); 2078 tcp->sum(0); 2079 tcp->sum(cksum(tcp)); 2080 txTcpChecksums++; 2081 } 2082 if (txDescCache.extsts & EXTSTS_IPPKT) { 2083 ip->sum(0); 2084 ip->sum(cksum(ip)); 2085 txIpChecksums++; 2086 } 2087 } 2088 2089 txPacket->length = txPacketBufPtr - txPacket->data; 2090 // this is just because the receive can't handle a 2091 // packet bigger want to make sure 2092 assert(txPacket->length <= 1514); 2093#ifndef NDEBUG 2094 bool success = 2095#endif 2096 txFifo.push(txPacket); 2097 assert(success); 2098 2099 /* 2100 * this following section is not tqo spec, but 2101 * functionally shouldn't be any different. normally, 2102 * the chip will wait til the transmit has occurred 2103 * before writing back the descriptor because it has 2104 * to wait to see that it was successfully transmitted 2105 * to decide whether to set CMDSTS_OK or not. 2106 * however, in the simulator since it is always 2107 * successfully transmitted, and writing it exactly to 2108 * spec would complicate the code, we just do it here 2109 */ 2110 2111 txDescCache.cmdsts &= ~CMDSTS_OWN; 2112 txDescCache.cmdsts |= CMDSTS_OK; 2113 2114 DPRINTF(EthernetDesc, 2115 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2116 txDescCache.cmdsts, txDescCache.extsts); 2117 2118 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 2119 txDmaAddr &= 0x3fffffff; 2120 txDmaData = &(txDescCache.cmdsts); 2121 txDmaLen = sizeof(txDescCache.cmdsts) + 2122 sizeof(txDescCache.extsts); 2123 txDmaFree = dmaDescFree; 2124 2125 descDmaWrites++; 2126 descDmaWrBytes += txDmaLen; 2127 2128 transmit(); 2129 txPacket = 0; 2130 2131 if (!txEnable) { 2132 DPRINTF(EthernetSM, "halting TX state machine\n"); 2133 txState = txIdle; 2134 goto exit; 2135 } else 2136 txState = txAdvance; 2137 2138 if (doTxDmaWrite()) 2139 goto exit; 2140 } 2141 } else { 2142 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2143 if (!txFifo.full()) { 2144 txState = txFragRead; 2145 2146 /* 2147 * The number of bytes transferred is either whatever 2148 * is left in the descriptor (txDescCnt), or if there 2149 * is not enough room in the fifo, just whatever room 2150 * is left in the fifo 2151 */ 2152 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2153 2154 txDmaAddr = txFragPtr & 0x3fffffff; 2155 txDmaData = txPacketBufPtr; 2156 txDmaLen = txXferLen; 2157 txDmaFree = dmaDataFree; 2158 2159 if (doTxDmaRead()) 2160 goto exit; 2161 } else { 2162 txState = txFifoBlock; 2163 transmit(); 2164 2165 goto exit; 2166 } 2167 2168 } 2169 break; 2170 2171 case txFragRead: 2172 if (txDmaState != dmaIdle) 2173 goto exit; 2174 2175 txPacketBufPtr += txXferLen; 2176 txFragPtr += txXferLen; 2177 txDescCnt -= txXferLen; 2178 txFifo.reserve(txXferLen); 2179 2180 txState = txFifoBlock; 2181 break; 2182 2183 case txDescWrite: 2184 if (txDmaState != dmaIdle) 2185 goto exit; 2186 2187 if (txDescCache.cmdsts & CMDSTS_INTR) 2188 devIntrPost(ISR_TXDESC); 2189 2190 txState = txAdvance; 2191 break; 2192 2193 case txAdvance: 2194 if (txDescCache.link == 0) { 2195 devIntrPost(ISR_TXIDLE); 2196 txState = txIdle; 2197 goto exit; 2198 } else { 2199 txState = txDescRead; 2200 regs.txdp = txDescCache.link; 2201 CTDD = false; 2202 2203 txDmaAddr = txDescCache.link & 0x3fffffff; 2204 txDmaData = &txDescCache; 2205 txDmaLen = sizeof(ns_desc); 2206 txDmaFree = dmaDescFree; 2207 2208 if (doTxDmaRead()) 2209 goto exit; 2210 } 2211 break; 2212 2213 default: 2214 panic("invalid state"); 2215 } 2216 2217 DPRINTF(EthernetSM, "entering next txState=%s\n", 2218 NsTxStateStrings[txState]); 2219 2220 goto next; 2221 2222 exit: 2223 /** 2224 * @todo do we want to schedule a future kick? 2225 */ 2226 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2227 NsTxStateStrings[txState]); 2228} 2229 2230void 2231NSGigE::transferDone() 2232{ 2233 if (txFifo.empty()) { 2234 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2235 return; 2236 } 2237 2238 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2239 2240 if (txEvent.scheduled()) 2241 txEvent.reschedule(curTick + cycles(1)); 2242 else 2243 txEvent.schedule(curTick + cycles(1)); 2244} 2245 2246bool 2247NSGigE::rxFilter(const PacketPtr &packet) 2248{ 2249 EthPtr eth = packet; 2250 bool drop = true; 2251 string type; 2252 2253 const EthAddr &dst = eth->dst(); 2254 if (dst.unicast()) { 2255 // If we're accepting all unicast addresses 2256 if (acceptUnicast) 2257 drop = false; 2258 2259 // If we make a perfect match 2260 if (acceptPerfect && dst == rom.perfectMatch) 2261 drop = false; 2262 2263 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2264 drop = false; 2265 2266 } else if (dst.broadcast()) { 2267 // if we're accepting broadcasts 2268 if (acceptBroadcast) 2269 drop = false; 2270 2271 } else if (dst.multicast()) { 2272 // if we're accepting all multicasts 2273 if (acceptMulticast) 2274 drop = false; 2275 2276 } 2277 2278 if (drop) { 2279 DPRINTF(Ethernet, "rxFilter drop\n"); 2280 DDUMP(EthernetData, packet->data, packet->length); 2281 } 2282 2283 return drop; 2284} 2285 2286bool 2287NSGigE::recvPacket(PacketPtr packet) 2288{ 2289 rxBytes += packet->length; 2290 rxPackets++; 2291 2292 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2293 rxFifo.avail()); 2294 2295 if (!rxEnable) { 2296 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2297 debug_break(); 2298 interface->recvDone(); 2299 return true; 2300 } 2301 2302 if (rxFilterEnable && rxFilter(packet)) { 2303 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2304 interface->recvDone(); 2305 return true; 2306 } 2307 2308 if (rxFifo.avail() < packet->length) { 2309#if TRACING_ON 2310 IpPtr ip(packet); 2311 TcpPtr tcp(ip); 2312 if (ip) { 2313 DPRINTF(Ethernet, 2314 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2315 ip->id()); 2316 if (tcp) { 2317 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2318 } 2319 } 2320#endif 2321 droppedPackets++; 2322 devIntrPost(ISR_RXORN); 2323 return false; 2324 } 2325 2326 rxFifo.push(packet); 2327 interface->recvDone(); 2328 2329 rxKick(); 2330 return true; 2331} 2332 2333//===================================================================== 2334// 2335// 2336void 2337NSGigE::serialize(ostream &os) 2338{ 2339 // Serialize the PciDev base class 2340 PciDev::serialize(os); 2341 2342 /* 2343 * Finalize any DMA events now. 2344 */ 2345 if (rxDmaReadEvent.scheduled()) 2346 rxDmaReadCopy(); 2347 if (rxDmaWriteEvent.scheduled()) 2348 rxDmaWriteCopy(); 2349 if (txDmaReadEvent.scheduled()) 2350 txDmaReadCopy(); 2351 if (txDmaWriteEvent.scheduled()) 2352 txDmaWriteCopy(); 2353 2354 /* 2355 * Serialize the device registers 2356 */ 2357 SERIALIZE_SCALAR(regs.command); 2358 SERIALIZE_SCALAR(regs.config); 2359 SERIALIZE_SCALAR(regs.mear); 2360 SERIALIZE_SCALAR(regs.ptscr); 2361 SERIALIZE_SCALAR(regs.isr); 2362 SERIALIZE_SCALAR(regs.imr); 2363 SERIALIZE_SCALAR(regs.ier); 2364 SERIALIZE_SCALAR(regs.ihr); 2365 SERIALIZE_SCALAR(regs.txdp); 2366 SERIALIZE_SCALAR(regs.txdp_hi); 2367 SERIALIZE_SCALAR(regs.txcfg); 2368 SERIALIZE_SCALAR(regs.gpior); 2369 SERIALIZE_SCALAR(regs.rxdp); 2370 SERIALIZE_SCALAR(regs.rxdp_hi); 2371 SERIALIZE_SCALAR(regs.rxcfg); 2372 SERIALIZE_SCALAR(regs.pqcr); 2373 SERIALIZE_SCALAR(regs.wcsr); 2374 SERIALIZE_SCALAR(regs.pcr); 2375 SERIALIZE_SCALAR(regs.rfcr); 2376 SERIALIZE_SCALAR(regs.rfdr); 2377 SERIALIZE_SCALAR(regs.srr); 2378 SERIALIZE_SCALAR(regs.mibc); 2379 SERIALIZE_SCALAR(regs.vrcr); 2380 SERIALIZE_SCALAR(regs.vtcr); 2381 SERIALIZE_SCALAR(regs.vdr); 2382 SERIALIZE_SCALAR(regs.ccsr); 2383 SERIALIZE_SCALAR(regs.tbicr); 2384 SERIALIZE_SCALAR(regs.tbisr); 2385 SERIALIZE_SCALAR(regs.tanar); 2386 SERIALIZE_SCALAR(regs.tanlpar); 2387 SERIALIZE_SCALAR(regs.taner); 2388 SERIALIZE_SCALAR(regs.tesr); 2389 2390 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2391 2392 SERIALIZE_SCALAR(ioEnable); 2393 2394 /* 2395 * Serialize the data Fifos 2396 */ 2397 rxFifo.serialize("rxFifo", os); 2398 txFifo.serialize("txFifo", os); 2399 2400 /* 2401 * Serialize the various helper variables 2402 */ 2403 bool txPacketExists = txPacket; 2404 SERIALIZE_SCALAR(txPacketExists); 2405 if (txPacketExists) { 2406 txPacket->length = txPacketBufPtr - txPacket->data; 2407 txPacket->serialize("txPacket", os); 2408 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2409 SERIALIZE_SCALAR(txPktBufPtr); 2410 } 2411 2412 bool rxPacketExists = rxPacket; 2413 SERIALIZE_SCALAR(rxPacketExists); 2414 if (rxPacketExists) { 2415 rxPacket->serialize("rxPacket", os); 2416 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2417 SERIALIZE_SCALAR(rxPktBufPtr); 2418 } 2419 2420 SERIALIZE_SCALAR(txXferLen); 2421 SERIALIZE_SCALAR(rxXferLen); 2422 2423 /* 2424 * Serialize DescCaches 2425 */ 2426 SERIALIZE_SCALAR(txDescCache.link); 2427 SERIALIZE_SCALAR(txDescCache.bufptr); 2428 SERIALIZE_SCALAR(txDescCache.cmdsts); 2429 SERIALIZE_SCALAR(txDescCache.extsts); 2430 SERIALIZE_SCALAR(rxDescCache.link); 2431 SERIALIZE_SCALAR(rxDescCache.bufptr); 2432 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2433 SERIALIZE_SCALAR(rxDescCache.extsts); 2434 2435 /* 2436 * Serialize tx state machine 2437 */ 2438 int txState = this->txState; 2439 SERIALIZE_SCALAR(txState); 2440 SERIALIZE_SCALAR(txEnable); 2441 SERIALIZE_SCALAR(CTDD); 2442 SERIALIZE_SCALAR(txFragPtr); 2443 SERIALIZE_SCALAR(txDescCnt); 2444 int txDmaState = this->txDmaState; 2445 SERIALIZE_SCALAR(txDmaState); 2446 2447 /* 2448 * Serialize rx state machine 2449 */ 2450 int rxState = this->rxState; 2451 SERIALIZE_SCALAR(rxState); 2452 SERIALIZE_SCALAR(rxEnable); 2453 SERIALIZE_SCALAR(CRDD); 2454 SERIALIZE_SCALAR(rxPktBytes); 2455 SERIALIZE_SCALAR(rxFragPtr); 2456 SERIALIZE_SCALAR(rxDescCnt); 2457 int rxDmaState = this->rxDmaState; 2458 SERIALIZE_SCALAR(rxDmaState); 2459 2460 SERIALIZE_SCALAR(extstsEnable); 2461 2462 /* 2463 * If there's a pending transmit, store the time so we can 2464 * reschedule it later 2465 */ 2466 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2467 SERIALIZE_SCALAR(transmitTick); 2468 2469 /* 2470 * receive address filter settings 2471 */ 2472 SERIALIZE_SCALAR(rxFilterEnable); 2473 SERIALIZE_SCALAR(acceptBroadcast); 2474 SERIALIZE_SCALAR(acceptMulticast); 2475 SERIALIZE_SCALAR(acceptUnicast); 2476 SERIALIZE_SCALAR(acceptPerfect); 2477 SERIALIZE_SCALAR(acceptArp); 2478 2479 /* 2480 * Keep track of pending interrupt status. 2481 */ 2482 SERIALIZE_SCALAR(intrTick); 2483 SERIALIZE_SCALAR(cpuPendingIntr); 2484 Tick intrEventTick = 0; 2485 if (intrEvent) 2486 intrEventTick = intrEvent->when(); 2487 SERIALIZE_SCALAR(intrEventTick); 2488 2489} 2490 2491void 2492NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2493{ 2494 // Unserialize the PciDev base class 2495 PciDev::unserialize(cp, section); 2496 2497 UNSERIALIZE_SCALAR(regs.command); 2498 UNSERIALIZE_SCALAR(regs.config); 2499 UNSERIALIZE_SCALAR(regs.mear); 2500 UNSERIALIZE_SCALAR(regs.ptscr); 2501 UNSERIALIZE_SCALAR(regs.isr); 2502 UNSERIALIZE_SCALAR(regs.imr); 2503 UNSERIALIZE_SCALAR(regs.ier); 2504 UNSERIALIZE_SCALAR(regs.ihr); 2505 UNSERIALIZE_SCALAR(regs.txdp); 2506 UNSERIALIZE_SCALAR(regs.txdp_hi); 2507 UNSERIALIZE_SCALAR(regs.txcfg); 2508 UNSERIALIZE_SCALAR(regs.gpior); 2509 UNSERIALIZE_SCALAR(regs.rxdp); 2510 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2511 UNSERIALIZE_SCALAR(regs.rxcfg); 2512 UNSERIALIZE_SCALAR(regs.pqcr); 2513 UNSERIALIZE_SCALAR(regs.wcsr); 2514 UNSERIALIZE_SCALAR(regs.pcr); 2515 UNSERIALIZE_SCALAR(regs.rfcr); 2516 UNSERIALIZE_SCALAR(regs.rfdr); 2517 UNSERIALIZE_SCALAR(regs.srr); 2518 UNSERIALIZE_SCALAR(regs.mibc); 2519 UNSERIALIZE_SCALAR(regs.vrcr); 2520 UNSERIALIZE_SCALAR(regs.vtcr); 2521 UNSERIALIZE_SCALAR(regs.vdr); 2522 UNSERIALIZE_SCALAR(regs.ccsr); 2523 UNSERIALIZE_SCALAR(regs.tbicr); 2524 UNSERIALIZE_SCALAR(regs.tbisr); 2525 UNSERIALIZE_SCALAR(regs.tanar); 2526 UNSERIALIZE_SCALAR(regs.tanlpar); 2527 UNSERIALIZE_SCALAR(regs.taner); 2528 UNSERIALIZE_SCALAR(regs.tesr); 2529 2530 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2531 2532 UNSERIALIZE_SCALAR(ioEnable); 2533 2534 /* 2535 * unserialize the data fifos 2536 */ 2537 rxFifo.unserialize("rxFifo", cp, section); 2538 txFifo.unserialize("txFifo", cp, section); 2539 2540 /* 2541 * unserialize the various helper variables 2542 */ 2543 bool txPacketExists; 2544 UNSERIALIZE_SCALAR(txPacketExists); 2545 if (txPacketExists) { 2546 txPacket = new PacketData(16384); 2547 txPacket->unserialize("txPacket", cp, section); 2548 uint32_t txPktBufPtr; 2549 UNSERIALIZE_SCALAR(txPktBufPtr); 2550 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2551 } else 2552 txPacket = 0; 2553 2554 bool rxPacketExists; 2555 UNSERIALIZE_SCALAR(rxPacketExists); 2556 rxPacket = 0; 2557 if (rxPacketExists) { 2558 rxPacket = new PacketData(16384); 2559 rxPacket->unserialize("rxPacket", cp, section); 2560 uint32_t rxPktBufPtr; 2561 UNSERIALIZE_SCALAR(rxPktBufPtr); 2562 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2563 } else 2564 rxPacket = 0; 2565 2566 UNSERIALIZE_SCALAR(txXferLen); 2567 UNSERIALIZE_SCALAR(rxXferLen); 2568 2569 /* 2570 * Unserialize DescCaches 2571 */ 2572 UNSERIALIZE_SCALAR(txDescCache.link); 2573 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2574 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2575 UNSERIALIZE_SCALAR(txDescCache.extsts); 2576 UNSERIALIZE_SCALAR(rxDescCache.link); 2577 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2578 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2579 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2580 2581 /* 2582 * unserialize tx state machine 2583 */ 2584 int txState; 2585 UNSERIALIZE_SCALAR(txState); 2586 this->txState = (TxState) txState; 2587 UNSERIALIZE_SCALAR(txEnable); 2588 UNSERIALIZE_SCALAR(CTDD); 2589 UNSERIALIZE_SCALAR(txFragPtr); 2590 UNSERIALIZE_SCALAR(txDescCnt); 2591 int txDmaState; 2592 UNSERIALIZE_SCALAR(txDmaState); 2593 this->txDmaState = (DmaState) txDmaState; 2594 2595 /* 2596 * unserialize rx state machine 2597 */ 2598 int rxState; 2599 UNSERIALIZE_SCALAR(rxState); 2600 this->rxState = (RxState) rxState; 2601 UNSERIALIZE_SCALAR(rxEnable); 2602 UNSERIALIZE_SCALAR(CRDD); 2603 UNSERIALIZE_SCALAR(rxPktBytes); 2604 UNSERIALIZE_SCALAR(rxFragPtr); 2605 UNSERIALIZE_SCALAR(rxDescCnt); 2606 int rxDmaState; 2607 UNSERIALIZE_SCALAR(rxDmaState); 2608 this->rxDmaState = (DmaState) rxDmaState; 2609 2610 UNSERIALIZE_SCALAR(extstsEnable); 2611 2612 /* 2613 * If there's a pending transmit, reschedule it now 2614 */ 2615 Tick transmitTick; 2616 UNSERIALIZE_SCALAR(transmitTick); 2617 if (transmitTick) 2618 txEvent.schedule(curTick + transmitTick); 2619 2620 /* 2621 * unserialize receive address filter settings 2622 */ 2623 UNSERIALIZE_SCALAR(rxFilterEnable); 2624 UNSERIALIZE_SCALAR(acceptBroadcast); 2625 UNSERIALIZE_SCALAR(acceptMulticast); 2626 UNSERIALIZE_SCALAR(acceptUnicast); 2627 UNSERIALIZE_SCALAR(acceptPerfect); 2628 UNSERIALIZE_SCALAR(acceptArp); 2629 2630 /* 2631 * Keep track of pending interrupt status. 2632 */ 2633 UNSERIALIZE_SCALAR(intrTick); 2634 UNSERIALIZE_SCALAR(cpuPendingIntr); 2635 Tick intrEventTick; 2636 UNSERIALIZE_SCALAR(intrEventTick); 2637 if (intrEventTick) { 2638 intrEvent = new IntrEvent(this, true); 2639 intrEvent->schedule(intrEventTick); 2640 } 2641 2642 /* 2643 * re-add addrRanges to bus bridges 2644 */ 2645 if (pioInterface) { 2646 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 2647 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 2648 } 2649} 2650 2651Tick 2652NSGigE::cacheAccess(MemReqPtr &req) 2653{ 2654 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2655 req->paddr, req->paddr - addr); 2656 return curTick + pioLatency; 2657} 2658 2659BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2660 2661 SimObjectParam<EtherInt *> peer; 2662 SimObjectParam<NSGigE *> device; 2663 2664END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2665 2666BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2667 2668 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2669 INIT_PARAM(device, "Ethernet device of this interface") 2670 2671END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2672 2673CREATE_SIM_OBJECT(NSGigEInt) 2674{ 2675 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2676 2677 EtherInt *p = (EtherInt *)peer; 2678 if (p) { 2679 dev_int->setPeer(p); 2680 p->setPeer(dev_int); 2681 } 2682 2683 return dev_int; 2684} 2685 2686REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2687 2688 2689BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2690 2691 Param<Addr> addr; 2692 Param<Tick> cycle_time; 2693 Param<Tick> tx_delay; 2694 Param<Tick> rx_delay; 2695 Param<Tick> intr_delay; 2696 SimObjectParam<MemoryController *> mmu; 2697 SimObjectParam<PhysicalMemory *> physmem; 2698 Param<bool> rx_filter; 2699 Param<string> hardware_address; 2700 SimObjectParam<Bus*> io_bus; 2701 SimObjectParam<Bus*> payload_bus; 2702 SimObjectParam<HierParams *> hier; 2703 Param<Tick> pio_latency; 2704 Param<bool> dma_desc_free; 2705 Param<bool> dma_data_free; 2706 Param<Tick> dma_read_delay; 2707 Param<Tick> dma_write_delay; 2708 Param<Tick> dma_read_factor; 2709 Param<Tick> dma_write_factor; 2710 SimObjectParam<PciConfigAll *> configspace; 2711 SimObjectParam<PciConfigData *> configdata; 2712 SimObjectParam<Platform *> platform; 2713 Param<uint32_t> pci_bus; 2714 Param<uint32_t> pci_dev; 2715 Param<uint32_t> pci_func; 2716 Param<uint32_t> tx_fifo_size; 2717 Param<uint32_t> rx_fifo_size; 2718 Param<uint32_t> m5reg; 2719 Param<bool> dma_no_allocate; 2720 2721END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2722 2723BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2724 2725 INIT_PARAM(addr, "Device Address"), 2726 INIT_PARAM(cycle_time, "State machine processor frequency"), 2727 INIT_PARAM(tx_delay, "Transmit Delay"), 2728 INIT_PARAM(rx_delay, "Receive Delay"), 2729 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 2730 INIT_PARAM(mmu, "Memory Controller"), 2731 INIT_PARAM(physmem, "Physical Memory"), 2732 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2733 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2734 "00:99:00:00:00:01"), 2735 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), 2736 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2737 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2738 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2739 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2740 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2741 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2742 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2743 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2744 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2745 INIT_PARAM(configspace, "PCI Configspace"), 2746 INIT_PARAM(configdata, "PCI Config data"), 2747 INIT_PARAM(platform, "Platform"), 2748 INIT_PARAM(pci_bus, "PCI bus"), 2749 INIT_PARAM(pci_dev, "PCI device number"), 2750 INIT_PARAM(pci_func, "PCI function code"), 2751 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2752 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072), 2753 INIT_PARAM(m5reg, "m5 register"), 2754 INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true) 2755 2756END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2757 2758 2759CREATE_SIM_OBJECT(NSGigE) 2760{ 2761 NSGigE::Params *params = new NSGigE::Params; 2762 2763 params->name = getInstanceName(); 2764 params->mmu = mmu; 2765 params->configSpace = configspace; 2766 params->configData = configdata; 2767 params->plat = platform; 2768 params->busNum = pci_bus; 2769 params->deviceNum = pci_dev; 2770 params->functionNum = pci_func; 2771 2772 params->cycle_time = cycle_time; 2773 params->intr_delay = intr_delay; 2774 params->pmem = physmem; 2775 params->tx_delay = tx_delay; 2776 params->rx_delay = rx_delay; 2777 params->hier = hier; 2778 params->header_bus = io_bus; 2779 params->payload_bus = payload_bus; 2780 params->pio_latency = pio_latency; 2781 params->dma_desc_free = dma_desc_free; 2782 params->dma_data_free = dma_data_free; 2783 params->dma_read_delay = dma_read_delay; 2784 params->dma_write_delay = dma_write_delay; 2785 params->dma_read_factor = dma_read_factor; 2786 params->dma_write_factor = dma_write_factor; 2787 params->rx_filter = rx_filter; 2788 params->eaddr = hardware_address; 2789 params->tx_fifo_size = tx_fifo_size; 2790 params->rx_fifo_size = rx_fifo_size; 2791 params->m5reg = m5reg; 2792 params->dma_no_allocate = dma_no_allocate; 2793 return new NSGigE(params); 2794} 2795 2796REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2797