ns_gige.cc revision 837
12292SN/A/* 22292SN/A * Copyright (c) 2003 The Regents of The University of Michigan 32292SN/A * All rights reserved. 42292SN/A * 52292SN/A * Redistribution and use in source and binary forms, with or without 62292SN/A * modification, are permitted provided that the following conditions are 72292SN/A * met: redistributions of source code must retain the above copyright 82292SN/A * notice, this list of conditions and the following disclaimer; 92292SN/A * redistributions in binary form must reproduce the above copyright 102292SN/A * notice, this list of conditions and the following disclaimer in the 112292SN/A * documentation and/or other materials provided with the distribution; 122292SN/A * neither the name of the copyright holders nor the names of its 132292SN/A * 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. 272689Sktlim@umich.edu */ 282689Sktlim@umich.edu 292689Sktlim@umich.edu/* @file 302292SN/A * Device module for modelling the National Semiconductor 312292SN/A * DP83820 ethernet controller. Does not support priority queueing 323326Sktlim@umich.edu */ 332733Sktlim@umich.edu#include <cstdio> 342733Sktlim@umich.edu#include <deque> 352907Sktlim@umich.edu#include <string> 362292SN/A 372292SN/A#include "base/inet.hh" 382722Sktlim@umich.edu#include "cpu/exec_context.hh" 392669Sktlim@umich.edu#include "cpu/intr_control.hh" 402292SN/A#include "dev/dma.hh" 412790Sktlim@umich.edu#include "dev/ns_gige.hh" 422790Sktlim@umich.edu#include "dev/etherlink.hh" 432790Sktlim@umich.edu#include "mem/functional_mem/memory_control.hh" 442790Sktlim@umich.edu#include "mem/functional_mem/physical_memory.hh" 452669Sktlim@umich.edu#include "sim/builder.hh" 462678Sktlim@umich.edu#include "sim/host.hh" 472678Sktlim@umich.edu#include "sim/sim_stats.hh" 482678Sktlim@umich.edu#include "targetarch/vtophys.hh" 492292SN/A 502678Sktlim@umich.eduusing namespace std; 512292SN/A 522292SN/A/////////////////////////////////////////////////////////////////////// 532669Sktlim@umich.edu// 542292SN/A// EtherDev PCI Device 552678Sktlim@umich.edu// 562292SN/AEtherDev::EtherDev(const string &_name, DmaEngine *de, bool use_interface, 572678Sktlim@umich.edu IntrControl *i, MemoryController *mmu, PhysicalMemory *pmem, 582678Sktlim@umich.edu PCIConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus, 592678Sktlim@umich.edu uint32_t dev, uint32_t func, bool rx_filter, 604319Sktlim@umich.edu const int eaddr[6], Tick tx_delay, Tick rx_delay, Addr addr, 614319Sktlim@umich.edu Addr mask) 624319Sktlim@umich.edu : PciDev(_name, mmu, cf, cd, bus, dev, func), tsunami(t), 634319Sktlim@umich.edu addr(addr), mask(mask), txPacketLen(0), 644319Sktlim@umich.edu txPacketBufPtr(NULL), rxPacketBufPtr(NULL), rxDescBufPtr(NULL), 652678Sktlim@umich.edu fragLen(0), rxCopied(0), txState(txIdle), CTDD(false), txFifoCnt(0), 662678Sktlim@umich.edu txFifoAvail(MAX_TX_FIFO_SIZE), txHalt(false), txPacketFlag(false), 672292SN/A txFragPtr(0), txDescCnt(0), rxState(rxIdle), CRDD(false), 682678Sktlim@umich.edu rxPktBytes(0), rxFifoCnt(0), rxHalt(false), rxPacketFlag(false), 692678Sktlim@umich.edu rxFragPtr(0), rxDescCnt(0), extstsEnable(false), maxTxBurst(0), 705336Shines@cs.fsu.edu maxRxBurst(0), physmem(pmem), 712678Sktlim@umich.edu rxDescDoneCB(this), rxDoneCB(this), txDescDoneCB(this), txDoneCB(this), 724873Sstever@eecs.umich.edu dma(de), readRequest(use_interface), writeRequest(use_interface), 732678Sktlim@umich.edu readDescRequest(use_interface), writeDescRequest(use_interface), 742292SN/A interface(NULL), intctrl(i), txDelay(tx_delay), rxDelay(rx_delay), 752678Sktlim@umich.edu txEvent(this), cpuPendingIntr(false), rxFilterEnable(rx_filter), 762678Sktlim@umich.edu acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), 772678Sktlim@umich.edu acceptPerfect(false), acceptArp(false) 782678Sktlim@umich.edu{ 792678Sktlim@umich.edu tsunami->ethernet = this; 802678Sktlim@umich.edu 812678Sktlim@umich.edu memset(®s, 0, sizeof(regs)); 822698Sktlim@umich.edu regsReset(); 832344SN/A regs.perfectMatch[0] = eaddr[0]; 842678Sktlim@umich.edu regs.perfectMatch[1] = eaddr[1]; 852678Sktlim@umich.edu regs.perfectMatch[2] = eaddr[2]; 864986Ssaidi@eecs.umich.edu regs.perfectMatch[3] = eaddr[3]; 874986Ssaidi@eecs.umich.edu regs.perfectMatch[4] = eaddr[4]; 882678Sktlim@umich.edu regs.perfectMatch[5] = eaddr[5]; 892820Sktlim@umich.edu 902678Sktlim@umich.edu} 912678Sktlim@umich.edu 922678Sktlim@umich.eduEtherDev::~EtherDev() 932678Sktlim@umich.edu{} 942678Sktlim@umich.edu 952678Sktlim@umich.eduvoid 962678Sktlim@umich.eduEtherDev::regStats() 972678Sktlim@umich.edu{ 982344SN/A txBytes 992307SN/A .name(name() + ".txBytes") 1002678Sktlim@umich.edu .desc("Bytes Transmitted") 1014032Sktlim@umich.edu .prereq(txBytes) 1022678Sktlim@umich.edu ; 1032292SN/A 1042292SN/A rxBytes 1052292SN/A .name(name() + ".rxBytes") 1062292SN/A .desc("Bytes Received") 1072678Sktlim@umich.edu .prereq(rxBytes) 1082678Sktlim@umich.edu ; 1092292SN/A 1102292SN/A txPackets 1112292SN/A .name(name() + ".txPackets") 1122292SN/A .desc("Number of Packets Transmitted") 1132292SN/A .prereq(txBytes) 1142292SN/A ; 1154329Sktlim@umich.edu 1164329Sktlim@umich.edu rxPackets 1172292SN/A .name(name() + ".rxPackets") 1184329Sktlim@umich.edu .desc("Number of Packets Received") 1194329Sktlim@umich.edu .prereq(rxBytes) 1204329Sktlim@umich.edu ; 1214329Sktlim@umich.edu 1222292SN/A txBandwidth 1232307SN/A .name(name() + ".txBandwidth") 1242307SN/A .desc("Transmit Bandwidth (bits/s)") 1252907Sktlim@umich.edu .precision(0) 1262907Sktlim@umich.edu .prereq(txBytes) 1272292SN/A ; 1282292SN/A 1292329SN/A rxBandwidth 1302329SN/A .name(name() + ".rxBandwidth") 1312329SN/A .desc("Receive Bandwidth (bits/s)") 1322292SN/A .precision(0) 1332292SN/A .prereq(rxBytes) 1342292SN/A ; 1352292SN/A 1362292SN/A txPacketRate 1372292SN/A .name(name() + ".txPPS") 1382292SN/A .desc("Packet Tranmission Rate (packets/s)") 1392292SN/A .precision(0) 1402292SN/A .prereq(txBytes) 1412292SN/A ; 1422292SN/A 1433492Sktlim@umich.edu rxPacketRate 1442329SN/A .name(name() + ".rxPPS") 1452292SN/A .desc("Packet Reception Rate (packets/s)") 1462292SN/A .precision(0) 1472292SN/A .prereq(rxBytes) 1482292SN/A ; 1492292SN/A 1502292SN/A txBandwidth = txBytes * Statistics::constant(8) / simSeconds; 1512292SN/A rxBandwidth = rxBytes * Statistics::constant(8) / simSeconds; 1522292SN/A txPacketRate = txPackets / simSeconds; 1532292SN/A rxPacketRate = rxPackets / simSeconds; 1542292SN/A} 1552292SN/A 1562292SN/Avoid 1572292SN/AEtherDev::ReadConfig(int offset, int size, uint8_t *data) 1582292SN/A{ 1592292SN/A if (offset < PCI_DEVICE_SPECIFIC) 1602292SN/A PciDev::ReadConfig(offset, size, data); 1612292SN/A else { 1622727Sktlim@umich.edu panic("need to do this\n"); 1632727Sktlim@umich.edu } 1642727Sktlim@umich.edu} 1652727Sktlim@umich.edu 1662727Sktlim@umich.eduvoid 1672727Sktlim@umich.eduEtherDev::WriteConfig(int offset, int size, uint32_t data) 1682727Sktlim@umich.edu{ 1692727Sktlim@umich.edu if (offset < PCI_DEVICE_SPECIFIC) 1702727Sktlim@umich.edu PciDev::WriteConfig(offset, size, data); 1712727Sktlim@umich.edu else 1722727Sktlim@umich.edu panic("Need to do that\n"); 1732727Sktlim@umich.edu} 1742727Sktlim@umich.edu 1752727Sktlim@umich.eduFault 1762727Sktlim@umich.eduEtherDev::read(MemReqPtr req, uint8_t *data) 1772727Sktlim@umich.edu{ 1782727Sktlim@umich.edu DPRINTF(Ethernet, "read va=%#x size=%d\n", req->vaddr, req->size); 1792727Sktlim@umich.edu 1802361SN/A Addr daddr = req->paddr - addr; 1812361SN/A 1822361SN/A if (daddr > LAST) 1832361SN/A panic("Accessing reserved register"); 1842727Sktlim@umich.edu 1852727Sktlim@umich.edu switch (req->size) { 1862727Sktlim@umich.edu case sizeof(uint32_t): 1872727Sktlim@umich.edu { 1882727Sktlim@umich.edu uint32_t ® = *(uint32_t *)data; 1892727Sktlim@umich.edu 1902727Sktlim@umich.edu switch (daddr) { 1912727Sktlim@umich.edu case CR: 1922727Sktlim@umich.edu reg = regs.command; 1932727Sktlim@umich.edu reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 1942727Sktlim@umich.edu break; 1952727Sktlim@umich.edu 1962727Sktlim@umich.edu case CFG: 1972727Sktlim@umich.edu reg = regs.config; 1982727Sktlim@umich.edu break; 1992727Sktlim@umich.edu 2002727Sktlim@umich.edu case MEAR: 2012727Sktlim@umich.edu reg = regs.mear; 2022727Sktlim@umich.edu break; 2032727Sktlim@umich.edu 2042727Sktlim@umich.edu case PTSCR: 2052727Sktlim@umich.edu reg = regs.ptscr; 2062727Sktlim@umich.edu break; 2074329Sktlim@umich.edu 2084329Sktlim@umich.edu case ISR: 2094329Sktlim@umich.edu reg = regs.isr; 2104329Sktlim@umich.edu regs.isr = 0; 2114329Sktlim@umich.edu break; 2124329Sktlim@umich.edu 2134329Sktlim@umich.edu case IMR: 2144329Sktlim@umich.edu reg = regs.imr; 2154329Sktlim@umich.edu break; 2164329Sktlim@umich.edu 2174329Sktlim@umich.edu case IER: 2184329Sktlim@umich.edu reg = regs.ier; 2194329Sktlim@umich.edu break; 2202292SN/A 2212292SN/A case IHR: 2222292SN/A reg = regs.ihr; 2232292SN/A break; 2242292SN/A 2252292SN/A case TXDP: 2262292SN/A reg = regs.txdp; 2272292SN/A break; 2282292SN/A 2292292SN/A case TXDP_HI: 2302292SN/A reg = regs.txdp_hi; 2312292SN/A break; 2322292SN/A 2332292SN/A case TXCFG: 2342307SN/A reg = regs.txcfg; 2352307SN/A break; 2362307SN/A 2372367SN/A case GPIOR: 2382367SN/A reg = regs.gpior; 2392307SN/A break; 2402367SN/A 2412307SN/A case RXDP: 2422329SN/A reg = regs.rxdp; 2432307SN/A break; 2442307SN/A 2452307SN/A case RXDP_HI: 2462307SN/A reg = regs.rxdp_hi; 2472307SN/A break; 2482307SN/A 2492307SN/A case RXCFG: 2502307SN/A reg = regs.rxcfg; 2512307SN/A break; 2522307SN/A 2532307SN/A case PQCR: 2542307SN/A reg = regs.pqcr; 2552307SN/A break; 2562307SN/A 2572307SN/A case WCSR: 2582329SN/A reg = regs.wcsr; 2592307SN/A break; 2602307SN/A 2612307SN/A case PCR: 2622307SN/A reg = regs.pcr; 2632307SN/A break; 2642307SN/A 2652307SN/A case RFCR: 2662307SN/A reg = regs.rfcr; 2672307SN/A break; 2682307SN/A 2692292SN/A case RFDR: 2702292SN/A 2712329SN/A switch (regs.rfcr & RFCR_RFADDR) { 2722329SN/A case 0x000: 2732292SN/A reg = regs.perfectMatch[1] << 8; 2742329SN/A reg += regs.perfectMatch[0]; 2752329SN/A break; 2762292SN/A case 0x002: 2772292SN/A reg = regs.perfectMatch[3] << 8; 2782292SN/A reg += regs.perfectMatch[2]; 2792292SN/A break; 2802292SN/A case 0x004: 2812329SN/A reg = regs.perfectMatch[5] << 8; 2822292SN/A reg += regs.perfectMatch[4]; 2832292SN/A break; 2842292SN/A default: 2852292SN/A panic("reading from RFDR for something for other than PMATCH!\n"); 2862292SN/A //didn't implement other RFDR functionality b/c driver didn't use 2872292SN/A } 2882292SN/A break; 2892292SN/A 2902329SN/A case SRR: 2912329SN/A reg = regs.srr; 2922329SN/A break; 2932292SN/A 2942292SN/A case MIBC: 2952292SN/A reg = regs.mibc; 2962292SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 2972292SN/A break; 2982329SN/A 2992292SN/A case VRCR: 3002292SN/A reg = regs.vrcr; 3012292SN/A break; 3022292SN/A 3032292SN/A case VTCR: 3042292SN/A reg = regs.vtcr; 3052292SN/A break; 3062292SN/A 3072292SN/A case VDR: 3082292SN/A reg = regs.vdr; 3092292SN/A break; 3102292SN/A 3112292SN/A case CCSR: 3122292SN/A reg = regs.ccsr; 3132292SN/A break; 3142292SN/A 3152292SN/A case TBICR: 3162292SN/A reg = regs.tbicr; 3172292SN/A break; 3182292SN/A 3192292SN/A case TBISR: 3202292SN/A reg = regs.tbisr; 3212292SN/A break; 3222292SN/A 3232329SN/A case TANAR: 3242329SN/A reg = regs.tanar; 3252292SN/A break; 3262292SN/A 3272292SN/A case TANLPAR: 3282292SN/A reg = regs.tanlpar; 3292292SN/A break; 3302292SN/A 3312292SN/A case TANER: 3322292SN/A reg = regs.taner; 3332292SN/A break; 3342292SN/A 3352292SN/A case TESR: 3362292SN/A reg = regs.tesr; 3372292SN/A break; 3382292SN/A 3392292SN/A default: 3402292SN/A panic("reading unimplemented register: addr = %#x", daddr); 3412292SN/A } 3422292SN/A 3432292SN/A DPRINTF(Ethernet, "read from %#x: data=%d data=%#x\n", daddr, reg, reg); 3442292SN/A } 3452292SN/A break; 3462292SN/A 3472292SN/A default: 3482292SN/A panic("accessing register with invalid size: addr=%#x, size=%d", 3492292SN/A daddr, req->size); 3502292SN/A } 3512292SN/A 3522292SN/A return No_Fault; 3532292SN/A} 3542292SN/A 3552292SN/AFault 3562292SN/AEtherDev::write(MemReqPtr req, const uint8_t *data) 3572292SN/A{ 3582292SN/A DPRINTF(Ethernet, "write va=%#x size=%d\n", req->vaddr, req->size); 3592292SN/A 3602292SN/A Addr daddr = req->paddr - addr; 3612292SN/A 3622292SN/A if (daddr > LAST && daddr <= RESERVED) 3632292SN/A panic("Accessing reserved register"); 3642292SN/A 3652292SN/A if (daddr > RESERVED) 3662292SN/A panic("higher memory accesses not implemented!\n"); 3672292SN/A 3682292SN/A if (req->size == sizeof(uint32_t)) { 3692292SN/A uint32_t reg = *(uint32_t *)data; 3702292SN/A DPRINTF(Ethernet, "write data=%d data=%#x\n", reg, reg); 3712292SN/A 3722292SN/A switch (daddr) { 3732292SN/A case CR: 3742292SN/A regs.command = reg; 3752292SN/A if ((reg & (CR_TXE | CR_TXD)) == (CR_TXE | CR_TXD)) { 3762292SN/A txHalt = true; 3772292SN/A } else if (reg & CR_TXE) { 3782292SN/A if (txState == txIdle) 3792292SN/A txKick(); 3802292SN/A } else if (reg & CR_TXD) { 3812292SN/A txHalt = true; 3822292SN/A } 3832292SN/A 3842292SN/A if ((reg & (CR_RXE | CR_RXD)) == (CR_RXE | CR_RXD)) { 3852292SN/A rxHalt = true; 3862292SN/A } else if (reg & CR_RXE) { 3872292SN/A if (rxState == rxIdle) { 3882292SN/A rxKick(); 3892292SN/A } 3902292SN/A } else if (reg & CR_RXD) { 3912292SN/A rxHalt = true; 3922292SN/A } 3932292SN/A 3942292SN/A if (reg & CR_TXR) 3952292SN/A txReset(); 3962292SN/A 3972292SN/A if (reg & CR_RXR) 3982292SN/A rxReset(); 3992292SN/A 4002292SN/A if (reg & CR_SWI) 4012292SN/A devIntrPost(ISR_SWI); 4022292SN/A 4032292SN/A if (reg & CR_RST) { 4042292SN/A txReset(); 4052292SN/A rxReset(); 4062292SN/A regsReset(); 4072292SN/A } 4082292SN/A break; 4092292SN/A 4102292SN/A case CFG: 4112292SN/A regs.config = reg; 4122292SN/A if (reg & CFG_LNKSTS || reg & CFG_SPDSTS || reg & CFG_DUPSTS 4132292SN/A || reg & CFG_RESERVED || reg & CFG_T64ADDR 4144032Sktlim@umich.edu || reg & CFG_PCI64_DET) 4152292SN/A panic("writing to read-only or reserved CFG bits!\n"); 4162292SN/A 4172292SN/A#if 0 4182292SN/A if (reg & CFG_TBI_EN) ; 4192292SN/A if (reg & CFG_MODE_1000) ; 4202292SN/A#endif 4214032Sktlim@umich.edu 4224032Sktlim@umich.edu if (reg & CFG_AUTO_1000) 4232669Sktlim@umich.edu panic("CFG_AUTO_1000 not implemented!\n"); 4242292SN/A 4252292SN/A#if 0 4262292SN/A if (reg & CFG_PINT_DUPSTS || reg & CFG_PINT_LNKSTS || reg & CFG_PINT_SPDSTS) ; 4272292SN/A if (reg & CFG_TMRTEST) ; 4282329SN/A if (reg & CFG_MRM_DIS) ; 4292329SN/A if (reg & CFG_MWI_DIS) ; 4302367SN/A#endif 4312367SN/A 4324032Sktlim@umich.edu if (reg & CFG_T64ADDR) 4333731Sktlim@umich.edu panic("CFG_T64ADDR is read only register!\n"); 4342367SN/A 4352367SN/A if (reg & CFG_PCI64_DET) 4362292SN/A panic("CFG_PCI64_DET is read only register!\n"); 4372292SN/A 4384032Sktlim@umich.edu#if 0 4394032Sktlim@umich.edu if (reg & CFG_DATA64_EN) ; 4404032Sktlim@umich.edu if (reg & CFG_M64ADDR) ; 4414032Sktlim@umich.edu if (reg & CFG_PHY_RST) ; 4424032Sktlim@umich.edu if (reg & CFG_PHY_DIS) ; 4434032Sktlim@umich.edu#endif 4444032Sktlim@umich.edu 4454032Sktlim@umich.edu if (reg & CFG_EXTSTS_EN) 4464032Sktlim@umich.edu extstsEnable = true; 4474032Sktlim@umich.edu else 4484032Sktlim@umich.edu extstsEnable = false; 4494032Sktlim@umich.edu 4504032Sktlim@umich.edu#if 0 4514032Sktlim@umich.edu if (reg & CFG_REQALG) ; 4524032Sktlim@umich.edu if (reg & CFG_SB) ; 4534032Sktlim@umich.edu if (reg & CFG_POW) ; 4544032Sktlim@umich.edu if (reg & CFG_EXD) ; 4554032Sktlim@umich.edu if (reg & CFG_PESEL) ; 4564032Sktlim@umich.edu if (reg & CFG_BROM_DIS) ; 4574032Sktlim@umich.edu if (reg & CFG_EXT_125) ; 4584032Sktlim@umich.edu if (reg & CFG_BEM) ; 4594032Sktlim@umich.edu#endif 4604032Sktlim@umich.edu break; 4614032Sktlim@umich.edu 4624032Sktlim@umich.edu case MEAR: 4634032Sktlim@umich.edu regs.mear = reg; 4644032Sktlim@umich.edu /* since phy is completely faked, MEAR_MD* don't matter 4654032Sktlim@umich.edu and since the driver never uses MEAR_EE*, they don't matter */ 4664032Sktlim@umich.edu#if 0 4674032Sktlim@umich.edu if (reg & MEAR_EEDI) ; 4684032Sktlim@umich.edu if (reg & MEAR_EEDO) ; //this one is read only 4694032Sktlim@umich.edu if (reg & MEAR_EECLK) ; 4702292SN/A if (reg & MEAR_EESEL) ; 4712292SN/A if (reg & MEAR_MDIO) ; 4722292SN/A if (reg & MEAR_MDDIR) ; 4732292SN/A if (reg & MEAR_MDC) ; 4742292SN/A#endif 4752292SN/A break; 4762292SN/A 4772292SN/A case PTSCR: 4782292SN/A regs.ptscr = reg; 4792292SN/A /* these control BISTs for various parts of chip - we don't care or do */ 4802292SN/A break; 4812292SN/A 4822292SN/A case ISR: /* writing to the ISR has no effect */ 4832292SN/A panic("ISR is a read only register!\n"); 4842292SN/A 4852292SN/A case IMR: 4862292SN/A regs.imr = reg; 4872292SN/A devIntrChangeMask(); 4884032Sktlim@umich.edu break; 4894032Sktlim@umich.edu 4902292SN/A case IER: 4912292SN/A regs.ier = reg; 4922292SN/A break; 4932292SN/A 4942292SN/A case IHR: 4952292SN/A regs.ihr = reg; 4962329SN/A /* not going to implement real interrupt holdoff */ 4972292SN/A break; 4982292SN/A 4992292SN/A case TXDP: 5002292SN/A regs.txdp = (reg & 0xFFFFFFFC); 5012292SN/A assert(txState == txIdle); 5022292SN/A CTDD = false; 5032292SN/A break; 5042292SN/A 5052336SN/A case TXDP_HI: 5062336SN/A regs.txdp_hi = reg; 5072336SN/A break; 5082329SN/A 5092292SN/A case TXCFG: 5102329SN/A regs.txcfg = reg; 5112292SN/A#if 0 5122292SN/A if (reg & TXCFG_CSI) ; 5134032Sktlim@umich.edu if (reg & TXCFG_HBI) ; 5144032Sktlim@umich.edu if (reg & TXCFG_MLB) ; 5154032Sktlim@umich.edu if (reg & TXCFG_ATP) ; 5164032Sktlim@umich.edu if (reg & TXCFG_ECRETRY) ; /* this could easily be implemented, but 5174032Sktlim@umich.edu considering the network is just a fake 5182292SN/A pipe, wouldn't make sense to do this */ 5194032Sktlim@umich.edu 5204032Sktlim@umich.edu if (reg & TXCFG_BRST_DIS) ; 5214032Sktlim@umich.edu#endif 5222329SN/A 5234032Sktlim@umich.edu#if 0 /* current 2.6 driver doesn't use these. if we upgrade, may need these */ 5244032Sktlim@umich.edu if (reg & TXCFG_MXDMA1024) 5254032Sktlim@umich.edu maxTxBurst = 1024; 5264032Sktlim@umich.edu 5274032Sktlim@umich.edu if (reg & TXCFG_MXDMA8) 5284032Sktlim@umich.edu maxTxBurst = 8; 5294032Sktlim@umich.edu 5304032Sktlim@umich.edu if (reg & TXCFG_MXDMA16) 5314032Sktlim@umich.edu maxTxBurst = 16; 5324032Sktlim@umich.edu 5334032Sktlim@umich.edu if (reg & TXCFG_MXDMA32) 5344032Sktlim@umich.edu maxTxBurst = 32; 5352292SN/A 5362292SN/A if (reg & TXCFG_MXDMA64) 5374032Sktlim@umich.edu maxTxBurst = 64; 5384032Sktlim@umich.edu 5394032Sktlim@umich.edu if (reg & TXCFG_MXDMA128) 5402292SN/A maxTxBurst = 128; 5412292SN/A 5424032Sktlim@umich.edu if (reg & TXCFG_MXDMA256) 5432292SN/A maxTxBurst = 256; 5442292SN/A#endif 5452292SN/A 5462292SN/A if (reg & TXCFG_MXDMA512) 5472292SN/A maxTxBurst = 512; 5482292SN/A 5492292SN/A break; 5502292SN/A 5512292SN/A case GPIOR: 5522292SN/A regs.gpior = reg; 5532292SN/A /* these just control general purpose i/o pins, don't matter */ 5542292SN/A break; 5552292SN/A 5562292SN/A case RXCFG: 5572292SN/A regs.rxcfg = reg; 5582292SN/A#if 0 5592292SN/A if (reg & RXCFG_AEP) ; 5602292SN/A if (reg & RXCFG_ARP) ; 5612292SN/A if (reg & RXCFG_STRIPCRC) ; 5622292SN/A if (reg & RXCFG_RX_RD) ; 5632292SN/A if (reg & RXCFG_ALP) ; 5642292SN/A if (reg & RXCFG_AIRL) ; 5652292SN/A#endif 5662292SN/A 5672292SN/A if (reg & RXCFG_MXDMA512) 5682292SN/A maxRxBurst = 512; 5692292SN/A 5702292SN/A#if 0 5712292SN/A if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 5722292SN/A#endif 5732292SN/A break; 5742292SN/A 5752292SN/A case PQCR: 5762292SN/A /* there is no priority queueing used in the linux 2.6 driver */ 5772292SN/A regs.pqcr = reg; 5782292SN/A break; 5792292SN/A 5802292SN/A case WCSR: 5812292SN/A /* not going to implement wake on LAN */ 5822292SN/A regs.wcsr = reg; 5832292SN/A break; 5842292SN/A 5852329SN/A case PCR: 5862329SN/A /* not going to implement pause control */ 5872292SN/A regs.pcr = reg; 5882292SN/A break; 5892292SN/A 5902292SN/A case RFCR: 5912292SN/A regs.rfcr = reg; 5922292SN/A rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 5932292SN/A 5942292SN/A acceptBroadcast = (reg & RFCR_AAB) ? true : false; 5952292SN/A 5962292SN/A acceptMulticast = (reg & RFCR_AAM) ? true : false; 5972292SN/A 5982292SN/A acceptUnicast = (reg & RFCR_AAU) ? true : false; 5992292SN/A 6002292SN/A acceptPerfect = (reg & RFCR_APM) ? true : false; 6012292SN/A 6022292SN/A acceptArp = (reg & RFCR_AARP) ? true : false; 6032292SN/A 6042292SN/A if (reg & RFCR_APAT) 6052292SN/A panic("RFCR_APAT not implemented!\n"); 6062292SN/A 6072292SN/A if (reg & RFCR_MHEN || reg & RFCR_UHEN) 6082292SN/A panic("hash filtering not implemented!\n"); 6092292SN/A 6102292SN/A if (reg & RFCR_ULM) 6112292SN/A panic("RFCR_ULM not implemented!\n"); 6122292SN/A 6132292SN/A break; 6142292SN/A 6152907Sktlim@umich.edu case RFDR: 6162678Sktlim@umich.edu panic("the driver never writes to RFDR, something is wrong!\n"); 6172678Sktlim@umich.edu 6182678Sktlim@umich.edu case BRAR: 6192678Sktlim@umich.edu panic("the driver never uses BRAR, something is wrong!\n"); 6202678Sktlim@umich.edu 6212329SN/A case BRDR: 6222329SN/A panic("the driver never uses BRDR, something is wrong!\n"); 6232292SN/A 6242292SN/A case SRR: 6252292SN/A panic("SRR is read only register!\n"); 6262292SN/A 6272292SN/A case MIBC: 6282292SN/A panic("the driver never uses MIBC, something is wrong!\n"); 6292292SN/A 6302678Sktlim@umich.edu case VRCR: 6312292SN/A regs.vrcr = reg; 6322292SN/A break; 6332292SN/A 6342292SN/A case VTCR: 6352292SN/A regs.vtcr = reg; 6362292SN/A break; 6372292SN/A 6382292SN/A case VDR: 6392292SN/A panic("the driver never uses VDR, something is wrong!\n"); 6402292SN/A break; 6412292SN/A 6422669Sktlim@umich.edu case CCSR: 6432669Sktlim@umich.edu /* not going to implement clockrun stuff */ 6442669Sktlim@umich.edu regs.ccsr = reg; 6452292SN/A break; 6462292SN/A 6472669Sktlim@umich.edu case TBICR: 6482669Sktlim@umich.edu regs.tbicr = reg; 6493772Sgblack@eecs.umich.edu if (reg & TBICR_MR_LOOPBACK) 6504326Sgblack@eecs.umich.edu panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 6512669Sktlim@umich.edu 6524878Sstever@eecs.umich.edu if (reg & TBICR_MR_AN_ENABLE) { 6534878Sstever@eecs.umich.edu regs.tanlpar = regs.tanar; 6544909Sstever@eecs.umich.edu regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 6554350Sgblack@eecs.umich.edu } 6564022Sstever@eecs.umich.edu 6572669Sktlim@umich.edu#if 0 6582292SN/A if (reg & TBICR_MR_RESTART_AN) ; 6592678Sktlim@umich.edu#endif 6602678Sktlim@umich.edu 6612678Sktlim@umich.edu break; 6622678Sktlim@umich.edu 6632678Sktlim@umich.edu case TBISR: 6642678Sktlim@umich.edu panic("TBISR is read only register!\n"); 6652292SN/A 6662292SN/A case TANAR: 6673221Sktlim@umich.edu regs.tanar = reg; 6683797Sgblack@eecs.umich.edu if (reg & TANAR_PS2) 6693221Sktlim@umich.edu panic("this isn't used in driver, something wrong!\n"); 6702292SN/A 6712693Sktlim@umich.edu if (reg & TANAR_PS1) 6724350Sgblack@eecs.umich.edu panic("this isn't used in driver, something wrong!\n"); 6733326Sktlim@umich.edu break; 6743326Sktlim@umich.edu 6753326Sktlim@umich.edu case TANLPAR: 6763326Sktlim@umich.edu panic("this should only be written to by the fake phy!\n"); 6773326Sktlim@umich.edu 6783326Sktlim@umich.edu case TANER: 6793326Sktlim@umich.edu panic("TANER is read only register!\n"); 6803326Sktlim@umich.edu 6813326Sktlim@umich.edu case TESR: 6823326Sktlim@umich.edu regs.tesr = reg; 6833326Sktlim@umich.edu break; 6843326Sktlim@umich.edu 6853326Sktlim@umich.edu default: 6863326Sktlim@umich.edu panic("thought i covered all the register, what is this? addr=%#x", 6873326Sktlim@umich.edu daddr); 6883326Sktlim@umich.edu } 6893326Sktlim@umich.edu } else 6902693Sktlim@umich.edu panic("Invalid Request Size"); 6912693Sktlim@umich.edu 6922693Sktlim@umich.edu return No_Fault; 6932693Sktlim@umich.edu} 6942693Sktlim@umich.edu 6952693Sktlim@umich.eduvoid 6962669Sktlim@umich.eduEtherDev::devIntrPost(uint32_t interrupts) 6972669Sktlim@umich.edu{ 6984032Sktlim@umich.eduDPRINTF(Ethernet, "interrupt posted intr=%x isr=%x imr=%x\n", 6993221Sktlim@umich.edu interrupts, regs.isr, regs.imr); 7003221Sktlim@umich.edu 7012678Sktlim@umich.eduif (interrupts & ISR_RESERVE) 7022727Sktlim@umich.edu panic("Cannot set a reserved interrupt"); 7032698Sktlim@umich.edu 7042698Sktlim@umich.eduif (interrupts & ISR_TXRCMP) 7053014Srdreslin@umich.edu regs.isr |= ISR_TXRCMP; 7062669Sktlim@umich.edu 7072693Sktlim@umich.eduif (interrupts & ISR_RXRCMP) 7082292SN/A regs.isr |= ISR_RXRCMP; 7092292SN/A 7102292SN/A//ISR_DPERR not implemented 7112292SN/A//ISR_SSERR not implemented 7122292SN/A//ISR_RMABT not implemented 7132292SN/A//ISR_RXSOVR not implemented 7142292SN/A//ISR_HIBINT not implemented 7152292SN/A//ISR_PHY not implemented 7162292SN/A//ISR_PME not implemented 7172292SN/A 7182292SN/Aif (interrupts & ISR_SWI) 7192292SN/A regs.isr |= ISR_SWI; 7202292SN/A 7212292SN/A//ISR_MIB not implemented 7222292SN/A//ISR_TXURN not implemented 7232292SN/A 7242292SN/A if (interrupts & ISR_TXIDLE) 7252292SN/A regs.isr |= ISR_TXIDLE; 7262292SN/A 7272292SN/A if (interrupts & ISR_TXERR) 7282292SN/A regs.isr |= ISR_TXERR; 7292292SN/A 7302292SN/A if (interrupts & ISR_TXDESC) 7312292SN/A regs.isr |= ISR_TXDESC; 7322292SN/A 7332292SN/A if (interrupts & ISR_TXOK) 7342292SN/A regs.isr |= ISR_TXOK; 7352292SN/A 7362329SN/A if (interrupts & ISR_RXORN) 7372292SN/A regs.isr |= ISR_RXORN; 7382292SN/A 7392292SN/A if (interrupts & ISR_RXIDLE) 7402292SN/A regs.isr |= ISR_RXIDLE; 7412292SN/A 7422292SN/A//ISR_RXEARLY not implemented 7432292SN/A 7442292SN/A if (interrupts & ISR_RXERR) 7452292SN/A regs.isr |= ISR_RXERR; 7462292SN/A 7472292SN/A if (interrupts & ISR_RXOK) 7482292SN/A regs.isr |= ISR_RXOK; 7492292SN/A 7502292SN/A if ((regs.isr & regs.imr)) 7512292SN/A cpuIntrPost(); 7522292SN/A} 7532329SN/A 7542731Sktlim@umich.eduvoid 7552292SN/AEtherDev::devIntrClear(uint32_t interrupts) 7562292SN/A{ 7572292SN/A DPRINTF(Ethernet, "interrupt cleared intr=%x isr=%x imr=%x\n", 7582292SN/A interrupts, regs.isr, regs.imr); 7592292SN/A 7602292SN/A if (interrupts & ISR_RESERVE) 7612292SN/A panic("Cannot clear a reserved interrupt"); 7622727Sktlim@umich.edu 7632292SN/A if (interrupts & ISR_TXRCMP) 7642292SN/A regs.isr &= ~ISR_TXRCMP; 7652292SN/A 7662292SN/A if (interrupts & ISR_RXRCMP) 7672292SN/A regs.isr &= ~ISR_RXRCMP; 7682292SN/A 7692292SN/A//ISR_DPERR not implemented 7702292SN/A//ISR_SSERR not implemented 7712292SN/A//ISR_RMABT not implemented 7722292SN/A//ISR_RXSOVR not implemented 7734032Sktlim@umich.edu//ISR_HIBINT not implemented 7744032Sktlim@umich.edu//ISR_PHY not implemented 7754032Sktlim@umich.edu//ISR_PME not implemented 7764032Sktlim@umich.edu 7772292SN/A if (interrupts & ISR_SWI) 7782292SN/A regs.isr &= ~ISR_SWI; 7792292SN/A 7802292SN/A//ISR_MIB not implemented 7812292SN/A//ISR_TXURN not implemented 7822329SN/A 7832292SN/A if (interrupts & ISR_TXIDLE) 7842292SN/A regs.isr &= ~ISR_TXIDLE; 7852292SN/A 7862292SN/A if (interrupts & ISR_TXERR) 7872292SN/A regs.isr &= ~ISR_TXERR; 7882292SN/A 7892292SN/A if (interrupts & ISR_TXDESC) 7902292SN/A regs.isr &= ~ISR_TXDESC; 7912292SN/A 7922329SN/A if (interrupts & ISR_TXOK) 7932329SN/A regs.isr &= ~ISR_TXOK; 7942292SN/A 7952292SN/A if (interrupts & ISR_RXORN) 7962292SN/A regs.isr &= ~ISR_RXORN; 7972292SN/A 7982292SN/A if (interrupts & ISR_RXIDLE) 7992292SN/A regs.isr &= ~ISR_RXIDLE; 8002292SN/A 8012329SN/A//ISR_RXEARLY not implemented 8022731Sktlim@umich.edu 8032292SN/A if (interrupts & ISR_RXERR) 8042292SN/A regs.isr &= ~ISR_RXERR; 8052292SN/A 8064032Sktlim@umich.edu if (interrupts & ISR_RXOK) 8074032Sktlim@umich.edu regs.isr &= ~ISR_RXOK; 8084032Sktlim@umich.edu 8094032Sktlim@umich.edu if ((regs.isr & regs.imr)) 8104032Sktlim@umich.edu cpuIntrPost(); 8112292SN/A 8122292SN/A if (!(regs.isr & regs.imr)) 8132292SN/A cpuIntrClear(); 8142292SN/A} 8152292SN/A 8162292SN/Avoid 8172292SN/AEtherDev::devIntrChangeMask() 8182727Sktlim@umich.edu{ 8192292SN/A DPRINTF(Ethernet, "iterrupt mask changed\n"); 8202292SN/A 8212292SN/A if (regs.isr & regs.imr) 8222292SN/A cpuIntrPost(); 8232292SN/A else 8243349Sbinkertn@umich.edu cpuIntrClear(); 8252693Sktlim@umich.edu} 8262693Sktlim@umich.edu 8272693Sktlim@umich.eduvoid 8282693Sktlim@umich.eduEtherDev::cpuIntrPost() 8292693Sktlim@umich.edu{ 8302693Sktlim@umich.edu if (!cpuPendingIntr) { 8312693Sktlim@umich.edu if (regs.ier) { 8322693Sktlim@umich.edu cpuPendingIntr = true; 8332693Sktlim@umich.edu intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 8342693Sktlim@umich.edu } 8352693Sktlim@umich.edu } 8362693Sktlim@umich.edu} 8372693Sktlim@umich.edu 8382693Sktlim@umich.eduvoid 8392693Sktlim@umich.eduEtherDev::cpuIntrClear() 8402693Sktlim@umich.edu{ 8412733Sktlim@umich.edu if (cpuPendingIntr) { 8422693Sktlim@umich.edu cpuPendingIntr = false; 8432732Sktlim@umich.edu intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 8442693Sktlim@umich.edu } 8452733Sktlim@umich.edu} 8462693Sktlim@umich.edu 8472693Sktlim@umich.edubool 8482693Sktlim@umich.eduEtherDev::cpuIntrPending() const 8492693Sktlim@umich.edu{ return cpuPendingIntr; } 8502693Sktlim@umich.edu 8512693Sktlim@umich.eduvoid 8522693Sktlim@umich.eduEtherDev::txReset() 8532678Sktlim@umich.edu{ 8542678Sktlim@umich.edu 8552678Sktlim@umich.edu DPRINTF(Ethernet, "transmit reset\n"); 8562678Sktlim@umich.edu 8572678Sktlim@umich.edu txPacketFlag = false; 8582678Sktlim@umich.edu CTDD = false; 8592927Sktlim@umich.edu txFifoCnt = 0; 8602678Sktlim@umich.edu txFifoAvail = 0; 8612727Sktlim@umich.edu txHalt = false; 8622678Sktlim@umich.edu txFifo.clear(); 8632678Sktlim@umich.edu descAddrFifo.clear(); 8642678Sktlim@umich.edu regs.command &= ~CR_TXE; 8652678Sktlim@umich.edu txState = txIdle; 8662678Sktlim@umich.edu} 8672678Sktlim@umich.edu 8682678Sktlim@umich.eduvoid 8692678Sktlim@umich.eduEtherDev::rxReset() 8702678Sktlim@umich.edu{ 8712678Sktlim@umich.edu DPRINTF(Ethernet, "receive reset\n"); 8722678Sktlim@umich.edu 8732678Sktlim@umich.edu rxPacketFlag = false; 8742678Sktlim@umich.edu CRDD = false; 8752678Sktlim@umich.edu fragLen = 0; 8762678Sktlim@umich.edu rxFifoCnt = 0; 8772678Sktlim@umich.edu rxHalt = false; 8782678Sktlim@umich.edu rxFifo.clear(); 8792678Sktlim@umich.edu regs.command &= ~CR_RXE; 8802292SN/A rxState = rxIdle; 8812292SN/A} 8822292SN/A 8832292SN/A/** 8842292SN/A * This sets up a DMA transfer to read one data segment from the rxFifo into 8852292SN/A * the buffer indicated by rxDescCache.bufptr. Assumes the value of rxFragPtr 8862292SN/A * is already correctly set. 8872292SN/A */ 8883126Sktlim@umich.eduvoid 8892292SN/AEtherDev::writeOneFrag() 8902292SN/A{ 8912292SN/A /* i think there is no need for an "in use" warning here like in old */ 8922292SN/A fragLen = rxFifo.front()->length; //length of whole packet 8932292SN/A fragLen = (fragLen < rxDescCnt) ? fragLen : rxDescCnt; 8942292SN/A 8952292SN/A writePhys.addr = rxFragPtr; 8962292SN/A writePhys.length = fragLen; 8972292SN/A 8982292SN/A // Set up DMA request area 8992292SN/A writeRequest.init(&rxDoneCB, 0, false, &writePhys, 1, fragLen, 9002292SN/A rxDescBufPtr, fragLen, curTick); 9012292SN/A 9022329SN/A dma->doTransfer(&readRequest); 9032329SN/A} 9042329SN/A 9052292SN/Avoid 9062292SN/AEtherDev::rxKick() 9072292SN/A{ 9082292SN/A DPRINTF(Ethernet, "receive state machine activated!\n"); 9092292SN/A 9102292SN/A if (CRDD) { 9112292SN/A rxState = rxDescRefr; 9122292SN/A readOneDesc(rx, LINK_LEN); 9132292SN/A } else { 9142292SN/A rxState = rxDescRead; 9152316SN/A readOneDesc(rx); 9162316SN/A } 9172329SN/A} 9182329SN/A 9192329SN/AEtherDev::RxDescDone::RxDescDone(EtherDev *e) 9202329SN/A : ethernet(e) 9212733Sktlim@umich.edu{ 9222316SN/A} 9232732Sktlim@umich.edu 9242316SN/Astd::string 9252733Sktlim@umich.eduEtherDev::RxDescDone::name() const 9262292SN/A{ 9272292SN/A return ethernet->name() + ".rxDescDoneCB"; 9282292SN/A} 9292693Sktlim@umich.edu 9302693Sktlim@umich.eduvoid 9312693Sktlim@umich.eduEtherDev::RxDescDone::process() 9322698Sktlim@umich.edu{ 9334985Sktlim@umich.edu DPRINTF(Ethernet, "receive descriptor done callback\n"); 9342698Sktlim@umich.edu ethernet->rxDescDone(); 9352693Sktlim@umich.edu} 9362698Sktlim@umich.edu 9372698Sktlim@umich.eduvoid 9382699Sktlim@umich.eduEtherDev::rxDescDone() 9392693Sktlim@umich.edu{ 9403014Srdreslin@umich.edu if (rxState == rxDescRefr) { 9412693Sktlim@umich.edu if (rxDescCache.link == 0) { 9422693Sktlim@umich.edu rxState = rxIdle; 9432727Sktlim@umich.edu regs.command &= ~CR_RXE; 9442907Sktlim@umich.edu devIntrPost(ISR_RXIDLE); 9452693Sktlim@umich.edu return; 9462693Sktlim@umich.edu } else { 9472693Sktlim@umich.edu rxState = rxDescRead; 9482693Sktlim@umich.edu regs.rxdp = rxDescCache.link; 9492693Sktlim@umich.edu CRDD = false; 9502693Sktlim@umich.edu readOneDesc(rx); 9512693Sktlim@umich.edu } 9522693Sktlim@umich.edu } else if (rxState == rxDescRead) { 9532693Sktlim@umich.edu if (rxDescCache.cmdsts & CMDSTS_OWN) { 9542693Sktlim@umich.edu rxState = rxIdle; 9552292SN/A regs.command &= ~CR_RXE; 9562292SN/A devIntrPost(ISR_RXIDLE); 9572292SN/A } else { 9582292SN/A rxState = rxFifoBlock; 9592292SN/A rxFragPtr = rxDescCache.bufptr; 9602292SN/A rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 9612292SN/A 9622292SN/A if (!rxFifo.empty()) { 9632292SN/A rxState = rxFragWrite; 9642292SN/A if (!rxPacketFlag) { // reading a new packet 9652292SN/A rxPacketBufPtr = rxFifo.front()->data; 9662292SN/A rxPacketBufPtr -= rxDescCnt; 9672292SN/A rxDescBufPtr = rxPacketBufPtr; 9682292SN/A rxCopied = 0; 9692292SN/A } else { 9702292SN/A rxDescBufPtr = rxPacketBufPtr - rxDescCnt; 9712292SN/A } 9722292SN/A writeOneFrag(); 9732292SN/A } 9742292SN/A } 9752292SN/A } else if (rxState == rxDescWrite) { 9762292SN/A devIntrPost(ISR_RXOK); 9772292SN/A 9782292SN/A if (rxDescCache.cmdsts & CMDSTS_INTR) 9792292SN/A devIntrPost(ISR_RXDESC); 9802292SN/A 9812292SN/A if (rxDescCache.link == 0 || ((rxPktBytes != 0) && rxHalt)) { 9822292SN/A rxState = rxIdle; 9832292SN/A regs.command &= ~CR_RXE; 9842292SN/A devIntrPost(ISR_RXIDLE); 9852329SN/A rxHalt = false; 9862329SN/A } else { 9872329SN/A rxState = rxDescRead; 9882329SN/A regs.rxdp = rxDescCache.link; 9892329SN/A CRDD = false; 9902329SN/A readOneDesc(rx); 9912329SN/A } 9922329SN/A } 9932329SN/A} 9942329SN/A 9952329SN/AEtherDev::RxDone::RxDone(EtherDev *e) 9962329SN/A : ethernet(e) 9972329SN/A{ 9982329SN/A} 9992329SN/A 10002329SN/Astd::string 10012329SN/AEtherDev::RxDone::name() const 10022329SN/A{ 10032329SN/A return ethernet->name() + ".rxDoneCB"; 10042329SN/A} 10052329SN/A 10062329SN/Avoid 10072329SN/AEtherDev::RxDone::process() 10082329SN/A{ 10092329SN/A DPRINTF(Ethernet, "receive done callback\n"); 10102329SN/A ethernet->rxDone(); 10112329SN/A} 10122329SN/A 10132329SN/Avoid 10142329SN/AEtherDev::rxDone() 1015{ 1016 DPRINTF(Ethernet, "packet received to host memory\n"); 1017 1018 if (!rxDescCache.cmdsts & CMDSTS_OWN) 1019 panic("This descriptor is already owned by the driver!\n"); 1020 1021 rxState = rxFifoBlock; 1022 rxCopied += fragLen; 1023 rxFifoCnt -= fragLen; 1024 1025 if (rxDescCnt) { /* there is still data left in the descriptor */ 1026 rxState = rxFragWrite; 1027 rxDescBufPtr += fragLen; 1028 writeOneFrag(); 1029 } else { 1030 rxState = rxDescWrite; 1031 if (rxPktBytes == 0) { /* packet is done */ 1032 rxDescCache.cmdsts |= CMDSTS_OWN; 1033 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1034 rxDescCache.cmdsts |= CMDSTS_OK; 1035 rxDescCache.cmdsts += rxCopied; //i.e. set CMDSTS_SIZE 1036 1037 rxPacketFlag = false; 1038 if (rxFilterEnable) { 1039 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1040 if (rxFifo.front()->IsUnicast()) 1041 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1042 if (rxFifo.front()->IsMulticast()) 1043 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1044 if (rxFifo.front()->IsBroadcast()) 1045 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1046 } 1047 1048 PacketPtr &pkt = rxFifo.front(); 1049 eth_header *eth = (eth_header *) pkt->data; 1050 if (eth->type == 0x800 && extstsEnable) { 1051 rxDescCache.extsts |= EXTSTS_IPPKT; 1052 if (!ipChecksum(pkt, false)) 1053 rxDescCache.extsts |= EXTSTS_IPERR; 1054 ip_header *ip = rxFifo.front()->getIpHdr(); 1055 1056 if (ip->protocol == 6) { 1057 rxDescCache.extsts |= EXTSTS_TCPPKT; 1058 if (!tcpChecksum(pkt, false)) 1059 rxDescCache.extsts |= EXTSTS_TCPERR; 1060 } else if (ip->protocol == 17) { 1061 rxDescCache.extsts |= EXTSTS_UDPPKT; 1062 if (!udpChecksum(pkt, false)) 1063 rxDescCache.extsts |= EXTSTS_UDPERR; 1064 } 1065 } 1066 1067 rxFifo.front() = NULL; 1068 rxFifo.pop_front(); 1069 } else { /* just the descriptor is done */ 1070 rxDescCache.cmdsts |= CMDSTS_OWN; 1071 rxDescCache.cmdsts |= CMDSTS_MORE; 1072 } 1073 writeDescPhys.addr = regs.rxdp + LINK_LEN + BUFPTR_LEN; 1074 writeDescPhys.length = CMDSTS_LEN; 1075 1076 writeDescRequest.init(&rxDescDoneCB, 0, true, &writeDescPhys, 1, 1077 CMDSTS_LEN, (uint8_t *) &rxDescCache.cmdsts, 1078 CMDSTS_LEN, curTick); 1079 } 1080} 1081 1082/** 1083 * This sets up a DMA transfer to read one descriptor into the network device. 1084 */ 1085void 1086EtherDev::readOneDesc(dir_t dir, uint32_t len) { 1087 readDescPhys.addr = (dir == tx) ? regs.txdp : regs.rxdp; 1088 readDescPhys.length = len; 1089 1090 ns_desc *cache = (dir == tx) ? &txDescCache : &rxDescCache; 1091 1092 /* THIS ASSUMES THAT DESC_LEN < regs.txcfg's maxdma value, 1093 which is 512 bytes in the driver, so i'll just hard code it here */ 1094 readDescRequest.init(&txDescDoneCB, 0, false, &readDescPhys, 1, 1095 len, (uint8_t *) cache , len, curTick); 1096 1097 dma->doTransfer(&readDescRequest); 1098} 1099 1100/** 1101 * This sets up a DMA transfer to read one data segment of the descriptor in 1102 * txDescCache. Assumes the value of txFragPtr is already correctly set 1103 */ 1104void 1105EtherDev::readOneFrag() 1106{ 1107 /* i think there is no need for an "in use" warning here like in old */ 1108 fragLen = (txDescCnt < txFifoAvail) ? txDescCnt : txFifoAvail; 1109 readPhys.addr = txFragPtr; 1110 readPhys.length = fragLen; 1111 1112 // Set up DMA request area 1113 readRequest.init(&txDoneCB, 0, false, &readPhys, 1, fragLen, 1114 txPacketBufPtr, fragLen, curTick); 1115 1116 dma->doTransfer(&readRequest); 1117} 1118 1119void 1120EtherDev::transmit() 1121{ 1122 if (txFifo.empty()) { 1123 DPRINTF(Ethernet, "nothing to transmit\n"); 1124 return; 1125 } 1126 1127 if (interface->sendPacket(txFifo.front())) { 1128 DPRINTF(Ethernet, "transmit packet\n"); 1129 txBytes += txFifo.front()->length; 1130 txPackets++; 1131 1132 txFifoCnt -= txFifo.front()->length; 1133 1134 txFifo.front() = NULL; 1135 txFifo.pop_front(); 1136 1137 txDescCache.cmdsts &= ~CMDSTS_OK; 1138 } else { 1139 txDescCache.cmdsts &= ~CMDSTS_ERR; 1140 } 1141 1142 txDescCache.cmdsts &= ~CMDSTS_OWN; 1143 1144 writeDescPhys.addr = descAddrFifo.front() + LINK_LEN + BUFPTR_LEN; 1145 writeDescPhys.length = CMDSTS_LEN; 1146 1147 descAddrFifo.front() = 0; 1148 descAddrFifo.pop_front(); 1149 1150 writeDescRequest.init(&txDescDoneCB, 0, true, &writeDescPhys, 1, 1151 writeDescPhys.length, 1152 (uint8_t *) &(txDescCache.cmdsts), 1153 writeDescPhys.length, curTick); 1154 1155 dma->doTransfer(&writeDescRequest); 1156 1157 transmit(); 1158} 1159 1160void 1161EtherDev::txKick() 1162{ 1163 DPRINTF(Ethernet, "transmit state machine activated\n"); 1164#if 0 1165 if (DTRACE(Ethernet)) 1166 txDump(); 1167#endif 1168 1169 if (CTDD) { 1170 txState = txDescRefr; 1171 readOneDesc(tx, LINK_LEN); 1172 } else { 1173 txState = txDescRead; 1174 readOneDesc(tx); 1175 } 1176} 1177 1178EtherDev::TxDescDone::TxDescDone(EtherDev *e) 1179 : ethernet(e) 1180{ 1181} 1182 1183std::string 1184EtherDev::TxDescDone::name() const 1185{ 1186 return ethernet->name() + ".txDescDoneCB"; 1187} 1188 1189void 1190EtherDev::TxDescDone::process() 1191{ 1192 DPRINTF(Ethernet, "transmit descriptor done callback\n"); 1193 ethernet->txDescDone(); 1194 1195} 1196 1197void 1198EtherDev::txDescDone() 1199{ 1200 if (txState == txFifoBlock) { 1201 if (txDescCache.cmdsts & CMDSTS_OK) { 1202 devIntrPost(ISR_TXOK); 1203 } else if (txDescCache.cmdsts & CMDSTS_ERR) { 1204 devIntrPost(ISR_TXERR); 1205 } 1206 } else if (txState == txDescRefr || txState == txDescWrite) { 1207 1208 if (txState == txDescWrite) { 1209 if (txDescCache.cmdsts & CMDSTS_INTR) { 1210 devIntrPost(ISR_TXDESC); 1211 } 1212 } 1213 1214 if (txDescCache.link == 0) { 1215 txState = txIdle; 1216 regs.command &= ~CR_TXE; 1217 devIntrPost(ISR_TXIDLE); 1218 return; 1219 } else { 1220 txState = txDescRead; 1221 regs.txdp = txDescCache.link; 1222 CTDD = false; 1223 readOneDesc(tx); 1224 } 1225 } else if (txState == txDescRead) { 1226 if (txDescCache.cmdsts & CMDSTS_OWN) { 1227 txState = txFifoBlock; 1228 txFragPtr = txDescCache.bufptr; 1229 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1230 1231 if (txFifoAvail >= ((regs.txcfg & TXCFG_FLTH_MASK) >> 8)) { 1232 txState = txFragRead; 1233 if (!txPacketFlag) { 1234 txPacketFlag = true; 1235 /* find the total length of this packet */ 1236 txPacketLen = txDescCnt; 1237 bool more = txDescCache.cmdsts & CMDSTS_MORE; 1238 uint8_t *addr = (uint8_t *) regs.txdp; 1239 while (more) { 1240 addr = physmem->dma_addr(((ns_desc *) addr)->link, sizeof(ns_desc)); 1241 /* !!!!!!mask needed? */ 1242 txPacketLen += ((ns_desc *)addr)->cmdsts & CMDSTS_LEN_MASK; 1243 more = ((ns_desc *) addr)->cmdsts & CMDSTS_MORE; 1244 } 1245 PacketPtr &packet = txDoneCB.packet; 1246 packet = new EtherPacket; 1247 packet->length = txPacketLen; 1248 packet->data = new uint8_t[txPacketLen]; 1249 txPacketBufPtr = packet->data; 1250 } 1251 readOneFrag(); 1252 } 1253 } else { 1254 txState = txIdle; 1255 regs.command &= ~CR_TXE; 1256 devIntrPost(ISR_TXIDLE); 1257 } 1258 } 1259} 1260 1261EtherDev::TxDone::TxDone(EtherDev *e) 1262 : ethernet(e) 1263{ 1264} 1265 1266std::string 1267EtherDev::TxDone::name() const 1268{ 1269 return ethernet->name() + ".txDoneCB"; 1270} 1271 1272 1273void 1274EtherDev::TxDone::process() 1275{ 1276 DPRINTF(Ethernet, "transmit done callback\n"); 1277 ethernet->txDone(packet); 1278} 1279 1280void 1281EtherDev::txDone(PacketPtr packet) 1282{ 1283 DPRINTF(Ethernet, "transmit done\n"); 1284 1285 if (!txDescCache.cmdsts & CMDSTS_OWN) 1286 panic("This descriptor is already owned by the driver!\n"); 1287 1288 txState = txFifoBlock; 1289 1290 txPacketBufPtr += fragLen; /* hope this ptr manipulation is right! */ 1291 txDescCnt -= fragLen; 1292 txFifoCnt += fragLen; 1293 1294 if (txFifoCnt >= (regs.txcfg & TXCFG_DRTH_MASK)) { 1295 if (txFifo.empty()) { 1296 txFifoCnt -= (uint32_t) (txPacketBufPtr - packet->data); 1297 } else { 1298 transmit(); 1299 } 1300 } 1301 1302 if (txDescCnt) { /* if there is still more data to go in this desc */ 1303 if (txFifoAvail >= regs.txcfg & TXCFG_FLTH_MASK) { 1304 txState = txFragRead; 1305 readOneFrag(); 1306 } 1307 } else { /* this descriptor is done */ 1308 /* but there is more descriptors for this packet */ 1309 if (txDescCache.cmdsts & CMDSTS_MORE) { 1310 txState = txDescWrite; 1311 txDescCache.cmdsts &= ~CMDSTS_OWN; 1312 writeDescPhys.addr = regs.txdp + LINK_LEN + BUFPTR_LEN; 1313 writeDescPhys.length = CMDSTS_LEN; 1314 1315 writeDescRequest.init(&txDescDoneCB, 0, true, &writeDescPhys, 1, 1316 writeDescPhys.length, 1317 (uint8_t*) &txDescCache.cmdsts, 1318 writeDescPhys.length, curTick); 1319 } else { /* this packet is totally done */ 1320 /* deal with the the packet that just finished */ 1321 if (regs.vtcr & VTCR_PPCHK && extstsEnable) { 1322 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1323 udpChecksum(packet, true); 1324 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1325 tcpChecksum(packet, true); 1326 } else if (txDescCache.extsts & EXTSTS_IPPKT) { 1327 ipChecksum(packet, true); 1328 } 1329 } 1330 1331 txFifo.push_back(packet); 1332 transmit(); 1333 txPacketFlag = false; 1334 descAddrFifo.push_back(regs.txdp); 1335 1336 /* if there is not another descriptor ready for reading, go idle */ 1337 if (txDescCache.link == 0 || txHalt) { 1338 txState = txIdle; 1339 devIntrPost(ISR_TXIDLE); 1340 txHalt = false; 1341 } else { /* else go read next descriptor */ 1342 txState = txDescRead; 1343 regs.txdp = txDescCache.link; 1344 CTDD = false; 1345 readOneDesc(tx); 1346 } 1347 } 1348 } 1349} 1350 1351void 1352EtherDev::transferDone() 1353{ 1354 if (txFifo.empty()) 1355 return; 1356 1357 DPRINTF(Ethernet, "schedule transmit\n"); 1358 1359 if (txEvent.scheduled()) 1360 txEvent.reschedule(curTick + 1); 1361 else 1362 txEvent.schedule(curTick + 1); 1363} 1364 1365void 1366EtherDev::txDump() const 1367{ 1368#if 0 1369 int i = tx_ptr; 1370 for (int loop = 0; loop < tx_ring_len; loop++) { 1371 es_desc *desc = &tx_ring[i]; 1372 1373 if (desc->addr) 1374 cprintf("desc[%d]: addr=%#x, len=%d, flags=%#x\n", 1375 i, desc->addr, desc->length, desc->flags); 1376 1377 if (++i >= tx_ring_len) 1378 i = 0; 1379 } 1380#endif 1381} 1382 1383void 1384EtherDev::rxDump() const 1385{ 1386#if 0 1387 int i = rx_ptr; 1388 for (int loop = 0; loop < rx_ring_len; loop++) { 1389 es_desc *desc = &rx_ring[i]; 1390 1391 if (desc->addr) 1392 cprintf("desc[%d]: addr=%#x, len=%d, flags=%#x\n", 1393 i, desc->addr, desc->length, desc->flags); 1394 1395 if (++i >= rx_ring_len) 1396 i = 0; 1397 } 1398#endif 1399} 1400 1401bool 1402EtherDev::rxFilter(PacketPtr packet) 1403{ 1404 bool drop = true; 1405 string type; 1406 1407 if (packet->IsUnicast()) { 1408 type = "unicast"; 1409 1410 // If we're accepting all unicast addresses 1411 if (acceptUnicast) 1412 drop = false; 1413 1414 // If we make a perfect match 1415 if ((acceptPerfect) 1416 && (memcmp(regs.perfectMatch, packet->data, sizeof(regs.perfectMatch)) == 0)) 1417 drop = false; 1418 1419 eth_header *eth = (eth_header *) packet->data; 1420 if ((acceptArp) && (eth->type == 0x806)) 1421 drop = false; 1422 1423 } else if (packet->IsBroadcast()) { 1424 type = "broadcast"; 1425 1426 // if we're accepting broadcasts 1427 if (acceptBroadcast) 1428 drop = false; 1429 1430 } else if (packet->IsMulticast()) { 1431 type = "multicast"; 1432 1433 // if we're accepting all multicasts 1434 if (acceptMulticast) 1435 drop = false; 1436 1437 } else { 1438 type = "unknown"; 1439 1440 // oh well, punt on this one 1441 } 1442 1443 if (drop) { 1444 DPRINTF(Ethernet, "rxFilter drop\n"); 1445 DDUMP(EthernetData, packet->data, packet->length); 1446 } 1447 1448 return drop; 1449} 1450 1451bool 1452EtherDev::recvPacket(PacketPtr packet) 1453{ 1454 rxBytes += packet->length; 1455 rxPackets++; 1456 1457 if (rxState == rxIdle) { 1458 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1459 interface->recvDone(); 1460 return true; 1461 } 1462 1463 if (rxFilterEnable && rxFilter(packet)) { 1464 DPRINTF(Ethernet, "packet filtered...dropped\n"); 1465 interface->recvDone(); 1466 return true; 1467 } 1468 1469 if (rxFifoCnt + packet->length >= MAX_RX_FIFO_SIZE) { 1470 DPRINTF(Ethernet, 1471 "packet will not fit in receive buffer...packet dropped\n"); 1472 devIntrPost(ISR_RXORN); 1473 return false; 1474 } 1475 1476 rxFifo.push_back(packet); 1477 rxPktBytes = packet->length; 1478 rxFifoCnt += packet->length; 1479 interface->recvDone(); 1480 1481 return true; 1482} 1483 1484bool 1485EtherDev::udpChecksum(PacketPtr packet, bool gen) 1486{ 1487 udp_header *hdr = (udp_header *) packet->getTransportHdr(); 1488 1489 ip_header *ip = packet->getIpHdr(); 1490 1491 pseudo_header *pseudo = new pseudo_header; 1492 1493 pseudo->src_ip_addr = ip->src_ip_addr; 1494 pseudo->dest_ip_addr = ip->dest_ip_addr; 1495 pseudo->protocol = ip->protocol; 1496 pseudo->len = hdr->len; 1497 1498 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 1499 (uint32_t) hdr->len); 1500 1501 delete pseudo; 1502 if (gen) 1503 hdr->chksum = cksum; 1504 else 1505 if (cksum != 0) 1506 return false; 1507 1508 return true; 1509} 1510 1511bool 1512EtherDev::tcpChecksum(PacketPtr packet, bool gen) 1513{ 1514 tcp_header *hdr = (tcp_header *) packet->getTransportHdr(); 1515 1516 ip_header *ip = packet->getIpHdr(); 1517 1518 pseudo_header *pseudo = new pseudo_header; 1519 1520 pseudo->src_ip_addr = ip->src_ip_addr; 1521 pseudo->dest_ip_addr = ip->dest_ip_addr; 1522 pseudo->protocol = ip->protocol; 1523 pseudo->len = ip->dgram_len - (ip->vers_len & 0xf); 1524 1525 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 1526 (uint32_t) pseudo->len); 1527 1528 delete pseudo; 1529 if (gen) 1530 hdr->chksum = cksum; 1531 else 1532 if (cksum != 0) 1533 return false; 1534 1535 return true; 1536} 1537 1538bool 1539EtherDev::ipChecksum(PacketPtr packet, bool gen) 1540{ 1541 ip_header *hdr = packet->getIpHdr(); 1542 1543 uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, (hdr->vers_len & 0xf)); 1544 1545 if (gen) 1546 hdr->hdr_chksum = cksum; 1547 else 1548 if (cksum != 0) 1549 return false; 1550 1551 return true; 1552} 1553 1554uint16_t 1555EtherDev::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) 1556{ 1557 uint32_t sum = 0; 1558 1559 uint16_t last_pad = 0; 1560 if (len & 1) { 1561 last_pad = buf[len/2] & 0xff; 1562 len--; 1563 sum += last_pad; 1564 } 1565 1566 if (pseudo) { 1567 sum = pseudo[0] + pseudo[1] + pseudo[2] + 1568 pseudo[3] + pseudo[4] + pseudo[5]; 1569 } 1570 1571 for (int i=0; i < (len/2); ++i) { 1572 sum += buf[i]; 1573 } 1574 1575 while (sum >> 16) 1576 sum = (sum >> 16) + (sum & 0xffff); 1577 1578 return ~sum; 1579} 1580 1581//===================================================================== 1582// 1583// 1584void 1585dp_regs::serialize(ostream &os) 1586{ 1587 SERIALIZE_SCALAR(command); 1588 SERIALIZE_SCALAR(config); 1589 SERIALIZE_SCALAR(isr); 1590 SERIALIZE_SCALAR(imr); 1591} 1592 1593void 1594dp_regs::unserialize(Checkpoint *cp, const std::string §ion) 1595{ 1596 UNSERIALIZE_SCALAR(command); 1597 UNSERIALIZE_SCALAR(config); 1598 UNSERIALIZE_SCALAR(isr); 1599 UNSERIALIZE_SCALAR(imr); 1600#if 0 1601 UNSERIALIZE_SCALAR(tx_ring); 1602 UNSERIALIZE_SCALAR(rx_ring); 1603 UNSERIALIZE_SCALAR(tx_ring_len); 1604 UNSERIALIZE_SCALAR(rx_ring_len); 1605 UNSERIALIZE_SCALAR(rom_addr); 1606 UNSERIALIZE_SCALAR(rom_data); 1607 UNSERIALIZE_SCALAR(rxfilt_ctl); 1608 UNSERIALIZE_SCALAR(rxfilt_data); 1609 1610 UNSERIALIZE_ARRAY(perfect,EADDR_LEN); 1611 UNSERIALIZE_ARRAY(hash_table,ES_HASH_SIZE); 1612 1613 UNSERIALIZE_SCALAR(tx_ring_ptr); 1614 UNSERIALIZE_SCALAR(rx_ring_ptr); 1615#endif 1616} 1617 1618//--------------------------------------- 1619 1620void 1621EtherPacket::serialize(ostream &os) 1622{ 1623 SERIALIZE_SCALAR(length); 1624 SERIALIZE_ARRAY(data, length); 1625} 1626 1627void 1628EtherPacket::unserialize(Checkpoint *cp, const std::string §ion) 1629{ 1630 UNSERIALIZE_SCALAR(length); 1631 data = new uint8_t[length]; 1632 UNSERIALIZE_ARRAY(data, length); 1633} 1634 1635//--------------------------------------- 1636 1637void 1638EtherDev::serialize(ostream &os) 1639{ 1640 1641#if 0 1642 regs.serialize(os); 1643 1644 // tx_ring & rx_ring are contained in the physmem... 1645 SERIALIZE_SCALAR(cpuPendingIntr); 1646 SERIALIZE_SCALAR(tx_ptr); 1647 SERIALIZE_SCALAR(rx_ptr); 1648 1649 SERIALIZE_SCALAR(rxDoneCB.ptr); 1650 SERIALIZE_SCALAR(rxDoneCB.ignore); 1651 1652 SERIALIZE_SCALAR(txDoneCB.ptr); 1653 SERIALIZE_SCALAR(txDoneCB.ignore); 1654 1655 for (int i=0; i<ES_MAX_DMA_SEGS; ++i) { 1656 paramOut(os, csprintf("readPhys%d.addr",i), readPhys[i].addr); 1657 paramOut(os, csprintf("readPhys%d.length",i), readPhys[i].length); 1658 paramOut(os, csprintf("writePhys%d.addr",i), writePhys[i].addr); 1659 paramOut(os, csprintf("writePhys%d.length",i), writePhys[i].length); 1660 } 1661 1662 SERIALIZE_SCALAR(txEnable); 1663 SERIALIZE_SCALAR(rxEnable); 1664 SERIALIZE_SCALAR(txDelay); 1665 SERIALIZE_SCALAR(rxDelay); 1666 1667 SERIALIZE_SCALAR(txbuf_len); 1668 1669 //Calculate the number here, actually dump them at end 1670 int numTxPkts=0; 1671 for (pktiter_t p=txbuf.begin(); p!=txbuf.end(); ++p) { 1672 numTxPkts++; 1673 } 1674 SERIALIZE_SCALAR(numTxPkts); 1675 1676 SERIALIZE_SCALAR(rxbuf_len); 1677 int numRxPkts=0; 1678 for (pktiter_t p=rxbuf.begin(); p!=rxbuf.end(); ++p) { 1679 numRxPkts++; 1680 } 1681 SERIALIZE_SCALAR(numRxPkts); 1682 1683 // output whether the tx and rx packets exist 1684 bool txPacketExists = false; 1685 if (txDoneCB.packet) 1686 txPacketExists = true; 1687 SERIALIZE_SCALAR(txPacketExists); 1688 1689 bool rxPacketExists = false; 1690 if (rxPacket) 1691 rxPacketExists = true; 1692 SERIALIZE_SCALAR(rxPacketExists); 1693 1694 // output the names (unique by pointer) of the read and write requests 1695 paramOut(os, csprintf("readReqName"), readRequest.name()); 1696 paramOut(os, csprintf("writeReqName"), writeRequest.name()); 1697 1698 // Serialize txPacket, because its data is needed for readRequest 1699 if (txPacketExists) { 1700 nameOut(os, csprintf("%s.txPacket", name())); 1701 txDoneCB.packet->serialize(os); 1702 } 1703 1704 // Serialize rxPacket, because its data is needed for writeRequest 1705 if (rxPacketExists) { 1706 nameOut(os, csprintf("%s.rxPacket", name())); 1707 rxPacket->serialize(os); 1708 } 1709 1710 // create a section for the readRequest 1711 nameOut(os, readRequest.name()); 1712 paramOut(os, csprintf("parent"), name()); 1713 paramOut(os, csprintf("id"), 0); 1714 readRequest.serialize(os); 1715 1716 // create a section for the writeRequest 1717 nameOut(os, writeRequest.name()); 1718 paramOut(os, csprintf("parent"), name()); 1719 paramOut(os, csprintf("id"), 1); 1720 writeRequest.serialize(os); 1721 1722 //Redo the buffers, this time outputing them to the file 1723 numTxPkts = 0; 1724 for (pktiter_t p=txbuf.begin(); p!=txbuf.end(); ++p) { 1725 nameOut(os, csprintf("%s.txbuf%d", name(),numTxPkts++)); 1726 (*p)->serialize(os); 1727 } 1728 1729 numRxPkts = 0; 1730 for (pktiter_t p=rxbuf.begin(); p!=rxbuf.end(); ++p) { 1731 nameOut(os, csprintf("%s.rxbuf%d", name(),numRxPkts++)); 1732 (*p)->serialize(os); 1733 } 1734#endif 1735} 1736 1737void 1738EtherDev::unserialize(Checkpoint *cp, const std::string §ion) 1739{ 1740#if 0 1741 regs.unserialize(cp, section); 1742 1743 UNSERIALIZE_SCALAR(cpuPendingIntr); 1744 1745 // initialize the tx_ring 1746 txReset(); 1747 1748 // initialize the rx_ring 1749 rxReset(); 1750 1751 UNSERIALIZE_SCALAR(tx_ptr); 1752 UNSERIALIZE_SCALAR(rx_ptr); 1753 1754 PacketPtr p; 1755 UNSERIALIZE_SCALAR(txbuf_len); 1756 int numTxPkts; 1757 UNSERIALIZE_SCALAR(numTxPkts); 1758 for (int i=0; i<numTxPkts; ++i) { 1759 p = new EtherPacket; 1760 p->unserialize(cp, csprintf("%s.txbuf%d", section, i)); 1761 txbuf.push_back(p); 1762 } 1763 1764 UNSERIALIZE_SCALAR(rxbuf_len); 1765 int numRxPkts; 1766 UNSERIALIZE_SCALAR(numRxPkts); 1767 for (int i=0; i<numRxPkts; ++i) { 1768 p = new EtherPacket; 1769 p->unserialize(cp, csprintf("%s.rxbuf%d", section, i)); 1770 rxbuf.push_back(p); 1771 } 1772 1773 UNSERIALIZE_SCALAR(rxDoneCB.ptr); 1774 UNSERIALIZE_SCALAR(rxDoneCB.ignore); 1775 1776 UNSERIALIZE_SCALAR(txDoneCB.ptr); 1777 UNSERIALIZE_SCALAR(txDoneCB.ignore); 1778 1779 for (int i=0; i<ES_MAX_DMA_SEGS; ++i) { 1780 paramIn(cp, section, csprintf("readPhys%d.addr",i), 1781 readPhys[i].addr); 1782 paramIn(cp, section, csprintf("readPhys%d.length",i), 1783 readPhys[i].length); 1784 paramIn(cp, section, csprintf("writePhys%d.addr",i), 1785 writePhys[i].addr); 1786 paramIn(cp, section, csprintf("writePhys%d.length",i), 1787 writePhys[i].length); 1788 } 1789 1790 UNSERIALIZE_SCALAR(txEnable); 1791 UNSERIALIZE_SCALAR(rxEnable); 1792 UNSERIALIZE_SCALAR(txDelay); 1793 UNSERIALIZE_SCALAR(rxDelay); 1794 1795 // Unserialize the current txPacket 1796 bool txPacketExists; 1797 UNSERIALIZE_SCALAR(txPacketExists); 1798 1799 txDoneCB.packet = NULL; 1800 if (txPacketExists) { 1801 txDoneCB.packet = new EtherPacket; 1802 txDoneCB.packet->unserialize(cp, csprintf("%s.txPacket", section)); 1803 } 1804 1805 // Unserialize the current rxPacket 1806 bool rxPacketExists; 1807 UNSERIALIZE_SCALAR(rxPacketExists); 1808 1809 rxPacket = NULL; 1810 if (rxPacketExists) { 1811 rxPacket = new EtherPacket; 1812 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 1813 } 1814 1815 std::string readReqName, writeReqName; 1816 UNSERIALIZE_SCALAR(readReqName); 1817 UNSERIALIZE_SCALAR(writeReqName); 1818 1819 // Unserialize and fixup the readRequest 1820 readRequest.unserialize(cp, readReqName); 1821 readRequest.phys = readPhys; 1822 readRequest.bufferCB = 0; 1823 readRequest.dmaDoneCB = &txDoneCB; 1824 readRequest.data = NULL; 1825 1826 if (txDoneCB.packet) 1827 readRequest.data = txDoneCB.packet->data; 1828 1829 // Unserialize and fixup the writeRequest 1830 writeRequest.unserialize(cp, writeReqName); 1831 writeRequest.phys = writePhys; 1832 writeRequest.bufferCB = 0; 1833 writeRequest.dmaDoneCB = &rxDoneCB; 1834 writeRequest.data = NULL; 1835 1836 if (rxPacket) 1837 writeRequest.data = rxPacket->data; 1838#endif 1839} 1840 1841 1842//===================================================================== 1843 1844 1845BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt) 1846 1847 SimObjectParam<EtherInt *> peer; 1848 SimObjectParam<EtherDev *> device; 1849 1850END_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt) 1851 1852BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDevInt) 1853 1854 INIT_PARAM_DFLT(peer, "peer interface", NULL), 1855 INIT_PARAM(device, "Ethernet device of this interface") 1856 1857END_INIT_SIM_OBJECT_PARAMS(EtherDevInt) 1858 1859CREATE_SIM_OBJECT(EtherDevInt) 1860{ 1861 EtherDevInt *dev_int = new EtherDevInt(getInstanceName(), device); 1862 1863 EtherInt *p = (EtherInt *)peer; 1864 if (p) { 1865 dev_int->setPeer(p); 1866 p->setPeer(dev_int); 1867 } 1868 1869 return dev_int; 1870} 1871 1872REGISTER_SIM_OBJECT("EtherDevInt", EtherDevInt) 1873 1874 1875BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev) 1876 1877 Param<Tick> tx_delay; 1878 Param<Tick> rx_delay; 1879 SimObjectParam<DmaEngine *> engine; 1880 Param<bool> use_interface; 1881 SimObjectParam<IntrControl *> intr_ctrl; 1882 SimObjectParam<MemoryController *> mmu; 1883 SimObjectParam<PhysicalMemory *> physmem; 1884 Param<Addr> addr; 1885 Param<Addr> mask; 1886 Param<bool> rx_filter; 1887 Param<string> hardware_address; 1888 SimObjectParam<PCIConfigAll *> configspace; 1889 SimObjectParam<PciConfigData *> configdata; 1890 SimObjectParam<Tsunami *> tsunami; 1891 Param<uint32_t> pci_bus; 1892 Param<uint32_t> pci_dev; 1893 Param<uint32_t> pci_func; 1894 1895END_DECLARE_SIM_OBJECT_PARAMS(EtherDev) 1896 1897BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev) 1898 1899 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 1900 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 1901 INIT_PARAM(engine, "DMA Engine"), 1902 INIT_PARAM_DFLT(use_interface, "Use DMA Interface", true), 1903 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 1904 INIT_PARAM(mmu, "Memory Controller"), 1905 INIT_PARAM(physmem, "Physical Memory"), 1906 INIT_PARAM(addr, "Device Address"), 1907 INIT_PARAM(mask, "Address Mask"), 1908 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 1909 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 1910 "00:99:00:00:00:01"), 1911 INIT_PARAM(configspace, "PCI Configspace"), 1912 INIT_PARAM(configdata, "PCI Config data"), 1913 INIT_PARAM(tsunami, "Tsunami"), 1914 INIT_PARAM(pci_bus, "PCI bus"), 1915 INIT_PARAM(pci_dev, "PCI device number"), 1916 INIT_PARAM(pci_func, "PCI function code") 1917 1918END_INIT_SIM_OBJECT_PARAMS(EtherDev) 1919 1920 1921CREATE_SIM_OBJECT(EtherDev) 1922{ 1923 int eaddr[6]; 1924 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 1925 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 1926 1927 return new EtherDev(getInstanceName(), engine, use_interface, 1928 intr_ctrl, mmu, physmem, configspace, configdata, 1929 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 1930 tx_delay, rx_delay, addr, mask); 1931} 1932 1933REGISTER_SIM_OBJECT("EtherDev", EtherDev) 1934