ns_gige.cc revision 13342
1837SN/A/* 21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 3837SN/A * All rights reserved. 4837SN/A * 5837SN/A * Redistribution and use in source and binary forms, with or without 6837SN/A * modification, are permitted provided that the following conditions are 7837SN/A * met: redistributions of source code must retain the above copyright 8837SN/A * notice, this list of conditions and the following disclaimer; 9837SN/A * redistributions in binary form must reproduce the above copyright 10837SN/A * notice, this list of conditions and the following disclaimer in the 11837SN/A * documentation and/or other materials provided with the distribution; 12837SN/A * neither the name of the copyright holders nor the names of its 13837SN/A * contributors may be used to endorse or promote products derived from 14837SN/A * this software without specific prior written permission. 15837SN/A * 16837SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17837SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18837SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19837SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20837SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21837SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22837SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23837SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24837SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25837SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26837SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665SN/A * 282760SN/A * Authors: Nathan Binkert 292760SN/A * Lisa Hsu 30837SN/A */ 31837SN/A 321730SN/A/** @file 33837SN/A * Device module for modelling the National Semiconductor 34837SN/A * DP83820 ethernet controller. Does not support priority queueing 35837SN/A */ 3611263Sandreas.sandberg@arm.com 3711263Sandreas.sandberg@arm.com#include "dev/net/ns_gige.hh" 3811263Sandreas.sandberg@arm.com 39837SN/A#include <deque> 4010469SN/A#include <memory> 41837SN/A#include <string> 42837SN/A 435882SN/A#include "base/debug.hh" 44837SN/A#include "base/inet.hh" 456216SN/A#include "base/types.hh" 466658SN/A#include "config/the_isa.hh" 478232SN/A#include "debug/EthernetAll.hh" 4811263Sandreas.sandberg@arm.com#include "dev/net/etherlink.hh" 492566SN/A#include "mem/packet.hh" 503348SN/A#include "mem/packet_access.hh" 514762SN/A#include "params/NSGigE.hh" 522566SN/A#include "sim/system.hh" 53854SN/A 548737SN/A// clang complains about std::set being overloaded with Packet::set if 558737SN/A// we open up the entire namespace std 5610469SN/Ausing std::make_shared; 578737SN/Ausing std::min; 588737SN/Ausing std::ostream; 598737SN/Ausing std::string; 608737SN/A 61854SN/Aconst char *NsRxStateStrings[] = 62854SN/A{ 63854SN/A "rxIdle", 64854SN/A "rxDescRefr", 65854SN/A "rxDescRead", 66854SN/A "rxFifoBlock", 67854SN/A "rxFragWrite", 68854SN/A "rxDescWrite", 69854SN/A "rxAdvance" 70854SN/A}; 71854SN/A 72854SN/Aconst char *NsTxStateStrings[] = 73854SN/A{ 74854SN/A "txIdle", 75854SN/A "txDescRefr", 76854SN/A "txDescRead", 77854SN/A "txFifoBlock", 78854SN/A "txFragRead", 79854SN/A "txDescWrite", 80854SN/A "txAdvance" 81854SN/A}; 82854SN/A 83854SN/Aconst char *NsDmaState[] = 84854SN/A{ 85854SN/A "dmaIdle", 86854SN/A "dmaReading", 87854SN/A "dmaWriting", 88854SN/A "dmaReadWaiting", 89854SN/A "dmaWriteWaiting" 90854SN/A}; 91837SN/A 921114SN/Ausing namespace Net; 932107SN/Ausing namespace TheISA; 94927SN/A 95837SN/A/////////////////////////////////////////////////////////////////////// 96837SN/A// 97879SN/A// NSGigE PCI Device 98837SN/A// 991149SN/ANSGigE::NSGigE(Params *p) 1009339SN/A : EtherDevBase(p), ioEnable(false), 1011149SN/A txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 102915SN/A txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 1034093SN/A txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false), 1044093SN/A txState(txIdle), txEnable(false), CTDD(false), txHalt(false), 105854SN/A txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 1064093SN/A rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false), 107854SN/A rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1084093SN/A eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0), 1094093SN/A eepromOpcode(0), eepromAddress(0), eepromData(0), 1104093SN/A dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay), 1114093SN/A dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor), 1124093SN/A rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0), 1134093SN/A txDmaData(NULL), txDmaAddr(0), txDmaLen(0), 11412087Sspwilson2@wisc.edu rxDmaReadEvent([this]{ rxDmaReadDone(); }, name()), 11512087Sspwilson2@wisc.edu rxDmaWriteEvent([this]{ rxDmaWriteDone(); }, name()), 11612087Sspwilson2@wisc.edu txDmaReadEvent([this]{ txDmaReadDone(); }, name()), 11712087Sspwilson2@wisc.edu txDmaWriteEvent([this]{ txDmaWriteDone(); }, name()), 1181149SN/A dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1191149SN/A txDelay(p->tx_delay), rxDelay(p->rx_delay), 12012087Sspwilson2@wisc.edu rxKickTick(0), 12112087Sspwilson2@wisc.edu rxKickEvent([this]{ rxKick(); }, name()), 12212087Sspwilson2@wisc.edu txKickTick(0), 12312087Sspwilson2@wisc.edu txKickEvent([this]{ txKick(); }, name()), 12412087Sspwilson2@wisc.edu txEvent([this]{ txEventTransmit(); }, name()), 12512087Sspwilson2@wisc.edu rxFilterEnable(p->rx_filter), 1264093SN/A acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), 1271843SN/A acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1284093SN/A intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false), 129995SN/A intrEvent(0), interface(0) 130837SN/A{ 131854SN/A 132854SN/A 1334981SN/A interface = new NSGigEInt(name() + ".int0", this); 1344981SN/A 135837SN/A regsReset(); 1364762SN/A memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN); 1371909SN/A 1381909SN/A memset(&rxDesc32, 0, sizeof(rxDesc32)); 1391909SN/A memset(&txDesc32, 0, sizeof(txDesc32)); 1401909SN/A memset(&rxDesc64, 0, sizeof(rxDesc64)); 1411909SN/A memset(&txDesc64, 0, sizeof(txDesc64)); 142837SN/A} 143837SN/A 144879SN/ANSGigE::~NSGigE() 1459086SN/A{ 1469086SN/A delete interface; 1479086SN/A} 148837SN/A 149855SN/A/** 150855SN/A * This is to write to the PCI general configuration registers 151855SN/A */ 1522846SN/ATick 1533349SN/ANSGigE::writeConfig(PacketPtr pkt) 154837SN/A{ 1552846SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 156837SN/A if (offset < PCI_DEVICE_SPECIFIC) 1579807SN/A PciDevice::writeConfig(pkt); 158837SN/A else 159897SN/A panic("Device specific PCI config space not implemented!\n"); 160897SN/A 161897SN/A switch (offset) { 1621027SN/A // seems to work fine without all these PCI settings, but i 1631027SN/A // put in the IO to double check, an assertion will fail if we 1641027SN/A // need to properly implement it 165917SN/A case PCI_COMMAND: 166917SN/A if (config.data[offset] & PCI_CMD_IOSE) 167927SN/A ioEnable = true; 168917SN/A else 169927SN/A ioEnable = false; 170897SN/A break; 171897SN/A } 1724875SN/A 1732846SN/A return configDelay; 174837SN/A} 175837SN/A 1764981SN/AEtherInt* 1774981SN/ANSGigE::getEthPort(const std::string &if_name, int idx) 1784981SN/A{ 1794981SN/A if (if_name == "interface") { 1804981SN/A if (interface->getPeer()) 1814981SN/A panic("interface already connected to\n"); 1824981SN/A return interface; 1834981SN/A } 1844981SN/A return NULL; 1854981SN/A} 1864981SN/A 187855SN/A/** 188855SN/A * This reads the device registers, which are detailed in the NS83820 189855SN/A * spec sheet 190855SN/A */ 1912566SN/ATick 1923349SN/ANSGigE::read(PacketPtr pkt) 193837SN/A{ 194927SN/A assert(ioEnable); 195917SN/A 196855SN/A //The mask is to give you only the offset into the device register file 1972641SN/A Addr daddr = pkt->getAddr() & 0xfff; 1982566SN/A DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 1992641SN/A daddr, pkt->getAddr(), pkt->getSize()); 200837SN/A 201855SN/A 2021027SN/A // there are some reserved registers, you can see ns_gige_reg.h and 2031027SN/A // the spec sheet for details 204854SN/A if (daddr > LAST && daddr <= RESERVED) { 205837SN/A panic("Accessing reserved register"); 206854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 2072846SN/A return readConfig(pkt); 208854SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 209854SN/A // don't implement all the MIB's. hopefully the kernel 210854SN/A // doesn't actually DEPEND upon their values 211855SN/A // MIB are just hardware stats keepers 21213342Sgabeblack@google.com pkt->setLE<uint32_t>(0); 2134870SN/A pkt->makeAtomicResponse(); 2142566SN/A return pioDelay; 215854SN/A } else if (daddr > 0x3FC) 216854SN/A panic("Something is messed up!\n"); 217837SN/A 2182641SN/A assert(pkt->getSize() == sizeof(uint32_t)); 2192630SN/A uint32_t ® = *pkt->getPtr<uint32_t>(); 2202566SN/A uint16_t rfaddr; 2212566SN/A 2222566SN/A switch (daddr) { 2232566SN/A case CR: 2242566SN/A reg = regs.command; 2252566SN/A //these are supposed to be cleared on a read 2262566SN/A reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 2272566SN/A break; 2282566SN/A 2292566SN/A case CFGR: 2302566SN/A reg = regs.config; 2312566SN/A break; 2322566SN/A 2332566SN/A case MEAR: 2342566SN/A reg = regs.mear; 2352566SN/A break; 2362566SN/A 2372566SN/A case PTSCR: 2382566SN/A reg = regs.ptscr; 2392566SN/A break; 2402566SN/A 2412566SN/A case ISR: 2422566SN/A reg = regs.isr; 2432566SN/A devIntrClear(ISR_ALL); 2442566SN/A break; 2452566SN/A 2462566SN/A case IMR: 2472566SN/A reg = regs.imr; 2482566SN/A break; 2492566SN/A 2502566SN/A case IER: 2512566SN/A reg = regs.ier; 2522566SN/A break; 2532566SN/A 2542566SN/A case IHR: 2552566SN/A reg = regs.ihr; 2562566SN/A break; 2572566SN/A 2582566SN/A case TXDP: 2592566SN/A reg = regs.txdp; 2602566SN/A break; 2612566SN/A 2622566SN/A case TXDP_HI: 2632566SN/A reg = regs.txdp_hi; 2642566SN/A break; 2652566SN/A 2662566SN/A case TX_CFG: 2672566SN/A reg = regs.txcfg; 2682566SN/A break; 2692566SN/A 2702566SN/A case GPIOR: 2712566SN/A reg = regs.gpior; 2722566SN/A break; 2732566SN/A 2742566SN/A case RXDP: 2752566SN/A reg = regs.rxdp; 2762566SN/A break; 2772566SN/A 2782566SN/A case RXDP_HI: 2792566SN/A reg = regs.rxdp_hi; 2802566SN/A break; 2812566SN/A 2822566SN/A case RX_CFG: 2832566SN/A reg = regs.rxcfg; 2842566SN/A break; 2852566SN/A 2862566SN/A case PQCR: 2872566SN/A reg = regs.pqcr; 2882566SN/A break; 2892566SN/A 2902566SN/A case WCSR: 2912566SN/A reg = regs.wcsr; 2922566SN/A break; 2932566SN/A 2942566SN/A case PCR: 2952566SN/A reg = regs.pcr; 2962566SN/A break; 2972566SN/A 2982566SN/A // see the spec sheet for how RFCR and RFDR work 2992566SN/A // basically, you write to RFCR to tell the machine 3002566SN/A // what you want to do next, then you act upon RFDR, 3012566SN/A // and the device will be prepared b/c of what you 3022566SN/A // wrote to RFCR 3032566SN/A case RFCR: 3042566SN/A reg = regs.rfcr; 3052566SN/A break; 3062566SN/A 3072566SN/A case RFDR: 3082566SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 3092566SN/A switch (rfaddr) { 3102566SN/A // Read from perfect match ROM octets 3112566SN/A case 0x000: 3122566SN/A reg = rom.perfectMatch[1]; 3132566SN/A reg = reg << 8; 3142566SN/A reg += rom.perfectMatch[0]; 315837SN/A break; 3162566SN/A case 0x002: 3172566SN/A reg = rom.perfectMatch[3] << 8; 3182566SN/A reg += rom.perfectMatch[2]; 319837SN/A break; 3202566SN/A case 0x004: 3212566SN/A reg = rom.perfectMatch[5] << 8; 3222566SN/A reg += rom.perfectMatch[4]; 323837SN/A break; 3242566SN/A default: 3252566SN/A // Read filter hash table 3262566SN/A if (rfaddr >= FHASH_ADDR && 3272566SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 3282566SN/A 3292566SN/A // Only word-aligned reads supported 3302566SN/A if (rfaddr % 2) 3312566SN/A panic("unaligned read from filter hash table!"); 3322566SN/A 3332566SN/A reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 3342566SN/A reg += rom.filterHash[rfaddr - FHASH_ADDR]; 335837SN/A break; 336837SN/A } 3372566SN/A 3382566SN/A panic("reading RFDR for something other than pattern" 3392566SN/A " matching or hashing! %#x\n", rfaddr); 340837SN/A } 3412566SN/A break; 3422566SN/A 3432566SN/A case SRR: 3442566SN/A reg = regs.srr; 3452566SN/A break; 3462566SN/A 3472566SN/A case MIBC: 3482566SN/A reg = regs.mibc; 3492566SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 3502566SN/A break; 3512566SN/A 3522566SN/A case VRCR: 3532566SN/A reg = regs.vrcr; 3542566SN/A break; 3552566SN/A 3562566SN/A case VTCR: 3572566SN/A reg = regs.vtcr; 3582566SN/A break; 3592566SN/A 3602566SN/A case VDR: 3612566SN/A reg = regs.vdr; 3622566SN/A break; 3632566SN/A 3642566SN/A case CCSR: 3652566SN/A reg = regs.ccsr; 3662566SN/A break; 3672566SN/A 3682566SN/A case TBICR: 3692566SN/A reg = regs.tbicr; 3702566SN/A break; 3712566SN/A 3722566SN/A case TBISR: 3732566SN/A reg = regs.tbisr; 3742566SN/A break; 3752566SN/A 3762566SN/A case TANAR: 3772566SN/A reg = regs.tanar; 3782566SN/A break; 3792566SN/A 3802566SN/A case TANLPAR: 3812566SN/A reg = regs.tanlpar; 3822566SN/A break; 3832566SN/A 3842566SN/A case TANER: 3852566SN/A reg = regs.taner; 3862566SN/A break; 3872566SN/A 3882566SN/A case TESR: 3892566SN/A reg = regs.tesr; 3902566SN/A break; 3912566SN/A 3922566SN/A case M5REG: 3932566SN/A reg = 0; 3942566SN/A if (params()->rx_thread) 3952566SN/A reg |= M5REG_RX_THREAD; 3962566SN/A if (params()->tx_thread) 3972566SN/A reg |= M5REG_TX_THREAD; 3982566SN/A if (params()->rss) 3992566SN/A reg |= M5REG_RSS; 4002566SN/A break; 4012566SN/A 4022566SN/A default: 4032566SN/A panic("reading unimplemented register: addr=%#x", daddr); 404837SN/A } 4052566SN/A 4062566SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 4072566SN/A daddr, reg, reg); 4082566SN/A 4094870SN/A pkt->makeAtomicResponse(); 4102566SN/A return pioDelay; 411837SN/A} 412837SN/A 4132566SN/ATick 4143349SN/ANSGigE::write(PacketPtr pkt) 415837SN/A{ 416927SN/A assert(ioEnable); 417917SN/A 4182641SN/A Addr daddr = pkt->getAddr() & 0xfff; 4192566SN/A DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 4202641SN/A daddr, pkt->getAddr(), pkt->getSize()); 4212630SN/A 422854SN/A if (daddr > LAST && daddr <= RESERVED) { 423837SN/A panic("Accessing reserved register"); 424854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 4252846SN/A return writeConfig(pkt); 426854SN/A } else if (daddr > 0x3FC) 427854SN/A panic("Something is messed up!\n"); 428837SN/A 4292641SN/A if (pkt->getSize() == sizeof(uint32_t)) { 43013342Sgabeblack@google.com uint32_t reg = pkt->getLE<uint32_t>(); 4311848SN/A uint16_t rfaddr; 4321848SN/A 433854SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 434837SN/A 435837SN/A switch (daddr) { 436837SN/A case CR: 437837SN/A regs.command = reg; 4381035SN/A if (reg & CR_TXD) { 4391035SN/A txEnable = false; 440837SN/A } else if (reg & CR_TXE) { 4412126SN/A txEnable = true; 4422126SN/A 4432126SN/A // the kernel is enabling the transmit machine 4442126SN/A if (txState == txIdle) 4452126SN/A txKick(); 446837SN/A } 447837SN/A 4481035SN/A if (reg & CR_RXD) { 4491035SN/A rxEnable = false; 450837SN/A } else if (reg & CR_RXE) { 4512126SN/A rxEnable = true; 4522126SN/A 4532126SN/A if (rxState == rxIdle) 4542126SN/A rxKick(); 455837SN/A } 456837SN/A 457837SN/A if (reg & CR_TXR) 458837SN/A txReset(); 459837SN/A 460837SN/A if (reg & CR_RXR) 461837SN/A rxReset(); 462837SN/A 463837SN/A if (reg & CR_SWI) 464837SN/A devIntrPost(ISR_SWI); 465837SN/A 466837SN/A if (reg & CR_RST) { 467837SN/A txReset(); 468837SN/A rxReset(); 469854SN/A 470837SN/A regsReset(); 471837SN/A } 472837SN/A break; 473837SN/A 4741690SN/A case CFGR: 4751690SN/A if (reg & CFGR_LNKSTS || 4761690SN/A reg & CFGR_SPDSTS || 4771690SN/A reg & CFGR_DUPSTS || 4781690SN/A reg & CFGR_RESERVED || 4791690SN/A reg & CFGR_T64ADDR || 4808726SN/A reg & CFGR_PCI64_DET) { 4818726SN/A // First clear all writable bits 4828726SN/A regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4838726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4848726SN/A CFGR_PCI64_DET; 4858726SN/A // Now set the appropriate writable bits 4868726SN/A regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4878726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4888726SN/A CFGR_PCI64_DET); 4898726SN/A } 4901027SN/A 4911027SN/A// all these #if 0's are because i don't THINK the kernel needs to 4921027SN/A// have these implemented. if there is a problem relating to one of 4931027SN/A// these, you may need to add functionality in. 4948737SN/A 4958737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy 4968737SN/A#if 0 4971690SN/A if (reg & CFGR_TBI_EN) ; 4981690SN/A if (reg & CFGR_MODE_1000) ; 499837SN/A 5001690SN/A if (reg & CFGR_PINT_DUPSTS || 5011690SN/A reg & CFGR_PINT_LNKSTS || 5021690SN/A reg & CFGR_PINT_SPDSTS) 5031027SN/A ; 5041027SN/A 5051690SN/A if (reg & CFGR_TMRTEST) ; 5061690SN/A if (reg & CFGR_MRM_DIS) ; 5071690SN/A if (reg & CFGR_MWI_DIS) ; 5081690SN/A 5091690SN/A if (reg & CFGR_DATA64_EN) ; 5101690SN/A if (reg & CFGR_M64ADDR) ; 5111690SN/A if (reg & CFGR_PHY_RST) ; 5121690SN/A if (reg & CFGR_PHY_DIS) ; 513837SN/A 5141909SN/A if (reg & CFGR_REQALG) ; 5151909SN/A if (reg & CFGR_SB) ; 5161909SN/A if (reg & CFGR_POW) ; 5171909SN/A if (reg & CFGR_EXD) ; 5181909SN/A if (reg & CFGR_PESEL) ; 5191909SN/A if (reg & CFGR_BROM_DIS) ; 5201909SN/A if (reg & CFGR_EXT_125) ; 5211909SN/A if (reg & CFGR_BEM) ; 5228737SN/A 5238737SN/A if (reg & CFGR_T64ADDR) ; 5248737SN/A // panic("CFGR_T64ADDR is read only register!\n"); 5258737SN/A#endif 5268737SN/A if (reg & CFGR_AUTO_1000) 5278737SN/A panic("CFGR_AUTO_1000 not implemented!\n"); 5288737SN/A 5298737SN/A if (reg & CFGR_PCI64_DET) 5308737SN/A panic("CFGR_PCI64_DET is read only register!\n"); 5318737SN/A 5328737SN/A if (reg & CFGR_EXTSTS_EN) 5338737SN/A extstsEnable = true; 5348737SN/A else 5358737SN/A extstsEnable = false; 536837SN/A break; 537837SN/A 538837SN/A case MEAR: 5391843SN/A // Clear writable bits 5401843SN/A regs.mear &= MEAR_EEDO; 5411843SN/A // Set appropriate writable bits 5421843SN/A regs.mear |= reg & ~MEAR_EEDO; 5431843SN/A 5441843SN/A // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 5451843SN/A // even though it could get it through RFDR 5461843SN/A if (reg & MEAR_EESEL) { 5471843SN/A // Rising edge of clock 5481843SN/A if (reg & MEAR_EECLK && !eepromClk) 5491843SN/A eepromKick(); 5501843SN/A } 5511843SN/A else { 5521843SN/A eepromState = eepromStart; 5531843SN/A regs.mear &= ~MEAR_EEDI; 5541843SN/A } 5551843SN/A 5561843SN/A eepromClk = reg & MEAR_EECLK; 5571843SN/A 5581027SN/A // since phy is completely faked, MEAR_MD* don't matter 5598737SN/A 5608737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy 5618737SN/A#if 0 562837SN/A if (reg & MEAR_MDIO) ; 563837SN/A if (reg & MEAR_MDDIR) ; 564837SN/A if (reg & MEAR_MDC) ; 5658737SN/A#endif 566837SN/A break; 567837SN/A 568837SN/A case PTSCR: 569854SN/A regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 5701027SN/A // these control BISTs for various parts of chip - we 5711027SN/A // don't care or do just fake that the BIST is done 572854SN/A if (reg & PTSCR_RBIST_EN) 573854SN/A regs.ptscr |= PTSCR_RBIST_DONE; 574854SN/A if (reg & PTSCR_EEBIST_EN) 575854SN/A regs.ptscr &= ~PTSCR_EEBIST_EN; 576854SN/A if (reg & PTSCR_EELOAD_EN) 577854SN/A regs.ptscr &= ~PTSCR_EELOAD_EN; 578837SN/A break; 579837SN/A 580837SN/A case ISR: /* writing to the ISR has no effect */ 581837SN/A panic("ISR is a read only register!\n"); 582837SN/A 583837SN/A case IMR: 584837SN/A regs.imr = reg; 585837SN/A devIntrChangeMask(); 586837SN/A break; 587837SN/A 588837SN/A case IER: 589837SN/A regs.ier = reg; 590837SN/A break; 591837SN/A 592837SN/A case IHR: 593837SN/A regs.ihr = reg; 594837SN/A /* not going to implement real interrupt holdoff */ 595837SN/A break; 596837SN/A 597837SN/A case TXDP: 598837SN/A regs.txdp = (reg & 0xFFFFFFFC); 599837SN/A assert(txState == txIdle); 600837SN/A CTDD = false; 601837SN/A break; 602837SN/A 603837SN/A case TXDP_HI: 604837SN/A regs.txdp_hi = reg; 605837SN/A break; 606837SN/A 6071690SN/A case TX_CFG: 608837SN/A regs.txcfg = reg; 609837SN/A#if 0 6101690SN/A if (reg & TX_CFG_CSI) ; 6111690SN/A if (reg & TX_CFG_HBI) ; 6121690SN/A if (reg & TX_CFG_MLB) ; 6131690SN/A if (reg & TX_CFG_ATP) ; 6141690SN/A if (reg & TX_CFG_ECRETRY) { 6151027SN/A /* 6161027SN/A * this could easily be implemented, but considering 6171027SN/A * the network is just a fake pipe, wouldn't make 6181027SN/A * sense to do this 6191027SN/A */ 6201027SN/A } 621837SN/A 6221690SN/A if (reg & TX_CFG_BRST_DIS) ; 623837SN/A#endif 624837SN/A 6251027SN/A#if 0 626854SN/A /* we handle our own DMA, ignore the kernel's exhortations */ 6271690SN/A if (reg & TX_CFG_MXDMA) ; 6281027SN/A#endif 6291027SN/A 6301027SN/A // also, we currently don't care about fill/drain 6311027SN/A // thresholds though this may change in the future with 6321027SN/A // more realistic networks or a driver which changes it 6331027SN/A // according to feedback 634837SN/A 635837SN/A break; 636837SN/A 637837SN/A case GPIOR: 6381843SN/A // Only write writable bits 6391843SN/A regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 6401843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 6411843SN/A regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 6421843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 643837SN/A /* these just control general purpose i/o pins, don't matter */ 644837SN/A break; 645837SN/A 646854SN/A case RXDP: 647854SN/A regs.rxdp = reg; 6481035SN/A CRDD = false; 649854SN/A break; 650854SN/A 651854SN/A case RXDP_HI: 652854SN/A regs.rxdp_hi = reg; 653854SN/A break; 654854SN/A 6551690SN/A case RX_CFG: 656837SN/A regs.rxcfg = reg; 657837SN/A#if 0 6581690SN/A if (reg & RX_CFG_AEP) ; 6591690SN/A if (reg & RX_CFG_ARP) ; 6601690SN/A if (reg & RX_CFG_STRIPCRC) ; 6611690SN/A if (reg & RX_CFG_RX_RD) ; 6621690SN/A if (reg & RX_CFG_ALP) ; 6631690SN/A if (reg & RX_CFG_AIRL) ; 664837SN/A 665854SN/A /* we handle our own DMA, ignore what kernel says about it */ 6661690SN/A if (reg & RX_CFG_MXDMA) ; 6671027SN/A 668927SN/A //also, we currently don't care about fill/drain thresholds 669927SN/A //though this may change in the future with more realistic 670927SN/A //networks or a driver which changes it according to feedback 6711690SN/A if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 672837SN/A#endif 673837SN/A break; 674837SN/A 675837SN/A case PQCR: 676837SN/A /* there is no priority queueing used in the linux 2.6 driver */ 677837SN/A regs.pqcr = reg; 678837SN/A break; 679837SN/A 680837SN/A case WCSR: 681837SN/A /* not going to implement wake on LAN */ 682837SN/A regs.wcsr = reg; 683837SN/A break; 684837SN/A 685837SN/A case PCR: 686837SN/A /* not going to implement pause control */ 687837SN/A regs.pcr = reg; 688837SN/A break; 689837SN/A 690837SN/A case RFCR: 691837SN/A regs.rfcr = reg; 692854SN/A 693837SN/A rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 694837SN/A acceptBroadcast = (reg & RFCR_AAB) ? true : false; 695837SN/A acceptMulticast = (reg & RFCR_AAM) ? true : false; 696837SN/A acceptUnicast = (reg & RFCR_AAU) ? true : false; 697837SN/A acceptPerfect = (reg & RFCR_APM) ? true : false; 698837SN/A acceptArp = (reg & RFCR_AARP) ? true : false; 6991843SN/A multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 700837SN/A 7011027SN/A#if 0 7021027SN/A if (reg & RFCR_APAT) 7031027SN/A panic("RFCR_APAT not implemented!\n"); 7041027SN/A#endif 7051843SN/A if (reg & RFCR_UHEN) 7061843SN/A panic("Unicast hash filtering not used by drivers!\n"); 707837SN/A 708837SN/A if (reg & RFCR_ULM) 709837SN/A panic("RFCR_ULM not implemented!\n"); 710837SN/A 711837SN/A break; 712837SN/A 713837SN/A case RFDR: 7141848SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 7151843SN/A switch (rfaddr) { 7161843SN/A case 0x000: 7171843SN/A rom.perfectMatch[0] = (uint8_t)reg; 7181843SN/A rom.perfectMatch[1] = (uint8_t)(reg >> 8); 7191843SN/A break; 7201843SN/A case 0x002: 7211843SN/A rom.perfectMatch[2] = (uint8_t)reg; 7221843SN/A rom.perfectMatch[3] = (uint8_t)(reg >> 8); 7231843SN/A break; 7241843SN/A case 0x004: 7251843SN/A rom.perfectMatch[4] = (uint8_t)reg; 7261843SN/A rom.perfectMatch[5] = (uint8_t)(reg >> 8); 7271843SN/A break; 7281843SN/A default: 7291843SN/A 7301843SN/A if (rfaddr >= FHASH_ADDR && 7311843SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 7321843SN/A 7331843SN/A // Only word-aligned writes supported 7341843SN/A if (rfaddr % 2) 7351843SN/A panic("unaligned write to filter hash table!"); 7361843SN/A 7371843SN/A rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 7381843SN/A rom.filterHash[rfaddr - FHASH_ADDR + 1] 7391843SN/A = (uint8_t)(reg >> 8); 7401843SN/A break; 7411843SN/A } 74210367SN/A panic("writing RFDR for something other than pattern matching " 74310367SN/A "or hashing! %#x\n", rfaddr); 7441843SN/A } 74512561Ssiddhesh.poyarekar@gmail.com break; 746837SN/A 747837SN/A case BRAR: 7481843SN/A regs.brar = reg; 7491843SN/A break; 750837SN/A 751837SN/A case BRDR: 752837SN/A panic("the driver never uses BRDR, something is wrong!\n"); 753837SN/A 754837SN/A case SRR: 755837SN/A panic("SRR is read only register!\n"); 756837SN/A 757837SN/A case MIBC: 758837SN/A panic("the driver never uses MIBC, something is wrong!\n"); 759837SN/A 760837SN/A case VRCR: 761837SN/A regs.vrcr = reg; 762837SN/A break; 763837SN/A 764837SN/A case VTCR: 765837SN/A regs.vtcr = reg; 766837SN/A break; 767837SN/A 768837SN/A case VDR: 769837SN/A panic("the driver never uses VDR, something is wrong!\n"); 770837SN/A 771837SN/A case CCSR: 772837SN/A /* not going to implement clockrun stuff */ 773837SN/A regs.ccsr = reg; 774837SN/A break; 775837SN/A 776837SN/A case TBICR: 777837SN/A regs.tbicr = reg; 778837SN/A if (reg & TBICR_MR_LOOPBACK) 779837SN/A panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 780837SN/A 781837SN/A if (reg & TBICR_MR_AN_ENABLE) { 782837SN/A regs.tanlpar = regs.tanar; 783837SN/A regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 784837SN/A } 785837SN/A 786837SN/A#if 0 787837SN/A if (reg & TBICR_MR_RESTART_AN) ; 788837SN/A#endif 789837SN/A 790837SN/A break; 791837SN/A 792837SN/A case TBISR: 793837SN/A panic("TBISR is read only register!\n"); 794837SN/A 795837SN/A case TANAR: 7961843SN/A // Only write the writable bits 7971843SN/A regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 7981843SN/A regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 7991843SN/A 8001843SN/A // Pause capability unimplemented 8011843SN/A#if 0 8021843SN/A if (reg & TANAR_PS2) ; 8031843SN/A if (reg & TANAR_PS1) ; 8041843SN/A#endif 8051843SN/A 806837SN/A break; 807837SN/A 808837SN/A case TANLPAR: 809837SN/A panic("this should only be written to by the fake phy!\n"); 810837SN/A 811837SN/A case TANER: 812837SN/A panic("TANER is read only register!\n"); 813837SN/A 814837SN/A case TESR: 815837SN/A regs.tesr = reg; 816837SN/A break; 817837SN/A 818837SN/A default: 8191027SN/A panic("invalid register access daddr=%#x", daddr); 820837SN/A } 8211027SN/A } else { 822837SN/A panic("Invalid Request Size"); 8231027SN/A } 8244870SN/A pkt->makeAtomicResponse(); 8252566SN/A return pioDelay; 826837SN/A} 827837SN/A 828837SN/Avoid 829879SN/ANSGigE::devIntrPost(uint32_t interrupts) 830837SN/A{ 831854SN/A if (interrupts & ISR_RESERVE) 832854SN/A panic("Cannot set a reserved interrupt"); 833837SN/A 8341057SN/A if (interrupts & ISR_NOIMPL) 8351057SN/A warn("interrupt not implemented %#x\n", interrupts); 8361057SN/A 8371883SN/A interrupts &= ISR_IMPL; 8381057SN/A regs.isr |= interrupts; 8391057SN/A 8401263SN/A if (interrupts & regs.imr) { 8411263SN/A if (interrupts & ISR_SWI) { 8421263SN/A totalSwi++; 8431263SN/A } 8441263SN/A if (interrupts & ISR_RXIDLE) { 8451263SN/A totalRxIdle++; 8461263SN/A } 8471263SN/A if (interrupts & ISR_RXOK) { 8481263SN/A totalRxOk++; 8491263SN/A } 8501263SN/A if (interrupts & ISR_RXDESC) { 8511263SN/A totalRxDesc++; 8521263SN/A } 8531263SN/A if (interrupts & ISR_TXOK) { 8541263SN/A totalTxOk++; 8551263SN/A } 8561263SN/A if (interrupts & ISR_TXIDLE) { 8571263SN/A totalTxIdle++; 8581263SN/A } 8591263SN/A if (interrupts & ISR_TXDESC) { 8601263SN/A totalTxDesc++; 8611263SN/A } 8621263SN/A if (interrupts & ISR_RXORN) { 8631263SN/A totalRxOrn++; 8641263SN/A } 8651263SN/A } 8661263SN/A 8671057SN/A DPRINTF(EthernetIntr, 8681057SN/A "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 8691057SN/A interrupts, regs.isr, regs.imr); 870837SN/A 871854SN/A if ((regs.isr & regs.imr)) { 8727823SN/A Tick when = curTick(); 8731883SN/A if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 874854SN/A when += intrDelay; 8755485SN/A postedInterrupts++; 876854SN/A cpuIntrPost(when); 877854SN/A } 878837SN/A} 879837SN/A 8801263SN/A/* writing this interrupt counting stats inside this means that this function 8811263SN/A is now limited to being used to clear all interrupts upon the kernel 8821263SN/A reading isr and servicing. just telling you in case you were thinking 8831263SN/A of expanding use. 8841263SN/A*/ 885837SN/Avoid 886879SN/ANSGigE::devIntrClear(uint32_t interrupts) 887837SN/A{ 888837SN/A if (interrupts & ISR_RESERVE) 889837SN/A panic("Cannot clear a reserved interrupt"); 890837SN/A 8911263SN/A if (regs.isr & regs.imr & ISR_SWI) { 8921263SN/A postedSwi++; 8931263SN/A } 8941263SN/A if (regs.isr & regs.imr & ISR_RXIDLE) { 8951263SN/A postedRxIdle++; 8961263SN/A } 8971263SN/A if (regs.isr & regs.imr & ISR_RXOK) { 8981263SN/A postedRxOk++; 8991263SN/A } 9001263SN/A if (regs.isr & regs.imr & ISR_RXDESC) { 9011263SN/A postedRxDesc++; 9021263SN/A } 9031263SN/A if (regs.isr & regs.imr & ISR_TXOK) { 9041263SN/A postedTxOk++; 9051263SN/A } 9061263SN/A if (regs.isr & regs.imr & ISR_TXIDLE) { 9071263SN/A postedTxIdle++; 9081263SN/A } 9091263SN/A if (regs.isr & regs.imr & ISR_TXDESC) { 9101263SN/A postedTxDesc++; 9111263SN/A } 9121263SN/A if (regs.isr & regs.imr & ISR_RXORN) { 9131263SN/A postedRxOrn++; 9141263SN/A } 9151263SN/A 9161057SN/A interrupts &= ~ISR_NOIMPL; 9171057SN/A regs.isr &= ~interrupts; 918837SN/A 9191027SN/A DPRINTF(EthernetIntr, 9201027SN/A "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 921881SN/A interrupts, regs.isr, regs.imr); 9221036SN/A 9231036SN/A if (!(regs.isr & regs.imr)) 9241036SN/A cpuIntrClear(); 925837SN/A} 926837SN/A 927837SN/Avoid 928879SN/ANSGigE::devIntrChangeMask() 929837SN/A{ 9301036SN/A DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 9311036SN/A regs.isr, regs.imr, regs.isr & regs.imr); 932837SN/A 933837SN/A if (regs.isr & regs.imr) 9347823SN/A cpuIntrPost(curTick()); 935837SN/A else 936837SN/A cpuIntrClear(); 937837SN/A} 938837SN/A 939837SN/Avoid 940879SN/ANSGigE::cpuIntrPost(Tick when) 941837SN/A{ 9421027SN/A // If the interrupt you want to post is later than an interrupt 9431027SN/A // already scheduled, just let it post in the coming one and don't 9441027SN/A // schedule another. 9451027SN/A // HOWEVER, must be sure that the scheduled intrTick is in the 9461027SN/A // future (this was formerly the source of a bug) 9471035SN/A /** 9481035SN/A * @todo this warning should be removed and the intrTick code should 9491035SN/A * be fixed. 9501035SN/A */ 9517823SN/A assert(when >= curTick()); 9527823SN/A assert(intrTick >= curTick() || intrTick == 0); 9531072SN/A if (when > intrTick && intrTick != 0) { 9541072SN/A DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 9551072SN/A intrTick); 9561072SN/A return; 9571035SN/A } 958854SN/A 959854SN/A intrTick = when; 9607823SN/A if (intrTick < curTick()) { 9617823SN/A intrTick = curTick(); 9621072SN/A } 9631072SN/A 9641072SN/A DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 9651072SN/A intrTick); 9661072SN/A 9671072SN/A if (intrEvent) 968854SN/A intrEvent->squash(); 96912087Sspwilson2@wisc.edu 97012087Sspwilson2@wisc.edu intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); }, 97112087Sspwilson2@wisc.edu name(), true); 9725606SN/A schedule(intrEvent, intrTick); 973854SN/A} 974854SN/A 975854SN/Avoid 976879SN/ANSGigE::cpuInterrupt() 977854SN/A{ 9787823SN/A assert(intrTick == curTick()); 9791072SN/A 9801072SN/A // Whether or not there's a pending interrupt, we don't care about 9811072SN/A // it anymore 9821072SN/A intrEvent = 0; 9831072SN/A intrTick = 0; 9841072SN/A 985854SN/A // Don't send an interrupt if there's already one 986927SN/A if (cpuPendingIntr) { 987927SN/A DPRINTF(EthernetIntr, 988927SN/A "would send an interrupt now, but there's already pending\n"); 9891072SN/A } else { 9901072SN/A // Send interrupt 9911072SN/A cpuPendingIntr = true; 9921072SN/A 9931149SN/A DPRINTF(EthernetIntr, "posting interrupt\n"); 9941149SN/A intrPost(); 995927SN/A } 996837SN/A} 997837SN/A 998837SN/Avoid 999879SN/ANSGigE::cpuIntrClear() 1000837SN/A{ 10011027SN/A if (!cpuPendingIntr) 10021027SN/A return; 10031027SN/A 10041072SN/A if (intrEvent) { 10051072SN/A intrEvent->squash(); 10061072SN/A intrEvent = 0; 10071072SN/A } 10081072SN/A 10091072SN/A intrTick = 0; 10101072SN/A 10111027SN/A cpuPendingIntr = false; 10121057SN/A 10131149SN/A DPRINTF(EthernetIntr, "clearing interrupt\n"); 10141149SN/A intrClear(); 1015837SN/A} 1016837SN/A 1017837SN/Abool 1018879SN/ANSGigE::cpuIntrPending() const 1019837SN/A{ return cpuPendingIntr; } 1020837SN/A 1021837SN/Avoid 1022879SN/ANSGigE::txReset() 1023837SN/A{ 1024837SN/A 1025837SN/A DPRINTF(Ethernet, "transmit reset\n"); 1026837SN/A 1027837SN/A CTDD = false; 10281035SN/A txEnable = false;; 1029854SN/A txFragPtr = 0; 1030854SN/A assert(txDescCnt == 0); 1031837SN/A txFifo.clear(); 1032837SN/A txState = txIdle; 1033854SN/A assert(txDmaState == dmaIdle); 1034837SN/A} 1035837SN/A 1036837SN/Avoid 1037879SN/ANSGigE::rxReset() 1038837SN/A{ 1039837SN/A DPRINTF(Ethernet, "receive reset\n"); 1040837SN/A 1041837SN/A CRDD = false; 1042854SN/A assert(rxPktBytes == 0); 10431035SN/A rxEnable = false; 1044854SN/A rxFragPtr = 0; 1045854SN/A assert(rxDescCnt == 0); 1046854SN/A assert(rxDmaState == dmaIdle); 1047837SN/A rxFifo.clear(); 1048837SN/A rxState = rxIdle; 1049837SN/A} 1050837SN/A 10511036SN/Avoid 10521036SN/ANSGigE::regsReset() 1053915SN/A{ 1054915SN/A memset(®s, 0, sizeof(regs)); 10551817SN/A regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 10561843SN/A regs.mear = 0x12; 10571057SN/A regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 10581057SN/A // fill threshold to 32 bytes 10591057SN/A regs.rxcfg = 0x4; // set drain threshold to 16 bytes 10601057SN/A regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 10611057SN/A regs.mibc = MIBC_FRZ; 10621057SN/A regs.vdr = 0x81; // set the vlan tag type to 802.1q 10631057SN/A regs.tesr = 0xc000; // TBI capable of both full and half duplex 10641843SN/A regs.brar = 0xffffffff; 1065927SN/A 1066927SN/A extstsEnable = false; 1067927SN/A acceptBroadcast = false; 1068927SN/A acceptMulticast = false; 1069927SN/A acceptUnicast = false; 1070927SN/A acceptPerfect = false; 1071927SN/A acceptArp = false; 1072915SN/A} 1073915SN/A 1074854SN/Abool 1075879SN/ANSGigE::doRxDmaRead() 1076854SN/A{ 1077854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1078854SN/A rxDmaState = dmaReading; 1079854SN/A 108010913SN/A if (dmaPending() || drainState() != DrainState::Running) 10812566SN/A rxDmaState = dmaReadWaiting; 10822566SN/A else 10832566SN/A dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 10842566SN/A 1085854SN/A return true; 1086854SN/A} 1087854SN/A 1088854SN/Avoid 1089879SN/ANSGigE::rxDmaReadDone() 1090854SN/A{ 1091854SN/A assert(rxDmaState == dmaReading); 10922566SN/A rxDmaState = dmaIdle; 10932566SN/A 10942566SN/A DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 10952566SN/A rxDmaAddr, rxDmaLen); 10962566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1097854SN/A 1098854SN/A // If the transmit state machine has a pending DMA, let it go first 1099854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1100854SN/A txKick(); 1101854SN/A 1102854SN/A rxKick(); 1103854SN/A} 1104854SN/A 1105854SN/Abool 1106879SN/ANSGigE::doRxDmaWrite() 1107854SN/A{ 1108854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1109854SN/A rxDmaState = dmaWriting; 1110854SN/A 111110913SN/A if (dmaPending() || drainState() != DrainState::Running) 11122566SN/A rxDmaState = dmaWriteWaiting; 11132566SN/A else 11142566SN/A dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 1115854SN/A return true; 1116854SN/A} 1117854SN/A 1118854SN/Avoid 1119879SN/ANSGigE::rxDmaWriteDone() 1120854SN/A{ 1121854SN/A assert(rxDmaState == dmaWriting); 11222566SN/A rxDmaState = dmaIdle; 11232566SN/A 11242566SN/A DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 11252566SN/A rxDmaAddr, rxDmaLen); 11262566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1127854SN/A 1128854SN/A // If the transmit state machine has a pending DMA, let it go first 1129854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1130854SN/A txKick(); 1131854SN/A 1132854SN/A rxKick(); 1133837SN/A} 1134837SN/A 1135837SN/Avoid 1136879SN/ANSGigE::rxKick() 1137837SN/A{ 11381909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 11391909SN/A 11401909SN/A DPRINTF(EthernetSM, 11411909SN/A "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 11421909SN/A NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 11431909SN/A 11441909SN/A Addr link, bufptr; 11451909SN/A uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 11461909SN/A uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1147837SN/A 11481801SN/A next: 11499417SN/A if (rxKickTick > curTick()) { 11509417SN/A DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 11519417SN/A rxKickTick); 11521801SN/A 11539417SN/A goto exit; 11549417SN/A } 11551801SN/A 11569417SN/A // Go to the next state machine clock tick. 11579417SN/A rxKickTick = clockEdge(Cycles(1)); 1158837SN/A 1159854SN/A switch(rxDmaState) { 1160854SN/A case dmaReadWaiting: 1161854SN/A if (doRxDmaRead()) 1162854SN/A goto exit; 1163854SN/A break; 1164854SN/A case dmaWriteWaiting: 1165854SN/A if (doRxDmaWrite()) 1166854SN/A goto exit; 1167854SN/A break; 1168854SN/A default: 1169854SN/A break; 1170854SN/A } 1171837SN/A 11721909SN/A link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 11731909SN/A bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 11741909SN/A 1175855SN/A // see state machine from spec for details 11761027SN/A // the way this works is, if you finish work on one state and can 11771027SN/A // go directly to another, you do that through jumping to the 11781027SN/A // label "next". however, if you have intermediate work, like DMA 11791027SN/A // so that you can't go to the next state yet, you go to exit and 11801027SN/A // exit the loop. however, when the DMA is done it will trigger 11811027SN/A // an event and come back to this loop. 1182854SN/A switch (rxState) { 1183854SN/A case rxIdle: 11841035SN/A if (!rxEnable) { 1185927SN/A DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1186854SN/A goto exit; 1187854SN/A } 1188837SN/A 1189854SN/A if (CRDD) { 1190854SN/A rxState = rxDescRefr; 1191837SN/A 1192854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 11931909SN/A rxDmaData = 11941909SN/A is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 11951909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1196854SN/A rxDmaFree = dmaDescFree; 1197854SN/A 1198961SN/A descDmaReads++; 1199961SN/A descDmaRdBytes += rxDmaLen; 1200961SN/A 1201854SN/A if (doRxDmaRead()) 1202854SN/A goto exit; 1203837SN/A } else { 1204837SN/A rxState = rxDescRead; 1205854SN/A 1206854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 12071909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 12081909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1209854SN/A rxDmaFree = dmaDescFree; 1210854SN/A 1211961SN/A descDmaReads++; 1212961SN/A descDmaRdBytes += rxDmaLen; 1213961SN/A 1214854SN/A if (doRxDmaRead()) 1215854SN/A goto exit; 1216837SN/A } 1217854SN/A break; 1218854SN/A 1219854SN/A case rxDescRefr: 1220854SN/A if (rxDmaState != dmaIdle) 1221854SN/A goto exit; 1222854SN/A 1223854SN/A rxState = rxAdvance; 1224854SN/A break; 1225854SN/A 1226854SN/A case rxDescRead: 1227854SN/A if (rxDmaState != dmaIdle) 1228854SN/A goto exit; 1229854SN/A 12301909SN/A DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 12311036SN/A regs.rxdp & 0x3fffffff); 12321036SN/A DPRINTF(EthernetDesc, 12331909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 12341909SN/A link, bufptr, cmdsts, extsts); 12351909SN/A 12361909SN/A if (cmdsts & CMDSTS_OWN) { 12371035SN/A devIntrPost(ISR_RXIDLE); 1238837SN/A rxState = rxIdle; 12391035SN/A goto exit; 1240837SN/A } else { 1241837SN/A rxState = rxFifoBlock; 12421909SN/A rxFragPtr = bufptr; 12431909SN/A rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1244854SN/A } 1245854SN/A break; 1246837SN/A 1247854SN/A case rxFifoBlock: 1248854SN/A if (!rxPacket) { 1249854SN/A /** 1250854SN/A * @todo in reality, we should be able to start processing 1251854SN/A * the packet as it arrives, and not have to wait for the 1252854SN/A * full packet ot be in the receive fifo. 1253854SN/A */ 1254854SN/A if (rxFifo.empty()) 1255854SN/A goto exit; 1256854SN/A 12571036SN/A DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1258927SN/A 1259854SN/A // If we don't have a packet, grab a new one from the fifo. 1260854SN/A rxPacket = rxFifo.front(); 1261854SN/A rxPktBytes = rxPacket->length; 1262854SN/A rxPacketBufPtr = rxPacket->data; 1263854SN/A 12641011SN/A#if TRACING_ON 1265927SN/A if (DTRACE(Ethernet)) { 12661114SN/A IpPtr ip(rxPacket); 12671078SN/A if (ip) { 12681078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 12691114SN/A TcpPtr tcp(ip); 12701078SN/A if (tcp) { 12711561SN/A DPRINTF(Ethernet, 12721561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 12731561SN/A tcp->sport(), tcp->dport(), tcp->seq(), 12741561SN/A tcp->ack()); 1275927SN/A } 1276927SN/A } 1277927SN/A } 12781011SN/A#endif 1279927SN/A 1280854SN/A // sanity check - i think the driver behaves like this 1281854SN/A assert(rxDescCnt >= rxPktBytes); 12821154SN/A rxFifo.pop(); 1283837SN/A } 1284837SN/A 1285837SN/A 12861027SN/A // dont' need the && rxDescCnt > 0 if driver sanity check 12871027SN/A // above holds 1288854SN/A if (rxPktBytes > 0) { 1289854SN/A rxState = rxFragWrite; 12901027SN/A // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 12911027SN/A // check holds 1292854SN/A rxXferLen = rxPktBytes; 1293854SN/A 1294854SN/A rxDmaAddr = rxFragPtr & 0x3fffffff; 1295854SN/A rxDmaData = rxPacketBufPtr; 1296854SN/A rxDmaLen = rxXferLen; 1297854SN/A rxDmaFree = dmaDataFree; 1298854SN/A 1299854SN/A if (doRxDmaWrite()) 1300854SN/A goto exit; 1301854SN/A 1302837SN/A } else { 1303854SN/A rxState = rxDescWrite; 1304837SN/A 1305854SN/A //if (rxPktBytes == 0) { /* packet is done */ 1306854SN/A assert(rxPktBytes == 0); 1307927SN/A DPRINTF(EthernetSM, "done with receiving packet\n"); 1308837SN/A 13091909SN/A cmdsts |= CMDSTS_OWN; 13101909SN/A cmdsts &= ~CMDSTS_MORE; 13111909SN/A cmdsts |= CMDSTS_OK; 13121909SN/A cmdsts &= 0xffff0000; 13131909SN/A cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1314837SN/A 1315854SN/A#if 0 13161027SN/A /* 13171027SN/A * all the driver uses these are for its own stats keeping 13181027SN/A * which we don't care about, aren't necessary for 13191027SN/A * functionality and doing this would just slow us down. 13201027SN/A * if they end up using this in a later version for 13211027SN/A * functional purposes, just undef 13221027SN/A */ 1323837SN/A if (rxFilterEnable) { 13241909SN/A cmdsts &= ~CMDSTS_DEST_MASK; 13251114SN/A const EthAddr &dst = rxFifoFront()->dst(); 13261114SN/A if (dst->unicast()) 13271909SN/A cmdsts |= CMDSTS_DEST_SELF; 13281114SN/A if (dst->multicast()) 13291909SN/A cmdsts |= CMDSTS_DEST_MULTI; 13301114SN/A if (dst->broadcast()) 13311909SN/A cmdsts |= CMDSTS_DEST_MASK; 1332837SN/A } 1333854SN/A#endif 1334837SN/A 13351114SN/A IpPtr ip(rxPacket); 13361114SN/A if (extstsEnable && ip) { 13371909SN/A extsts |= EXTSTS_IPPKT; 13381078SN/A rxIpChecksums++; 13391114SN/A if (cksum(ip) != 0) { 1340927SN/A DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 13411909SN/A extsts |= EXTSTS_IPERR; 1342927SN/A } 13431114SN/A TcpPtr tcp(ip); 13441114SN/A UdpPtr udp(ip); 13451114SN/A if (tcp) { 13461909SN/A extsts |= EXTSTS_TCPPKT; 13471078SN/A rxTcpChecksums++; 13481114SN/A if (cksum(tcp) != 0) { 1349927SN/A DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 13501909SN/A extsts |= EXTSTS_TCPERR; 1351961SN/A 1352927SN/A } 13531114SN/A } else if (udp) { 13541909SN/A extsts |= EXTSTS_UDPPKT; 13551078SN/A rxUdpChecksums++; 13561114SN/A if (cksum(udp) != 0) { 1357927SN/A DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 13581909SN/A extsts |= EXTSTS_UDPERR; 1359927SN/A } 1360837SN/A } 1361837SN/A } 1362881SN/A rxPacket = 0; 1363881SN/A 13641027SN/A /* 13651027SN/A * the driver seems to always receive into desc buffers 13661027SN/A * of size 1514, so you never have a pkt that is split 13671027SN/A * into multiple descriptors on the receive side, so 13681027SN/A * i don't implement that case, hence the assert above. 13691027SN/A */ 13701027SN/A 13711027SN/A DPRINTF(EthernetDesc, 13721909SN/A "rxDesc: addr=%08x writeback cmdsts extsts\n", 13731036SN/A regs.rxdp & 0x3fffffff); 13741036SN/A DPRINTF(EthernetDesc, 13751909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 13761909SN/A link, bufptr, cmdsts, extsts); 13771909SN/A 13781909SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 13791909SN/A rxDmaData = &cmdsts; 13801909SN/A if (is64bit) { 13811909SN/A rxDmaAddr += offsetof(ns_desc64, cmdsts); 13821909SN/A rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 13831909SN/A } else { 13841909SN/A rxDmaAddr += offsetof(ns_desc32, cmdsts); 13851909SN/A rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 13861909SN/A } 1387854SN/A rxDmaFree = dmaDescFree; 1388854SN/A 1389961SN/A descDmaWrites++; 1390961SN/A descDmaWrBytes += rxDmaLen; 1391961SN/A 1392854SN/A if (doRxDmaWrite()) 1393854SN/A goto exit; 1394837SN/A } 1395854SN/A break; 1396837SN/A 1397854SN/A case rxFragWrite: 1398854SN/A if (rxDmaState != dmaIdle) 1399854SN/A goto exit; 1400854SN/A 1401854SN/A rxPacketBufPtr += rxXferLen; 1402854SN/A rxFragPtr += rxXferLen; 1403854SN/A rxPktBytes -= rxXferLen; 1404854SN/A 1405854SN/A rxState = rxFifoBlock; 1406854SN/A break; 1407854SN/A 1408854SN/A case rxDescWrite: 1409854SN/A if (rxDmaState != dmaIdle) 1410854SN/A goto exit; 1411854SN/A 14121909SN/A assert(cmdsts & CMDSTS_OWN); 1413854SN/A 1414854SN/A assert(rxPacket == 0); 1415854SN/A devIntrPost(ISR_RXOK); 1416854SN/A 14171909SN/A if (cmdsts & CMDSTS_INTR) 1418854SN/A devIntrPost(ISR_RXDESC); 1419854SN/A 14201035SN/A if (!rxEnable) { 1421927SN/A DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1422854SN/A rxState = rxIdle; 14231035SN/A goto exit; 1424854SN/A } else 1425854SN/A rxState = rxAdvance; 1426854SN/A break; 1427854SN/A 1428854SN/A case rxAdvance: 14291909SN/A if (link == 0) { 14301035SN/A devIntrPost(ISR_RXIDLE); 1431854SN/A rxState = rxIdle; 14321035SN/A CRDD = true; 14331035SN/A goto exit; 1434854SN/A } else { 14351893SN/A if (rxDmaState != dmaIdle) 14361893SN/A goto exit; 1437854SN/A rxState = rxDescRead; 14381909SN/A regs.rxdp = link; 1439854SN/A CRDD = false; 1440854SN/A 1441854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 14421909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 14431909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1444854SN/A rxDmaFree = dmaDescFree; 1445854SN/A 1446854SN/A if (doRxDmaRead()) 1447854SN/A goto exit; 1448854SN/A } 1449854SN/A break; 1450854SN/A 1451854SN/A default: 1452854SN/A panic("Invalid rxState!"); 1453837SN/A } 1454837SN/A 14551036SN/A DPRINTF(EthernetSM, "entering next rxState=%s\n", 1456854SN/A NsRxStateStrings[rxState]); 1457854SN/A goto next; 1458837SN/A 1459854SN/A exit: 1460854SN/A /** 1461854SN/A * @todo do we want to schedule a future kick? 1462854SN/A */ 14631036SN/A DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1464854SN/A NsRxStateStrings[rxState]); 14651801SN/A 14669417SN/A if (!rxKickEvent.scheduled()) 14675606SN/A schedule(rxKickEvent, rxKickTick); 1468837SN/A} 1469837SN/A 1470837SN/Avoid 1471879SN/ANSGigE::transmit() 1472837SN/A{ 1473837SN/A if (txFifo.empty()) { 1474837SN/A DPRINTF(Ethernet, "nothing to transmit\n"); 1475837SN/A return; 1476837SN/A } 1477837SN/A 14781036SN/A DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 14791154SN/A txFifo.size()); 1480927SN/A if (interface->sendPacket(txFifo.front())) { 14811011SN/A#if TRACING_ON 1482927SN/A if (DTRACE(Ethernet)) { 14831114SN/A IpPtr ip(txFifo.front()); 14841078SN/A if (ip) { 14851078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 14861114SN/A TcpPtr tcp(ip); 14871078SN/A if (tcp) { 14881561SN/A DPRINTF(Ethernet, 14891561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 14901909SN/A tcp->sport(), tcp->dport(), tcp->seq(), 14911909SN/A tcp->ack()); 1492927SN/A } 1493927SN/A } 1494927SN/A } 14951011SN/A#endif 1496927SN/A 14971561SN/A DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1498837SN/A txBytes += txFifo.front()->length; 1499837SN/A txPackets++; 1500837SN/A 15011027SN/A DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 15021154SN/A txFifo.avail()); 15031154SN/A txFifo.pop(); 1504837SN/A 15051027SN/A /* 15061027SN/A * normally do a writeback of the descriptor here, and ONLY 15071027SN/A * after that is done, send this interrupt. but since our 15081027SN/A * stuff never actually fails, just do this interrupt here, 15091027SN/A * otherwise the code has to stray from this nice format. 15101027SN/A * besides, it's functionally the same. 15111027SN/A */ 1512854SN/A devIntrPost(ISR_TXOK); 15131027SN/A } 1514854SN/A 1515854SN/A if (!txFifo.empty() && !txEvent.scheduled()) { 1516854SN/A DPRINTF(Ethernet, "reschedule transmit\n"); 15177823SN/A schedule(txEvent, curTick() + retryTime); 1518854SN/A } 1519854SN/A} 1520854SN/A 1521854SN/Abool 1522879SN/ANSGigE::doTxDmaRead() 1523854SN/A{ 1524854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1525854SN/A txDmaState = dmaReading; 1526854SN/A 152710913SN/A if (dmaPending() || drainState() != DrainState::Running) 15282566SN/A txDmaState = dmaReadWaiting; 15292566SN/A else 15302566SN/A dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 15312566SN/A 1532854SN/A return true; 1533854SN/A} 1534837SN/A 1535854SN/Avoid 1536879SN/ANSGigE::txDmaReadDone() 1537854SN/A{ 1538854SN/A assert(txDmaState == dmaReading); 15392566SN/A txDmaState = dmaIdle; 15402566SN/A 15412566SN/A DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 15422566SN/A txDmaAddr, txDmaLen); 15432566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1544837SN/A 1545854SN/A // If the receive state machine has a pending DMA, let it go first 1546854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1547854SN/A rxKick(); 1548837SN/A 1549854SN/A txKick(); 1550854SN/A} 1551837SN/A 1552854SN/Abool 1553879SN/ANSGigE::doTxDmaWrite() 1554854SN/A{ 1555854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1556854SN/A txDmaState = dmaWriting; 1557854SN/A 155810913SN/A if (dmaPending() || drainState() != DrainState::Running) 15592566SN/A txDmaState = dmaWriteWaiting; 15602566SN/A else 15612566SN/A dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1562854SN/A return true; 1563854SN/A} 1564854SN/A 1565854SN/Avoid 1566879SN/ANSGigE::txDmaWriteDone() 1567854SN/A{ 1568854SN/A assert(txDmaState == dmaWriting); 15692566SN/A txDmaState = dmaIdle; 15702566SN/A 15712566SN/A DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 15722566SN/A txDmaAddr, txDmaLen); 15732566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1574854SN/A 1575854SN/A // If the receive state machine has a pending DMA, let it go first 1576854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1577854SN/A rxKick(); 1578854SN/A 1579854SN/A txKick(); 1580837SN/A} 1581837SN/A 1582837SN/Avoid 1583879SN/ANSGigE::txKick() 1584837SN/A{ 15851909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 15861909SN/A 15871909SN/A DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 15881909SN/A NsTxStateStrings[txState], is64bit ? 64 : 32); 15891909SN/A 15901909SN/A Addr link, bufptr; 15911909SN/A uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 15921909SN/A uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1593927SN/A 15941801SN/A next: 15959417SN/A if (txKickTick > curTick()) { 15969417SN/A DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 15979417SN/A txKickTick); 15989417SN/A goto exit; 15999417SN/A } 16001801SN/A 16019417SN/A // Go to the next state machine clock tick. 16029417SN/A txKickTick = clockEdge(Cycles(1)); 1603837SN/A 1604854SN/A switch(txDmaState) { 1605854SN/A case dmaReadWaiting: 1606854SN/A if (doTxDmaRead()) 1607854SN/A goto exit; 1608854SN/A break; 1609854SN/A case dmaWriteWaiting: 1610854SN/A if (doTxDmaWrite()) 1611854SN/A goto exit; 1612854SN/A break; 1613854SN/A default: 1614854SN/A break; 1615854SN/A } 1616837SN/A 16171909SN/A link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 16181909SN/A bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1619854SN/A switch (txState) { 1620854SN/A case txIdle: 16211035SN/A if (!txEnable) { 1622927SN/A DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1623854SN/A goto exit; 1624854SN/A } 1625837SN/A 1626854SN/A if (CTDD) { 1627854SN/A txState = txDescRefr; 1628837SN/A 1629881SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16301909SN/A txDmaData = 16311909SN/A is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 16321909SN/A txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1633854SN/A txDmaFree = dmaDescFree; 1634837SN/A 1635961SN/A descDmaReads++; 1636961SN/A descDmaRdBytes += txDmaLen; 1637961SN/A 1638854SN/A if (doTxDmaRead()) 1639854SN/A goto exit; 1640854SN/A 1641854SN/A } else { 1642854SN/A txState = txDescRead; 1643854SN/A 1644854SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16451909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 16461909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1647854SN/A txDmaFree = dmaDescFree; 1648854SN/A 1649961SN/A descDmaReads++; 1650961SN/A descDmaRdBytes += txDmaLen; 1651961SN/A 1652854SN/A if (doTxDmaRead()) 1653854SN/A goto exit; 1654837SN/A } 1655854SN/A break; 1656837SN/A 1657854SN/A case txDescRefr: 1658854SN/A if (txDmaState != dmaIdle) 1659854SN/A goto exit; 1660854SN/A 1661854SN/A txState = txAdvance; 1662854SN/A break; 1663854SN/A 1664854SN/A case txDescRead: 1665854SN/A if (txDmaState != dmaIdle) 1666854SN/A goto exit; 1667854SN/A 16681909SN/A DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 16691801SN/A regs.txdp & 0x3fffffff); 1670927SN/A DPRINTF(EthernetDesc, 16711909SN/A "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 16721909SN/A link, bufptr, cmdsts, extsts); 16731909SN/A 16741909SN/A if (cmdsts & CMDSTS_OWN) { 1675854SN/A txState = txFifoBlock; 16761909SN/A txFragPtr = bufptr; 16771909SN/A txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1678854SN/A } else { 16791035SN/A devIntrPost(ISR_TXIDLE); 1680854SN/A txState = txIdle; 16811035SN/A goto exit; 1682854SN/A } 1683854SN/A break; 1684854SN/A 1685854SN/A case txFifoBlock: 1686854SN/A if (!txPacket) { 16871036SN/A DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 168810469SN/A txPacket = make_shared<EthPacketData>(16384); 1689854SN/A txPacketBufPtr = txPacket->data; 1690854SN/A } 1691854SN/A 1692854SN/A if (txDescCnt == 0) { 1693927SN/A DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 16941909SN/A if (cmdsts & CMDSTS_MORE) { 1695927SN/A DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1696854SN/A txState = txDescWrite; 1697854SN/A 16981909SN/A cmdsts &= ~CMDSTS_OWN; 16991909SN/A 17001909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 17011909SN/A txDmaData = &cmdsts; 17021909SN/A if (is64bit) { 17031909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 17041909SN/A txDmaLen = sizeof(txDesc64.cmdsts); 17051909SN/A } else { 17061909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 17071909SN/A txDmaLen = sizeof(txDesc32.cmdsts); 17081909SN/A } 1709854SN/A txDmaFree = dmaDescFree; 1710854SN/A 1711854SN/A if (doTxDmaWrite()) 1712854SN/A goto exit; 1713854SN/A 1714854SN/A } else { /* this packet is totally done */ 1715927SN/A DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1716854SN/A /* deal with the the packet that just finished */ 1717854SN/A if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 17181114SN/A IpPtr ip(txPacket); 17191909SN/A if (extsts & EXTSTS_UDPPKT) { 17201114SN/A UdpPtr udp(ip); 17215484SN/A if (udp) { 17225484SN/A udp->sum(0); 17235484SN/A udp->sum(cksum(udp)); 17245484SN/A txUdpChecksums++; 17255484SN/A } else { 17268231SN/A Debug::breakpoint(); 17275484SN/A warn_once("UDPPKT set, but not UDP!\n"); 17285484SN/A } 17291909SN/A } else if (extsts & EXTSTS_TCPPKT) { 17301114SN/A TcpPtr tcp(ip); 17315484SN/A if (tcp) { 17325484SN/A tcp->sum(0); 17335484SN/A tcp->sum(cksum(tcp)); 17345484SN/A txTcpChecksums++; 17355484SN/A } else { 17365484SN/A warn_once("TCPPKT set, but not UDP!\n"); 17375484SN/A } 1738944SN/A } 17391909SN/A if (extsts & EXTSTS_IPPKT) { 17405484SN/A if (ip) { 17415484SN/A ip->sum(0); 17425484SN/A ip->sum(cksum(ip)); 17435484SN/A txIpChecksums++; 17445484SN/A } else { 17455484SN/A warn_once("IPPKT set, but not UDP!\n"); 17465484SN/A } 1747854SN/A } 1748854SN/A } 1749854SN/A 175011701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 1751854SN/A txPacket->length = txPacketBufPtr - txPacket->data; 17521027SN/A // this is just because the receive can't handle a 17531027SN/A // packet bigger want to make sure 17541909SN/A if (txPacket->length > 1514) 17551909SN/A panic("transmit packet too large, %s > 1514\n", 17561909SN/A txPacket->length); 17571909SN/A 17581205SN/A#ifndef NDEBUG 17591205SN/A bool success = 17601205SN/A#endif 17611205SN/A txFifo.push(txPacket); 17621205SN/A assert(success); 1763854SN/A 17641027SN/A /* 17651027SN/A * this following section is not tqo spec, but 17661027SN/A * functionally shouldn't be any different. normally, 17671027SN/A * the chip will wait til the transmit has occurred 17681027SN/A * before writing back the descriptor because it has 17691027SN/A * to wait to see that it was successfully transmitted 17701027SN/A * to decide whether to set CMDSTS_OK or not. 17711027SN/A * however, in the simulator since it is always 17721027SN/A * successfully transmitted, and writing it exactly to 17731027SN/A * spec would complicate the code, we just do it here 17741027SN/A */ 1775927SN/A 17761909SN/A cmdsts &= ~CMDSTS_OWN; 17771909SN/A cmdsts |= CMDSTS_OK; 1778854SN/A 1779927SN/A DPRINTF(EthernetDesc, 17801036SN/A "txDesc writeback: cmdsts=%08x extsts=%08x\n", 17811909SN/A cmdsts, extsts); 17821909SN/A 1783854SN/A txDmaFree = dmaDescFree; 17841909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 17851909SN/A txDmaData = &cmdsts; 17861909SN/A if (is64bit) { 17871909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 17881909SN/A txDmaLen = 17891909SN/A sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 17901909SN/A } else { 17911909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 17921909SN/A txDmaLen = 17931909SN/A sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 17941909SN/A } 1795854SN/A 1796961SN/A descDmaWrites++; 1797961SN/A descDmaWrBytes += txDmaLen; 1798961SN/A 1799927SN/A transmit(); 1800854SN/A txPacket = 0; 1801854SN/A 18021035SN/A if (!txEnable) { 1803927SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 1804854SN/A txState = txIdle; 18051035SN/A goto exit; 1806854SN/A } else 1807854SN/A txState = txAdvance; 1808986SN/A 1809986SN/A if (doTxDmaWrite()) 1810986SN/A goto exit; 1811854SN/A } 1812854SN/A } else { 1813927SN/A DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 18141154SN/A if (!txFifo.full()) { 1815992SN/A txState = txFragRead; 1816992SN/A 18171027SN/A /* 18181027SN/A * The number of bytes transferred is either whatever 18191027SN/A * is left in the descriptor (txDescCnt), or if there 18201027SN/A * is not enough room in the fifo, just whatever room 18211027SN/A * is left in the fifo 18221027SN/A */ 18231154SN/A txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 1824992SN/A 1825992SN/A txDmaAddr = txFragPtr & 0x3fffffff; 1826992SN/A txDmaData = txPacketBufPtr; 1827992SN/A txDmaLen = txXferLen; 1828992SN/A txDmaFree = dmaDataFree; 1829992SN/A 1830992SN/A if (doTxDmaRead()) 1831992SN/A goto exit; 1832992SN/A } else { 1833992SN/A txState = txFifoBlock; 1834992SN/A transmit(); 1835992SN/A 1836998SN/A goto exit; 1837992SN/A } 1838992SN/A 1839854SN/A } 1840854SN/A break; 1841854SN/A 1842854SN/A case txFragRead: 1843854SN/A if (txDmaState != dmaIdle) 1844854SN/A goto exit; 1845854SN/A 1846854SN/A txPacketBufPtr += txXferLen; 1847854SN/A txFragPtr += txXferLen; 1848854SN/A txDescCnt -= txXferLen; 18491205SN/A txFifo.reserve(txXferLen); 1850854SN/A 1851854SN/A txState = txFifoBlock; 1852854SN/A break; 1853854SN/A 1854854SN/A case txDescWrite: 1855854SN/A if (txDmaState != dmaIdle) 1856854SN/A goto exit; 1857854SN/A 18581909SN/A if (cmdsts & CMDSTS_INTR) 1859854SN/A devIntrPost(ISR_TXDESC); 1860854SN/A 18611801SN/A if (!txEnable) { 18621801SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 18631801SN/A txState = txIdle; 18641801SN/A goto exit; 18651801SN/A } else 18661801SN/A txState = txAdvance; 1867854SN/A break; 1868854SN/A 1869854SN/A case txAdvance: 18701909SN/A if (link == 0) { 18711035SN/A devIntrPost(ISR_TXIDLE); 1872837SN/A txState = txIdle; 18731035SN/A goto exit; 1874837SN/A } else { 18751893SN/A if (txDmaState != dmaIdle) 18761893SN/A goto exit; 1877837SN/A txState = txDescRead; 18781909SN/A regs.txdp = link; 1879837SN/A CTDD = false; 1880854SN/A 18811909SN/A txDmaAddr = link & 0x3fffffff; 18821909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 18831909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1884854SN/A txDmaFree = dmaDescFree; 1885854SN/A 1886854SN/A if (doTxDmaRead()) 1887854SN/A goto exit; 1888837SN/A } 1889854SN/A break; 1890837SN/A 1891854SN/A default: 1892854SN/A panic("invalid state"); 1893837SN/A } 1894837SN/A 18951036SN/A DPRINTF(EthernetSM, "entering next txState=%s\n", 1896854SN/A NsTxStateStrings[txState]); 1897854SN/A goto next; 1898837SN/A 1899854SN/A exit: 1900854SN/A /** 1901854SN/A * @todo do we want to schedule a future kick? 1902854SN/A */ 19031036SN/A DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1904854SN/A NsTxStateStrings[txState]); 19051801SN/A 19069417SN/A if (!txKickEvent.scheduled()) 19075606SN/A schedule(txKickEvent, txKickTick); 1908837SN/A} 1909837SN/A 19101843SN/A/** 19111843SN/A * Advance the EEPROM state machine 19121843SN/A * Called on rising edge of EEPROM clock bit in MEAR 19131843SN/A */ 19141843SN/Avoid 19151843SN/ANSGigE::eepromKick() 19161843SN/A{ 19171843SN/A switch (eepromState) { 19181843SN/A 19191843SN/A case eepromStart: 19201843SN/A 19211843SN/A // Wait for start bit 19221843SN/A if (regs.mear & MEAR_EEDI) { 19231843SN/A // Set up to get 2 opcode bits 19241843SN/A eepromState = eepromGetOpcode; 19251843SN/A eepromBitsToRx = 2; 19261843SN/A eepromOpcode = 0; 19271843SN/A } 19281843SN/A break; 19291843SN/A 19301843SN/A case eepromGetOpcode: 19311843SN/A eepromOpcode <<= 1; 19321843SN/A eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 19331843SN/A --eepromBitsToRx; 19341843SN/A 19351843SN/A // Done getting opcode 19361843SN/A if (eepromBitsToRx == 0) { 19371843SN/A if (eepromOpcode != EEPROM_READ) 19381843SN/A panic("only EEPROM reads are implemented!"); 19391843SN/A 19401843SN/A // Set up to get address 19411843SN/A eepromState = eepromGetAddress; 19421843SN/A eepromBitsToRx = 6; 19431843SN/A eepromAddress = 0; 19441843SN/A } 19451843SN/A break; 19461843SN/A 19471843SN/A case eepromGetAddress: 19481843SN/A eepromAddress <<= 1; 19491843SN/A eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 19501843SN/A --eepromBitsToRx; 19511843SN/A 19521843SN/A // Done getting address 19531843SN/A if (eepromBitsToRx == 0) { 19541843SN/A 19551843SN/A if (eepromAddress >= EEPROM_SIZE) 19561843SN/A panic("EEPROM read access out of range!"); 19571843SN/A 19581843SN/A switch (eepromAddress) { 19591843SN/A 19601843SN/A case EEPROM_PMATCH2_ADDR: 19611843SN/A eepromData = rom.perfectMatch[5]; 19621843SN/A eepromData <<= 8; 19631843SN/A eepromData += rom.perfectMatch[4]; 19641843SN/A break; 19651843SN/A 19661843SN/A case EEPROM_PMATCH1_ADDR: 19671843SN/A eepromData = rom.perfectMatch[3]; 19681843SN/A eepromData <<= 8; 19691843SN/A eepromData += rom.perfectMatch[2]; 19701843SN/A break; 19711843SN/A 19721843SN/A case EEPROM_PMATCH0_ADDR: 19731843SN/A eepromData = rom.perfectMatch[1]; 19741843SN/A eepromData <<= 8; 19751843SN/A eepromData += rom.perfectMatch[0]; 19761843SN/A break; 19771843SN/A 19781843SN/A default: 19791843SN/A panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 19801843SN/A } 19811843SN/A // Set up to read data 19821843SN/A eepromState = eepromRead; 19831843SN/A eepromBitsToRx = 16; 19841843SN/A 19851843SN/A // Clear data in bit 19861843SN/A regs.mear &= ~MEAR_EEDI; 19871843SN/A } 19881843SN/A break; 19891843SN/A 19901843SN/A case eepromRead: 19911843SN/A // Clear Data Out bit 19921843SN/A regs.mear &= ~MEAR_EEDO; 19931843SN/A // Set bit to value of current EEPROM bit 19941843SN/A regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 19951843SN/A 19961843SN/A eepromData <<= 1; 19971843SN/A --eepromBitsToRx; 19981843SN/A 19991843SN/A // All done 20001843SN/A if (eepromBitsToRx == 0) { 20011843SN/A eepromState = eepromStart; 20021843SN/A } 20031843SN/A break; 20041843SN/A 20051843SN/A default: 20061843SN/A panic("invalid EEPROM state"); 20071843SN/A } 20081843SN/A 20091843SN/A} 20101843SN/A 2011837SN/Avoid 2012879SN/ANSGigE::transferDone() 2013837SN/A{ 20141036SN/A if (txFifo.empty()) { 20151036SN/A DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2016837SN/A return; 20171036SN/A } 20181036SN/A 20191036SN/A DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2020837SN/A 20219417SN/A reschedule(txEvent, clockEdge(Cycles(1)), true); 2022837SN/A} 2023837SN/A 2024837SN/Abool 20252566SN/ANSGigE::rxFilter(const EthPacketPtr &packet) 2026837SN/A{ 20271114SN/A EthPtr eth = packet; 2028837SN/A bool drop = true; 2029837SN/A string type; 2030837SN/A 20311114SN/A const EthAddr &dst = eth->dst(); 20321114SN/A if (dst.unicast()) { 2033837SN/A // If we're accepting all unicast addresses 2034837SN/A if (acceptUnicast) 2035837SN/A drop = false; 2036837SN/A 2037837SN/A // If we make a perfect match 20381114SN/A if (acceptPerfect && dst == rom.perfectMatch) 2039837SN/A drop = false; 2040837SN/A 20411078SN/A if (acceptArp && eth->type() == ETH_TYPE_ARP) 2042837SN/A drop = false; 2043837SN/A 20441114SN/A } else if (dst.broadcast()) { 2045837SN/A // if we're accepting broadcasts 2046837SN/A if (acceptBroadcast) 2047837SN/A drop = false; 2048837SN/A 20491114SN/A } else if (dst.multicast()) { 2050837SN/A // if we're accepting all multicasts 2051837SN/A if (acceptMulticast) 2052837SN/A drop = false; 2053837SN/A 20541843SN/A // Multicast hashing faked - all packets accepted 20551843SN/A if (multicastHashEnable) 20561843SN/A drop = false; 2057837SN/A } 2058837SN/A 2059837SN/A if (drop) { 2060837SN/A DPRINTF(Ethernet, "rxFilter drop\n"); 2061837SN/A DDUMP(EthernetData, packet->data, packet->length); 2062837SN/A } 2063837SN/A 2064837SN/A return drop; 2065837SN/A} 2066837SN/A 2067837SN/Abool 20682566SN/ANSGigE::recvPacket(EthPacketPtr packet) 2069837SN/A{ 2070837SN/A rxBytes += packet->length; 2071837SN/A rxPackets++; 2072837SN/A 20731036SN/A DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 20741154SN/A rxFifo.avail()); 2075927SN/A 20761035SN/A if (!rxEnable) { 2077837SN/A DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2078837SN/A return true; 2079837SN/A } 2080837SN/A 20811843SN/A if (!rxFilterEnable) { 20821843SN/A DPRINTF(Ethernet, 20831843SN/A "receive packet filtering disabled . . . packet dropped\n"); 20841843SN/A return true; 20851843SN/A } 20861843SN/A 20871843SN/A if (rxFilter(packet)) { 2088837SN/A DPRINTF(Ethernet, "packet filtered...dropped\n"); 2089837SN/A return true; 2090837SN/A } 2091837SN/A 20921154SN/A if (rxFifo.avail() < packet->length) { 20931561SN/A#if TRACING_ON 20941561SN/A IpPtr ip(packet); 20951561SN/A TcpPtr tcp(ip); 20961561SN/A if (ip) { 20971561SN/A DPRINTF(Ethernet, 20981561SN/A "packet won't fit in receive buffer...pkt ID %d dropped\n", 20991561SN/A ip->id()); 21001561SN/A if (tcp) { 21011561SN/A DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 21021561SN/A } 21031561SN/A } 21041561SN/A#endif 21051263SN/A droppedPackets++; 2106837SN/A devIntrPost(ISR_RXORN); 2107837SN/A return false; 2108837SN/A } 2109837SN/A 21101154SN/A rxFifo.push(packet); 2111837SN/A 2112854SN/A rxKick(); 2113837SN/A return true; 2114837SN/A} 2115837SN/A 21162901SN/A 21172901SN/Avoid 21189342SN/ANSGigE::drainResume() 21192901SN/A{ 21209342SN/A Drainable::drainResume(); 21212901SN/A 21222901SN/A // During drain we could have left the state machines in a waiting state and 21232901SN/A // they wouldn't get out until some other event occured to kick them. 21242901SN/A // This way they'll get out immediately 21252901SN/A txKick(); 21262901SN/A rxKick(); 21272901SN/A} 21282901SN/A 21292901SN/A 2130837SN/A//===================================================================== 2131837SN/A// 2132837SN/A// 2133837SN/Avoid 213410905SN/ANSGigE::serialize(CheckpointOut &cp) const 2135837SN/A{ 21369807SN/A // Serialize the PciDevice base class 213710905SN/A PciDevice::serialize(cp); 2138897SN/A 2139854SN/A /* 2140854SN/A * Finalize any DMA events now. 2141854SN/A */ 21422566SN/A // @todo will mem system save pending dma? 2143837SN/A 2144854SN/A /* 2145854SN/A * Serialize the device registers 2146854SN/A */ 2147854SN/A SERIALIZE_SCALAR(regs.command); 2148854SN/A SERIALIZE_SCALAR(regs.config); 2149854SN/A SERIALIZE_SCALAR(regs.mear); 2150854SN/A SERIALIZE_SCALAR(regs.ptscr); 2151854SN/A SERIALIZE_SCALAR(regs.isr); 2152854SN/A SERIALIZE_SCALAR(regs.imr); 2153854SN/A SERIALIZE_SCALAR(regs.ier); 2154854SN/A SERIALIZE_SCALAR(regs.ihr); 2155854SN/A SERIALIZE_SCALAR(regs.txdp); 2156854SN/A SERIALIZE_SCALAR(regs.txdp_hi); 2157854SN/A SERIALIZE_SCALAR(regs.txcfg); 2158854SN/A SERIALIZE_SCALAR(regs.gpior); 2159854SN/A SERIALIZE_SCALAR(regs.rxdp); 2160854SN/A SERIALIZE_SCALAR(regs.rxdp_hi); 2161854SN/A SERIALIZE_SCALAR(regs.rxcfg); 2162854SN/A SERIALIZE_SCALAR(regs.pqcr); 2163854SN/A SERIALIZE_SCALAR(regs.wcsr); 2164854SN/A SERIALIZE_SCALAR(regs.pcr); 2165854SN/A SERIALIZE_SCALAR(regs.rfcr); 2166854SN/A SERIALIZE_SCALAR(regs.rfdr); 21671843SN/A SERIALIZE_SCALAR(regs.brar); 21681843SN/A SERIALIZE_SCALAR(regs.brdr); 2169854SN/A SERIALIZE_SCALAR(regs.srr); 2170854SN/A SERIALIZE_SCALAR(regs.mibc); 2171854SN/A SERIALIZE_SCALAR(regs.vrcr); 2172854SN/A SERIALIZE_SCALAR(regs.vtcr); 2173854SN/A SERIALIZE_SCALAR(regs.vdr); 2174854SN/A SERIALIZE_SCALAR(regs.ccsr); 2175854SN/A SERIALIZE_SCALAR(regs.tbicr); 2176854SN/A SERIALIZE_SCALAR(regs.tbisr); 2177854SN/A SERIALIZE_SCALAR(regs.tanar); 2178854SN/A SERIALIZE_SCALAR(regs.tanlpar); 2179854SN/A SERIALIZE_SCALAR(regs.taner); 2180854SN/A SERIALIZE_SCALAR(regs.tesr); 2181837SN/A 21821114SN/A SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 21831843SN/A SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2184837SN/A 2185927SN/A SERIALIZE_SCALAR(ioEnable); 2186917SN/A 2187854SN/A /* 2188915SN/A * Serialize the data Fifos 2189915SN/A */ 219010905SN/A rxFifo.serialize("rxFifo", cp); 219110905SN/A txFifo.serialize("txFifo", cp); 2192915SN/A 2193915SN/A /* 2194854SN/A * Serialize the various helper variables 2195854SN/A */ 219610469SN/A bool txPacketExists = txPacket != nullptr; 2197915SN/A SERIALIZE_SCALAR(txPacketExists); 2198915SN/A if (txPacketExists) { 219911701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 22001337SN/A txPacket->length = txPacketBufPtr - txPacket->data; 220110905SN/A txPacket->serialize("txPacket", cp); 2202915SN/A uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2203915SN/A SERIALIZE_SCALAR(txPktBufPtr); 2204915SN/A } 2205915SN/A 220610469SN/A bool rxPacketExists = rxPacket != nullptr; 2207915SN/A SERIALIZE_SCALAR(rxPacketExists); 2208915SN/A if (rxPacketExists) { 220910905SN/A rxPacket->serialize("rxPacket", cp); 2210915SN/A uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2211915SN/A SERIALIZE_SCALAR(rxPktBufPtr); 2212915SN/A } 2213915SN/A 2214854SN/A SERIALIZE_SCALAR(txXferLen); 2215854SN/A SERIALIZE_SCALAR(rxXferLen); 2216837SN/A 2217854SN/A /* 22181909SN/A * Serialize Cached Descriptors 2219854SN/A */ 22201909SN/A SERIALIZE_SCALAR(rxDesc64.link); 22211909SN/A SERIALIZE_SCALAR(rxDesc64.bufptr); 22221909SN/A SERIALIZE_SCALAR(rxDesc64.cmdsts); 22231909SN/A SERIALIZE_SCALAR(rxDesc64.extsts); 22241909SN/A SERIALIZE_SCALAR(txDesc64.link); 22251909SN/A SERIALIZE_SCALAR(txDesc64.bufptr); 22261909SN/A SERIALIZE_SCALAR(txDesc64.cmdsts); 22271909SN/A SERIALIZE_SCALAR(txDesc64.extsts); 22281909SN/A SERIALIZE_SCALAR(rxDesc32.link); 22291909SN/A SERIALIZE_SCALAR(rxDesc32.bufptr); 22301909SN/A SERIALIZE_SCALAR(rxDesc32.cmdsts); 22311909SN/A SERIALIZE_SCALAR(rxDesc32.extsts); 22321909SN/A SERIALIZE_SCALAR(txDesc32.link); 22331909SN/A SERIALIZE_SCALAR(txDesc32.bufptr); 22341909SN/A SERIALIZE_SCALAR(txDesc32.cmdsts); 22351909SN/A SERIALIZE_SCALAR(txDesc32.extsts); 22361801SN/A SERIALIZE_SCALAR(extstsEnable); 2237837SN/A 2238854SN/A /* 2239854SN/A * Serialize tx state machine 2240854SN/A */ 2241854SN/A int txState = this->txState; 2242854SN/A SERIALIZE_SCALAR(txState); 22431035SN/A SERIALIZE_SCALAR(txEnable); 2244854SN/A SERIALIZE_SCALAR(CTDD); 2245854SN/A SERIALIZE_SCALAR(txFragPtr); 2246854SN/A SERIALIZE_SCALAR(txDescCnt); 2247854SN/A int txDmaState = this->txDmaState; 2248854SN/A SERIALIZE_SCALAR(txDmaState); 22491801SN/A SERIALIZE_SCALAR(txKickTick); 2250854SN/A 2251854SN/A /* 2252854SN/A * Serialize rx state machine 2253854SN/A */ 2254854SN/A int rxState = this->rxState; 2255854SN/A SERIALIZE_SCALAR(rxState); 22561035SN/A SERIALIZE_SCALAR(rxEnable); 2257854SN/A SERIALIZE_SCALAR(CRDD); 2258854SN/A SERIALIZE_SCALAR(rxPktBytes); 22591224SN/A SERIALIZE_SCALAR(rxFragPtr); 2260854SN/A SERIALIZE_SCALAR(rxDescCnt); 2261854SN/A int rxDmaState = this->rxDmaState; 2262854SN/A SERIALIZE_SCALAR(rxDmaState); 22631801SN/A SERIALIZE_SCALAR(rxKickTick); 2264854SN/A 2265915SN/A /* 22661843SN/A * Serialize EEPROM state machine 22671843SN/A */ 22681843SN/A int eepromState = this->eepromState; 22691843SN/A SERIALIZE_SCALAR(eepromState); 22701843SN/A SERIALIZE_SCALAR(eepromClk); 22711843SN/A SERIALIZE_SCALAR(eepromBitsToRx); 22721843SN/A SERIALIZE_SCALAR(eepromOpcode); 22731843SN/A SERIALIZE_SCALAR(eepromAddress); 22741843SN/A SERIALIZE_SCALAR(eepromData); 22751843SN/A 22761843SN/A /* 2277854SN/A * If there's a pending transmit, store the time so we can 2278854SN/A * reschedule it later 2279854SN/A */ 22807823SN/A Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0; 2281854SN/A SERIALIZE_SCALAR(transmitTick); 2282854SN/A 2283854SN/A /* 2284915SN/A * receive address filter settings 2285915SN/A */ 2286915SN/A SERIALIZE_SCALAR(rxFilterEnable); 2287915SN/A SERIALIZE_SCALAR(acceptBroadcast); 2288915SN/A SERIALIZE_SCALAR(acceptMulticast); 2289915SN/A SERIALIZE_SCALAR(acceptUnicast); 2290915SN/A SERIALIZE_SCALAR(acceptPerfect); 2291915SN/A SERIALIZE_SCALAR(acceptArp); 22921843SN/A SERIALIZE_SCALAR(multicastHashEnable); 2293915SN/A 2294915SN/A /* 2295854SN/A * Keep track of pending interrupt status. 2296854SN/A */ 2297854SN/A SERIALIZE_SCALAR(intrTick); 2298854SN/A SERIALIZE_SCALAR(cpuPendingIntr); 2299854SN/A Tick intrEventTick = 0; 2300854SN/A if (intrEvent) 2301854SN/A intrEventTick = intrEvent->when(); 2302854SN/A SERIALIZE_SCALAR(intrEventTick); 2303854SN/A 2304837SN/A} 2305837SN/A 2306837SN/Avoid 230710905SN/ANSGigE::unserialize(CheckpointIn &cp) 2308837SN/A{ 23099807SN/A // Unserialize the PciDevice base class 231010905SN/A PciDevice::unserialize(cp); 2311897SN/A 2312854SN/A UNSERIALIZE_SCALAR(regs.command); 2313854SN/A UNSERIALIZE_SCALAR(regs.config); 2314854SN/A UNSERIALIZE_SCALAR(regs.mear); 2315854SN/A UNSERIALIZE_SCALAR(regs.ptscr); 2316854SN/A UNSERIALIZE_SCALAR(regs.isr); 2317854SN/A UNSERIALIZE_SCALAR(regs.imr); 2318854SN/A UNSERIALIZE_SCALAR(regs.ier); 2319854SN/A UNSERIALIZE_SCALAR(regs.ihr); 2320854SN/A UNSERIALIZE_SCALAR(regs.txdp); 2321854SN/A UNSERIALIZE_SCALAR(regs.txdp_hi); 2322854SN/A UNSERIALIZE_SCALAR(regs.txcfg); 2323854SN/A UNSERIALIZE_SCALAR(regs.gpior); 2324854SN/A UNSERIALIZE_SCALAR(regs.rxdp); 2325854SN/A UNSERIALIZE_SCALAR(regs.rxdp_hi); 2326854SN/A UNSERIALIZE_SCALAR(regs.rxcfg); 2327854SN/A UNSERIALIZE_SCALAR(regs.pqcr); 2328854SN/A UNSERIALIZE_SCALAR(regs.wcsr); 2329854SN/A UNSERIALIZE_SCALAR(regs.pcr); 2330854SN/A UNSERIALIZE_SCALAR(regs.rfcr); 2331854SN/A UNSERIALIZE_SCALAR(regs.rfdr); 23321843SN/A UNSERIALIZE_SCALAR(regs.brar); 23331843SN/A UNSERIALIZE_SCALAR(regs.brdr); 2334854SN/A UNSERIALIZE_SCALAR(regs.srr); 2335854SN/A UNSERIALIZE_SCALAR(regs.mibc); 2336854SN/A UNSERIALIZE_SCALAR(regs.vrcr); 2337854SN/A UNSERIALIZE_SCALAR(regs.vtcr); 2338854SN/A UNSERIALIZE_SCALAR(regs.vdr); 2339854SN/A UNSERIALIZE_SCALAR(regs.ccsr); 2340854SN/A UNSERIALIZE_SCALAR(regs.tbicr); 2341854SN/A UNSERIALIZE_SCALAR(regs.tbisr); 2342854SN/A UNSERIALIZE_SCALAR(regs.tanar); 2343854SN/A UNSERIALIZE_SCALAR(regs.tanlpar); 2344854SN/A UNSERIALIZE_SCALAR(regs.taner); 2345854SN/A UNSERIALIZE_SCALAR(regs.tesr); 2346837SN/A 23471114SN/A UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 23481843SN/A UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2349837SN/A 2350927SN/A UNSERIALIZE_SCALAR(ioEnable); 2351917SN/A 2352854SN/A /* 2353915SN/A * unserialize the data fifos 2354915SN/A */ 235510905SN/A rxFifo.unserialize("rxFifo", cp); 235610905SN/A txFifo.unserialize("txFifo", cp); 2357915SN/A 2358915SN/A /* 2359854SN/A * unserialize the various helper variables 2360854SN/A */ 2361915SN/A bool txPacketExists; 2362915SN/A UNSERIALIZE_SCALAR(txPacketExists); 2363915SN/A if (txPacketExists) { 236411719Smichael.lebeane@amd.com txPacket = make_shared<EthPacketData>(16384); 236510905SN/A txPacket->unserialize("txPacket", cp); 2366915SN/A uint32_t txPktBufPtr; 2367915SN/A UNSERIALIZE_SCALAR(txPktBufPtr); 2368915SN/A txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2369915SN/A } else 2370915SN/A txPacket = 0; 2371915SN/A 2372915SN/A bool rxPacketExists; 2373915SN/A UNSERIALIZE_SCALAR(rxPacketExists); 2374915SN/A rxPacket = 0; 2375915SN/A if (rxPacketExists) { 237611701Smichael.lebeane@amd.com rxPacket = make_shared<EthPacketData>(); 237710905SN/A rxPacket->unserialize("rxPacket", cp); 2378915SN/A uint32_t rxPktBufPtr; 2379915SN/A UNSERIALIZE_SCALAR(rxPktBufPtr); 2380915SN/A rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2381915SN/A } else 2382915SN/A rxPacket = 0; 2383915SN/A 2384854SN/A UNSERIALIZE_SCALAR(txXferLen); 2385854SN/A UNSERIALIZE_SCALAR(rxXferLen); 2386837SN/A 2387854SN/A /* 23881909SN/A * Unserialize Cached Descriptors 2389854SN/A */ 23901909SN/A UNSERIALIZE_SCALAR(rxDesc64.link); 23911909SN/A UNSERIALIZE_SCALAR(rxDesc64.bufptr); 23921909SN/A UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 23931909SN/A UNSERIALIZE_SCALAR(rxDesc64.extsts); 23941909SN/A UNSERIALIZE_SCALAR(txDesc64.link); 23951909SN/A UNSERIALIZE_SCALAR(txDesc64.bufptr); 23961909SN/A UNSERIALIZE_SCALAR(txDesc64.cmdsts); 23971909SN/A UNSERIALIZE_SCALAR(txDesc64.extsts); 23981909SN/A UNSERIALIZE_SCALAR(rxDesc32.link); 23991909SN/A UNSERIALIZE_SCALAR(rxDesc32.bufptr); 24001909SN/A UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 24011909SN/A UNSERIALIZE_SCALAR(rxDesc32.extsts); 24021909SN/A UNSERIALIZE_SCALAR(txDesc32.link); 24031909SN/A UNSERIALIZE_SCALAR(txDesc32.bufptr); 24041909SN/A UNSERIALIZE_SCALAR(txDesc32.cmdsts); 24051909SN/A UNSERIALIZE_SCALAR(txDesc32.extsts); 24061801SN/A UNSERIALIZE_SCALAR(extstsEnable); 2407854SN/A 2408854SN/A /* 2409854SN/A * unserialize tx state machine 2410854SN/A */ 2411854SN/A int txState; 2412854SN/A UNSERIALIZE_SCALAR(txState); 2413854SN/A this->txState = (TxState) txState; 24141035SN/A UNSERIALIZE_SCALAR(txEnable); 2415854SN/A UNSERIALIZE_SCALAR(CTDD); 2416854SN/A UNSERIALIZE_SCALAR(txFragPtr); 2417854SN/A UNSERIALIZE_SCALAR(txDescCnt); 2418854SN/A int txDmaState; 2419854SN/A UNSERIALIZE_SCALAR(txDmaState); 2420854SN/A this->txDmaState = (DmaState) txDmaState; 24211801SN/A UNSERIALIZE_SCALAR(txKickTick); 24221801SN/A if (txKickTick) 24235606SN/A schedule(txKickEvent, txKickTick); 2424854SN/A 2425854SN/A /* 2426854SN/A * unserialize rx state machine 2427854SN/A */ 2428854SN/A int rxState; 2429854SN/A UNSERIALIZE_SCALAR(rxState); 2430854SN/A this->rxState = (RxState) rxState; 24311035SN/A UNSERIALIZE_SCALAR(rxEnable); 2432854SN/A UNSERIALIZE_SCALAR(CRDD); 2433854SN/A UNSERIALIZE_SCALAR(rxPktBytes); 24341224SN/A UNSERIALIZE_SCALAR(rxFragPtr); 2435854SN/A UNSERIALIZE_SCALAR(rxDescCnt); 2436854SN/A int rxDmaState; 2437854SN/A UNSERIALIZE_SCALAR(rxDmaState); 2438854SN/A this->rxDmaState = (DmaState) rxDmaState; 24391801SN/A UNSERIALIZE_SCALAR(rxKickTick); 24401801SN/A if (rxKickTick) 24415606SN/A schedule(rxKickEvent, rxKickTick); 2442854SN/A 24431843SN/A /* 24441843SN/A * Unserialize EEPROM state machine 24451843SN/A */ 24461843SN/A int eepromState; 24471843SN/A UNSERIALIZE_SCALAR(eepromState); 24481843SN/A this->eepromState = (EEPROMState) eepromState; 24491843SN/A UNSERIALIZE_SCALAR(eepromClk); 24501843SN/A UNSERIALIZE_SCALAR(eepromBitsToRx); 24511843SN/A UNSERIALIZE_SCALAR(eepromOpcode); 24521843SN/A UNSERIALIZE_SCALAR(eepromAddress); 24531843SN/A UNSERIALIZE_SCALAR(eepromData); 24541843SN/A 24551843SN/A /* 2456915SN/A * If there's a pending transmit, reschedule it now 2457854SN/A */ 2458854SN/A Tick transmitTick; 2459854SN/A UNSERIALIZE_SCALAR(transmitTick); 2460854SN/A if (transmitTick) 24617823SN/A schedule(txEvent, curTick() + transmitTick); 2462854SN/A 2463854SN/A /* 2464915SN/A * unserialize receive address filter settings 2465915SN/A */ 2466915SN/A UNSERIALIZE_SCALAR(rxFilterEnable); 2467915SN/A UNSERIALIZE_SCALAR(acceptBroadcast); 2468915SN/A UNSERIALIZE_SCALAR(acceptMulticast); 2469915SN/A UNSERIALIZE_SCALAR(acceptUnicast); 2470915SN/A UNSERIALIZE_SCALAR(acceptPerfect); 2471915SN/A UNSERIALIZE_SCALAR(acceptArp); 24721843SN/A UNSERIALIZE_SCALAR(multicastHashEnable); 2473915SN/A 2474915SN/A /* 2475854SN/A * Keep track of pending interrupt status. 2476854SN/A */ 2477854SN/A UNSERIALIZE_SCALAR(intrTick); 2478854SN/A UNSERIALIZE_SCALAR(cpuPendingIntr); 2479854SN/A Tick intrEventTick; 2480854SN/A UNSERIALIZE_SCALAR(intrEventTick); 2481854SN/A if (intrEventTick) { 248212087Sspwilson2@wisc.edu intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); }, 248312087Sspwilson2@wisc.edu name(), true); 24845606SN/A schedule(intrEvent, intrEventTick); 2485854SN/A } 2486854SN/A} 2487927SN/A 24884762SN/ANSGigE * 24894762SN/ANSGigEParams::create() 2490837SN/A{ 24914762SN/A return new NSGigE(this); 2492837SN/A} 2493