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 17613784Sgabeblack@google.comPort & 17713784Sgabeblack@google.comNSGigE::getPort(const std::string &if_name, PortID idx) 1784981SN/A{ 17913784Sgabeblack@google.com if (if_name == "interface") 18013784Sgabeblack@google.com return *interface; 18113784Sgabeblack@google.com return EtherDevBase::getPort(if_name, idx); 1824981SN/A} 1834981SN/A 184855SN/A/** 185855SN/A * This reads the device registers, which are detailed in the NS83820 186855SN/A * spec sheet 187855SN/A */ 1882566SN/ATick 1893349SN/ANSGigE::read(PacketPtr pkt) 190837SN/A{ 191927SN/A assert(ioEnable); 192917SN/A 193855SN/A //The mask is to give you only the offset into the device register file 1942641SN/A Addr daddr = pkt->getAddr() & 0xfff; 1952566SN/A DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 1962641SN/A daddr, pkt->getAddr(), pkt->getSize()); 197837SN/A 198855SN/A 1991027SN/A // there are some reserved registers, you can see ns_gige_reg.h and 2001027SN/A // the spec sheet for details 201854SN/A if (daddr > LAST && daddr <= RESERVED) { 202837SN/A panic("Accessing reserved register"); 203854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 2042846SN/A return readConfig(pkt); 205854SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 206854SN/A // don't implement all the MIB's. hopefully the kernel 207854SN/A // doesn't actually DEPEND upon their values 208855SN/A // MIB are just hardware stats keepers 20913342Sgabeblack@google.com pkt->setLE<uint32_t>(0); 2104870SN/A pkt->makeAtomicResponse(); 2112566SN/A return pioDelay; 212854SN/A } else if (daddr > 0x3FC) 213854SN/A panic("Something is messed up!\n"); 214837SN/A 2152641SN/A assert(pkt->getSize() == sizeof(uint32_t)); 2162630SN/A uint32_t ® = *pkt->getPtr<uint32_t>(); 2172566SN/A uint16_t rfaddr; 2182566SN/A 2192566SN/A switch (daddr) { 2202566SN/A case CR: 2212566SN/A reg = regs.command; 2222566SN/A //these are supposed to be cleared on a read 2232566SN/A reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 2242566SN/A break; 2252566SN/A 2262566SN/A case CFGR: 2272566SN/A reg = regs.config; 2282566SN/A break; 2292566SN/A 2302566SN/A case MEAR: 2312566SN/A reg = regs.mear; 2322566SN/A break; 2332566SN/A 2342566SN/A case PTSCR: 2352566SN/A reg = regs.ptscr; 2362566SN/A break; 2372566SN/A 2382566SN/A case ISR: 2392566SN/A reg = regs.isr; 2402566SN/A devIntrClear(ISR_ALL); 2412566SN/A break; 2422566SN/A 2432566SN/A case IMR: 2442566SN/A reg = regs.imr; 2452566SN/A break; 2462566SN/A 2472566SN/A case IER: 2482566SN/A reg = regs.ier; 2492566SN/A break; 2502566SN/A 2512566SN/A case IHR: 2522566SN/A reg = regs.ihr; 2532566SN/A break; 2542566SN/A 2552566SN/A case TXDP: 2562566SN/A reg = regs.txdp; 2572566SN/A break; 2582566SN/A 2592566SN/A case TXDP_HI: 2602566SN/A reg = regs.txdp_hi; 2612566SN/A break; 2622566SN/A 2632566SN/A case TX_CFG: 2642566SN/A reg = regs.txcfg; 2652566SN/A break; 2662566SN/A 2672566SN/A case GPIOR: 2682566SN/A reg = regs.gpior; 2692566SN/A break; 2702566SN/A 2712566SN/A case RXDP: 2722566SN/A reg = regs.rxdp; 2732566SN/A break; 2742566SN/A 2752566SN/A case RXDP_HI: 2762566SN/A reg = regs.rxdp_hi; 2772566SN/A break; 2782566SN/A 2792566SN/A case RX_CFG: 2802566SN/A reg = regs.rxcfg; 2812566SN/A break; 2822566SN/A 2832566SN/A case PQCR: 2842566SN/A reg = regs.pqcr; 2852566SN/A break; 2862566SN/A 2872566SN/A case WCSR: 2882566SN/A reg = regs.wcsr; 2892566SN/A break; 2902566SN/A 2912566SN/A case PCR: 2922566SN/A reg = regs.pcr; 2932566SN/A break; 2942566SN/A 2952566SN/A // see the spec sheet for how RFCR and RFDR work 2962566SN/A // basically, you write to RFCR to tell the machine 2972566SN/A // what you want to do next, then you act upon RFDR, 2982566SN/A // and the device will be prepared b/c of what you 2992566SN/A // wrote to RFCR 3002566SN/A case RFCR: 3012566SN/A reg = regs.rfcr; 3022566SN/A break; 3032566SN/A 3042566SN/A case RFDR: 3052566SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 3062566SN/A switch (rfaddr) { 3072566SN/A // Read from perfect match ROM octets 3082566SN/A case 0x000: 3092566SN/A reg = rom.perfectMatch[1]; 3102566SN/A reg = reg << 8; 3112566SN/A reg += rom.perfectMatch[0]; 312837SN/A break; 3132566SN/A case 0x002: 3142566SN/A reg = rom.perfectMatch[3] << 8; 3152566SN/A reg += rom.perfectMatch[2]; 316837SN/A break; 3172566SN/A case 0x004: 3182566SN/A reg = rom.perfectMatch[5] << 8; 3192566SN/A reg += rom.perfectMatch[4]; 320837SN/A break; 3212566SN/A default: 3222566SN/A // Read filter hash table 3232566SN/A if (rfaddr >= FHASH_ADDR && 3242566SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 3252566SN/A 3262566SN/A // Only word-aligned reads supported 3272566SN/A if (rfaddr % 2) 3282566SN/A panic("unaligned read from filter hash table!"); 3292566SN/A 3302566SN/A reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 3312566SN/A reg += rom.filterHash[rfaddr - FHASH_ADDR]; 332837SN/A break; 333837SN/A } 3342566SN/A 3352566SN/A panic("reading RFDR for something other than pattern" 3362566SN/A " matching or hashing! %#x\n", rfaddr); 337837SN/A } 3382566SN/A break; 3392566SN/A 3402566SN/A case SRR: 3412566SN/A reg = regs.srr; 3422566SN/A break; 3432566SN/A 3442566SN/A case MIBC: 3452566SN/A reg = regs.mibc; 3462566SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 3472566SN/A break; 3482566SN/A 3492566SN/A case VRCR: 3502566SN/A reg = regs.vrcr; 3512566SN/A break; 3522566SN/A 3532566SN/A case VTCR: 3542566SN/A reg = regs.vtcr; 3552566SN/A break; 3562566SN/A 3572566SN/A case VDR: 3582566SN/A reg = regs.vdr; 3592566SN/A break; 3602566SN/A 3612566SN/A case CCSR: 3622566SN/A reg = regs.ccsr; 3632566SN/A break; 3642566SN/A 3652566SN/A case TBICR: 3662566SN/A reg = regs.tbicr; 3672566SN/A break; 3682566SN/A 3692566SN/A case TBISR: 3702566SN/A reg = regs.tbisr; 3712566SN/A break; 3722566SN/A 3732566SN/A case TANAR: 3742566SN/A reg = regs.tanar; 3752566SN/A break; 3762566SN/A 3772566SN/A case TANLPAR: 3782566SN/A reg = regs.tanlpar; 3792566SN/A break; 3802566SN/A 3812566SN/A case TANER: 3822566SN/A reg = regs.taner; 3832566SN/A break; 3842566SN/A 3852566SN/A case TESR: 3862566SN/A reg = regs.tesr; 3872566SN/A break; 3882566SN/A 3892566SN/A case M5REG: 3902566SN/A reg = 0; 3912566SN/A if (params()->rx_thread) 3922566SN/A reg |= M5REG_RX_THREAD; 3932566SN/A if (params()->tx_thread) 3942566SN/A reg |= M5REG_TX_THREAD; 3952566SN/A if (params()->rss) 3962566SN/A reg |= M5REG_RSS; 3972566SN/A break; 3982566SN/A 3992566SN/A default: 4002566SN/A panic("reading unimplemented register: addr=%#x", daddr); 401837SN/A } 4022566SN/A 4032566SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 4042566SN/A daddr, reg, reg); 4052566SN/A 4064870SN/A pkt->makeAtomicResponse(); 4072566SN/A return pioDelay; 408837SN/A} 409837SN/A 4102566SN/ATick 4113349SN/ANSGigE::write(PacketPtr pkt) 412837SN/A{ 413927SN/A assert(ioEnable); 414917SN/A 4152641SN/A Addr daddr = pkt->getAddr() & 0xfff; 4162566SN/A DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 4172641SN/A daddr, pkt->getAddr(), pkt->getSize()); 4182630SN/A 419854SN/A if (daddr > LAST && daddr <= RESERVED) { 420837SN/A panic("Accessing reserved register"); 421854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 4222846SN/A return writeConfig(pkt); 423854SN/A } else if (daddr > 0x3FC) 424854SN/A panic("Something is messed up!\n"); 425837SN/A 4262641SN/A if (pkt->getSize() == sizeof(uint32_t)) { 42713342Sgabeblack@google.com uint32_t reg = pkt->getLE<uint32_t>(); 4281848SN/A uint16_t rfaddr; 4291848SN/A 430854SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 431837SN/A 432837SN/A switch (daddr) { 433837SN/A case CR: 434837SN/A regs.command = reg; 4351035SN/A if (reg & CR_TXD) { 4361035SN/A txEnable = false; 437837SN/A } else if (reg & CR_TXE) { 4382126SN/A txEnable = true; 4392126SN/A 4402126SN/A // the kernel is enabling the transmit machine 4412126SN/A if (txState == txIdle) 4422126SN/A txKick(); 443837SN/A } 444837SN/A 4451035SN/A if (reg & CR_RXD) { 4461035SN/A rxEnable = false; 447837SN/A } else if (reg & CR_RXE) { 4482126SN/A rxEnable = true; 4492126SN/A 4502126SN/A if (rxState == rxIdle) 4512126SN/A rxKick(); 452837SN/A } 453837SN/A 454837SN/A if (reg & CR_TXR) 455837SN/A txReset(); 456837SN/A 457837SN/A if (reg & CR_RXR) 458837SN/A rxReset(); 459837SN/A 460837SN/A if (reg & CR_SWI) 461837SN/A devIntrPost(ISR_SWI); 462837SN/A 463837SN/A if (reg & CR_RST) { 464837SN/A txReset(); 465837SN/A rxReset(); 466854SN/A 467837SN/A regsReset(); 468837SN/A } 469837SN/A break; 470837SN/A 4711690SN/A case CFGR: 4721690SN/A if (reg & CFGR_LNKSTS || 4731690SN/A reg & CFGR_SPDSTS || 4741690SN/A reg & CFGR_DUPSTS || 4751690SN/A reg & CFGR_RESERVED || 4761690SN/A reg & CFGR_T64ADDR || 4778726SN/A reg & CFGR_PCI64_DET) { 4788726SN/A // First clear all writable bits 4798726SN/A regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4808726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4818726SN/A CFGR_PCI64_DET; 4828726SN/A // Now set the appropriate writable bits 4838726SN/A regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4848726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4858726SN/A CFGR_PCI64_DET); 4868726SN/A } 4871027SN/A 4888737SN/A if (reg & CFGR_AUTO_1000) 4898737SN/A panic("CFGR_AUTO_1000 not implemented!\n"); 4908737SN/A 4918737SN/A if (reg & CFGR_PCI64_DET) 4928737SN/A panic("CFGR_PCI64_DET is read only register!\n"); 4938737SN/A 4948737SN/A if (reg & CFGR_EXTSTS_EN) 4958737SN/A extstsEnable = true; 4968737SN/A else 4978737SN/A extstsEnable = false; 498837SN/A break; 499837SN/A 500837SN/A case MEAR: 5011843SN/A // Clear writable bits 5021843SN/A regs.mear &= MEAR_EEDO; 5031843SN/A // Set appropriate writable bits 5041843SN/A regs.mear |= reg & ~MEAR_EEDO; 5051843SN/A 5061843SN/A // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 5071843SN/A // even though it could get it through RFDR 5081843SN/A if (reg & MEAR_EESEL) { 5091843SN/A // Rising edge of clock 5101843SN/A if (reg & MEAR_EECLK && !eepromClk) 5111843SN/A eepromKick(); 5121843SN/A } 5131843SN/A else { 5141843SN/A eepromState = eepromStart; 5151843SN/A regs.mear &= ~MEAR_EEDI; 5161843SN/A } 5171843SN/A 5181843SN/A eepromClk = reg & MEAR_EECLK; 5191843SN/A 5201027SN/A // since phy is completely faked, MEAR_MD* don't matter 521837SN/A break; 522837SN/A 523837SN/A case PTSCR: 524854SN/A regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 5251027SN/A // these control BISTs for various parts of chip - we 5261027SN/A // don't care or do just fake that the BIST is done 527854SN/A if (reg & PTSCR_RBIST_EN) 528854SN/A regs.ptscr |= PTSCR_RBIST_DONE; 529854SN/A if (reg & PTSCR_EEBIST_EN) 530854SN/A regs.ptscr &= ~PTSCR_EEBIST_EN; 531854SN/A if (reg & PTSCR_EELOAD_EN) 532854SN/A regs.ptscr &= ~PTSCR_EELOAD_EN; 533837SN/A break; 534837SN/A 535837SN/A case ISR: /* writing to the ISR has no effect */ 536837SN/A panic("ISR is a read only register!\n"); 537837SN/A 538837SN/A case IMR: 539837SN/A regs.imr = reg; 540837SN/A devIntrChangeMask(); 541837SN/A break; 542837SN/A 543837SN/A case IER: 544837SN/A regs.ier = reg; 545837SN/A break; 546837SN/A 547837SN/A case IHR: 548837SN/A regs.ihr = reg; 549837SN/A /* not going to implement real interrupt holdoff */ 550837SN/A break; 551837SN/A 552837SN/A case TXDP: 553837SN/A regs.txdp = (reg & 0xFFFFFFFC); 554837SN/A assert(txState == txIdle); 555837SN/A CTDD = false; 556837SN/A break; 557837SN/A 558837SN/A case TXDP_HI: 559837SN/A regs.txdp_hi = reg; 560837SN/A break; 561837SN/A 5621690SN/A case TX_CFG: 563837SN/A regs.txcfg = reg; 5641027SN/A 5651027SN/A // also, we currently don't care about fill/drain 5661027SN/A // thresholds though this may change in the future with 5671027SN/A // more realistic networks or a driver which changes it 5681027SN/A // according to feedback 569837SN/A 570837SN/A break; 571837SN/A 572837SN/A case GPIOR: 5731843SN/A // Only write writable bits 5741843SN/A regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 5751843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 5761843SN/A regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 5771843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 578837SN/A /* these just control general purpose i/o pins, don't matter */ 579837SN/A break; 580837SN/A 581854SN/A case RXDP: 582854SN/A regs.rxdp = reg; 5831035SN/A CRDD = false; 584854SN/A break; 585854SN/A 586854SN/A case RXDP_HI: 587854SN/A regs.rxdp_hi = reg; 588854SN/A break; 589854SN/A 5901690SN/A case RX_CFG: 591837SN/A regs.rxcfg = reg; 592837SN/A break; 593837SN/A 594837SN/A case PQCR: 595837SN/A /* there is no priority queueing used in the linux 2.6 driver */ 596837SN/A regs.pqcr = reg; 597837SN/A break; 598837SN/A 599837SN/A case WCSR: 600837SN/A /* not going to implement wake on LAN */ 601837SN/A regs.wcsr = reg; 602837SN/A break; 603837SN/A 604837SN/A case PCR: 605837SN/A /* not going to implement pause control */ 606837SN/A regs.pcr = reg; 607837SN/A break; 608837SN/A 609837SN/A case RFCR: 610837SN/A regs.rfcr = reg; 611854SN/A 612837SN/A rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 613837SN/A acceptBroadcast = (reg & RFCR_AAB) ? true : false; 614837SN/A acceptMulticast = (reg & RFCR_AAM) ? true : false; 615837SN/A acceptUnicast = (reg & RFCR_AAU) ? true : false; 616837SN/A acceptPerfect = (reg & RFCR_APM) ? true : false; 617837SN/A acceptArp = (reg & RFCR_AARP) ? true : false; 6181843SN/A multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 619837SN/A 6201843SN/A if (reg & RFCR_UHEN) 6211843SN/A panic("Unicast hash filtering not used by drivers!\n"); 622837SN/A 623837SN/A if (reg & RFCR_ULM) 624837SN/A panic("RFCR_ULM not implemented!\n"); 625837SN/A 626837SN/A break; 627837SN/A 628837SN/A case RFDR: 6291848SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 6301843SN/A switch (rfaddr) { 6311843SN/A case 0x000: 6321843SN/A rom.perfectMatch[0] = (uint8_t)reg; 6331843SN/A rom.perfectMatch[1] = (uint8_t)(reg >> 8); 6341843SN/A break; 6351843SN/A case 0x002: 6361843SN/A rom.perfectMatch[2] = (uint8_t)reg; 6371843SN/A rom.perfectMatch[3] = (uint8_t)(reg >> 8); 6381843SN/A break; 6391843SN/A case 0x004: 6401843SN/A rom.perfectMatch[4] = (uint8_t)reg; 6411843SN/A rom.perfectMatch[5] = (uint8_t)(reg >> 8); 6421843SN/A break; 6431843SN/A default: 6441843SN/A 6451843SN/A if (rfaddr >= FHASH_ADDR && 6461843SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 6471843SN/A 6481843SN/A // Only word-aligned writes supported 6491843SN/A if (rfaddr % 2) 6501843SN/A panic("unaligned write to filter hash table!"); 6511843SN/A 6521843SN/A rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 6531843SN/A rom.filterHash[rfaddr - FHASH_ADDR + 1] 6541843SN/A = (uint8_t)(reg >> 8); 6551843SN/A break; 6561843SN/A } 65710367SN/A panic("writing RFDR for something other than pattern matching " 65810367SN/A "or hashing! %#x\n", rfaddr); 6591843SN/A } 66012561Ssiddhesh.poyarekar@gmail.com break; 661837SN/A 662837SN/A case BRAR: 6631843SN/A regs.brar = reg; 6641843SN/A break; 665837SN/A 666837SN/A case BRDR: 667837SN/A panic("the driver never uses BRDR, something is wrong!\n"); 668837SN/A 669837SN/A case SRR: 670837SN/A panic("SRR is read only register!\n"); 671837SN/A 672837SN/A case MIBC: 673837SN/A panic("the driver never uses MIBC, something is wrong!\n"); 674837SN/A 675837SN/A case VRCR: 676837SN/A regs.vrcr = reg; 677837SN/A break; 678837SN/A 679837SN/A case VTCR: 680837SN/A regs.vtcr = reg; 681837SN/A break; 682837SN/A 683837SN/A case VDR: 684837SN/A panic("the driver never uses VDR, something is wrong!\n"); 685837SN/A 686837SN/A case CCSR: 687837SN/A /* not going to implement clockrun stuff */ 688837SN/A regs.ccsr = reg; 689837SN/A break; 690837SN/A 691837SN/A case TBICR: 692837SN/A regs.tbicr = reg; 693837SN/A if (reg & TBICR_MR_LOOPBACK) 694837SN/A panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 695837SN/A 696837SN/A if (reg & TBICR_MR_AN_ENABLE) { 697837SN/A regs.tanlpar = regs.tanar; 698837SN/A regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 699837SN/A } 700837SN/A 701837SN/A break; 702837SN/A 703837SN/A case TBISR: 704837SN/A panic("TBISR is read only register!\n"); 705837SN/A 706837SN/A case TANAR: 7071843SN/A // Only write the writable bits 7081843SN/A regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 7091843SN/A regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 7101843SN/A 7111843SN/A // Pause capability unimplemented 712837SN/A break; 713837SN/A 714837SN/A case TANLPAR: 715837SN/A panic("this should only be written to by the fake phy!\n"); 716837SN/A 717837SN/A case TANER: 718837SN/A panic("TANER is read only register!\n"); 719837SN/A 720837SN/A case TESR: 721837SN/A regs.tesr = reg; 722837SN/A break; 723837SN/A 724837SN/A default: 7251027SN/A panic("invalid register access daddr=%#x", daddr); 726837SN/A } 7271027SN/A } else { 728837SN/A panic("Invalid Request Size"); 7291027SN/A } 7304870SN/A pkt->makeAtomicResponse(); 7312566SN/A return pioDelay; 732837SN/A} 733837SN/A 734837SN/Avoid 735879SN/ANSGigE::devIntrPost(uint32_t interrupts) 736837SN/A{ 737854SN/A if (interrupts & ISR_RESERVE) 738854SN/A panic("Cannot set a reserved interrupt"); 739837SN/A 7401057SN/A if (interrupts & ISR_NOIMPL) 7411057SN/A warn("interrupt not implemented %#x\n", interrupts); 7421057SN/A 7431883SN/A interrupts &= ISR_IMPL; 7441057SN/A regs.isr |= interrupts; 7451057SN/A 7461263SN/A if (interrupts & regs.imr) { 7471263SN/A if (interrupts & ISR_SWI) { 7481263SN/A totalSwi++; 7491263SN/A } 7501263SN/A if (interrupts & ISR_RXIDLE) { 7511263SN/A totalRxIdle++; 7521263SN/A } 7531263SN/A if (interrupts & ISR_RXOK) { 7541263SN/A totalRxOk++; 7551263SN/A } 7561263SN/A if (interrupts & ISR_RXDESC) { 7571263SN/A totalRxDesc++; 7581263SN/A } 7591263SN/A if (interrupts & ISR_TXOK) { 7601263SN/A totalTxOk++; 7611263SN/A } 7621263SN/A if (interrupts & ISR_TXIDLE) { 7631263SN/A totalTxIdle++; 7641263SN/A } 7651263SN/A if (interrupts & ISR_TXDESC) { 7661263SN/A totalTxDesc++; 7671263SN/A } 7681263SN/A if (interrupts & ISR_RXORN) { 7691263SN/A totalRxOrn++; 7701263SN/A } 7711263SN/A } 7721263SN/A 7731057SN/A DPRINTF(EthernetIntr, 7741057SN/A "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 7751057SN/A interrupts, regs.isr, regs.imr); 776837SN/A 777854SN/A if ((regs.isr & regs.imr)) { 7787823SN/A Tick when = curTick(); 7791883SN/A if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 780854SN/A when += intrDelay; 7815485SN/A postedInterrupts++; 782854SN/A cpuIntrPost(when); 783854SN/A } 784837SN/A} 785837SN/A 7861263SN/A/* writing this interrupt counting stats inside this means that this function 7871263SN/A is now limited to being used to clear all interrupts upon the kernel 7881263SN/A reading isr and servicing. just telling you in case you were thinking 7891263SN/A of expanding use. 7901263SN/A*/ 791837SN/Avoid 792879SN/ANSGigE::devIntrClear(uint32_t interrupts) 793837SN/A{ 794837SN/A if (interrupts & ISR_RESERVE) 795837SN/A panic("Cannot clear a reserved interrupt"); 796837SN/A 7971263SN/A if (regs.isr & regs.imr & ISR_SWI) { 7981263SN/A postedSwi++; 7991263SN/A } 8001263SN/A if (regs.isr & regs.imr & ISR_RXIDLE) { 8011263SN/A postedRxIdle++; 8021263SN/A } 8031263SN/A if (regs.isr & regs.imr & ISR_RXOK) { 8041263SN/A postedRxOk++; 8051263SN/A } 8061263SN/A if (regs.isr & regs.imr & ISR_RXDESC) { 8071263SN/A postedRxDesc++; 8081263SN/A } 8091263SN/A if (regs.isr & regs.imr & ISR_TXOK) { 8101263SN/A postedTxOk++; 8111263SN/A } 8121263SN/A if (regs.isr & regs.imr & ISR_TXIDLE) { 8131263SN/A postedTxIdle++; 8141263SN/A } 8151263SN/A if (regs.isr & regs.imr & ISR_TXDESC) { 8161263SN/A postedTxDesc++; 8171263SN/A } 8181263SN/A if (regs.isr & regs.imr & ISR_RXORN) { 8191263SN/A postedRxOrn++; 8201263SN/A } 8211263SN/A 8221057SN/A interrupts &= ~ISR_NOIMPL; 8231057SN/A regs.isr &= ~interrupts; 824837SN/A 8251027SN/A DPRINTF(EthernetIntr, 8261027SN/A "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 827881SN/A interrupts, regs.isr, regs.imr); 8281036SN/A 8291036SN/A if (!(regs.isr & regs.imr)) 8301036SN/A cpuIntrClear(); 831837SN/A} 832837SN/A 833837SN/Avoid 834879SN/ANSGigE::devIntrChangeMask() 835837SN/A{ 8361036SN/A DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 8371036SN/A regs.isr, regs.imr, regs.isr & regs.imr); 838837SN/A 839837SN/A if (regs.isr & regs.imr) 8407823SN/A cpuIntrPost(curTick()); 841837SN/A else 842837SN/A cpuIntrClear(); 843837SN/A} 844837SN/A 845837SN/Avoid 846879SN/ANSGigE::cpuIntrPost(Tick when) 847837SN/A{ 8481027SN/A // If the interrupt you want to post is later than an interrupt 8491027SN/A // already scheduled, just let it post in the coming one and don't 8501027SN/A // schedule another. 8511027SN/A // HOWEVER, must be sure that the scheduled intrTick is in the 8521027SN/A // future (this was formerly the source of a bug) 8531035SN/A /** 8541035SN/A * @todo this warning should be removed and the intrTick code should 8551035SN/A * be fixed. 8561035SN/A */ 8577823SN/A assert(when >= curTick()); 8587823SN/A assert(intrTick >= curTick() || intrTick == 0); 8591072SN/A if (when > intrTick && intrTick != 0) { 8601072SN/A DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 8611072SN/A intrTick); 8621072SN/A return; 8631035SN/A } 864854SN/A 865854SN/A intrTick = when; 8667823SN/A if (intrTick < curTick()) { 8677823SN/A intrTick = curTick(); 8681072SN/A } 8691072SN/A 8701072SN/A DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 8711072SN/A intrTick); 8721072SN/A 8731072SN/A if (intrEvent) 874854SN/A intrEvent->squash(); 87512087Sspwilson2@wisc.edu 87612087Sspwilson2@wisc.edu intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); }, 87712087Sspwilson2@wisc.edu name(), true); 8785606SN/A schedule(intrEvent, intrTick); 879854SN/A} 880854SN/A 881854SN/Avoid 882879SN/ANSGigE::cpuInterrupt() 883854SN/A{ 8847823SN/A assert(intrTick == curTick()); 8851072SN/A 8861072SN/A // Whether or not there's a pending interrupt, we don't care about 8871072SN/A // it anymore 8881072SN/A intrEvent = 0; 8891072SN/A intrTick = 0; 8901072SN/A 891854SN/A // Don't send an interrupt if there's already one 892927SN/A if (cpuPendingIntr) { 893927SN/A DPRINTF(EthernetIntr, 894927SN/A "would send an interrupt now, but there's already pending\n"); 8951072SN/A } else { 8961072SN/A // Send interrupt 8971072SN/A cpuPendingIntr = true; 8981072SN/A 8991149SN/A DPRINTF(EthernetIntr, "posting interrupt\n"); 9001149SN/A intrPost(); 901927SN/A } 902837SN/A} 903837SN/A 904837SN/Avoid 905879SN/ANSGigE::cpuIntrClear() 906837SN/A{ 9071027SN/A if (!cpuPendingIntr) 9081027SN/A return; 9091027SN/A 9101072SN/A if (intrEvent) { 9111072SN/A intrEvent->squash(); 9121072SN/A intrEvent = 0; 9131072SN/A } 9141072SN/A 9151072SN/A intrTick = 0; 9161072SN/A 9171027SN/A cpuPendingIntr = false; 9181057SN/A 9191149SN/A DPRINTF(EthernetIntr, "clearing interrupt\n"); 9201149SN/A intrClear(); 921837SN/A} 922837SN/A 923837SN/Abool 924879SN/ANSGigE::cpuIntrPending() const 925837SN/A{ return cpuPendingIntr; } 926837SN/A 927837SN/Avoid 928879SN/ANSGigE::txReset() 929837SN/A{ 930837SN/A 931837SN/A DPRINTF(Ethernet, "transmit reset\n"); 932837SN/A 933837SN/A CTDD = false; 9341035SN/A txEnable = false;; 935854SN/A txFragPtr = 0; 936854SN/A assert(txDescCnt == 0); 937837SN/A txFifo.clear(); 938837SN/A txState = txIdle; 939854SN/A assert(txDmaState == dmaIdle); 940837SN/A} 941837SN/A 942837SN/Avoid 943879SN/ANSGigE::rxReset() 944837SN/A{ 945837SN/A DPRINTF(Ethernet, "receive reset\n"); 946837SN/A 947837SN/A CRDD = false; 948854SN/A assert(rxPktBytes == 0); 9491035SN/A rxEnable = false; 950854SN/A rxFragPtr = 0; 951854SN/A assert(rxDescCnt == 0); 952854SN/A assert(rxDmaState == dmaIdle); 953837SN/A rxFifo.clear(); 954837SN/A rxState = rxIdle; 955837SN/A} 956837SN/A 9571036SN/Avoid 9581036SN/ANSGigE::regsReset() 959915SN/A{ 960915SN/A memset(®s, 0, sizeof(regs)); 9611817SN/A regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 9621843SN/A regs.mear = 0x12; 9631057SN/A regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 9641057SN/A // fill threshold to 32 bytes 9651057SN/A regs.rxcfg = 0x4; // set drain threshold to 16 bytes 9661057SN/A regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 9671057SN/A regs.mibc = MIBC_FRZ; 9681057SN/A regs.vdr = 0x81; // set the vlan tag type to 802.1q 9691057SN/A regs.tesr = 0xc000; // TBI capable of both full and half duplex 9701843SN/A regs.brar = 0xffffffff; 971927SN/A 972927SN/A extstsEnable = false; 973927SN/A acceptBroadcast = false; 974927SN/A acceptMulticast = false; 975927SN/A acceptUnicast = false; 976927SN/A acceptPerfect = false; 977927SN/A acceptArp = false; 978915SN/A} 979915SN/A 980854SN/Abool 981879SN/ANSGigE::doRxDmaRead() 982854SN/A{ 983854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 984854SN/A rxDmaState = dmaReading; 985854SN/A 98610913SN/A if (dmaPending() || drainState() != DrainState::Running) 9872566SN/A rxDmaState = dmaReadWaiting; 9882566SN/A else 9892566SN/A dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 9902566SN/A 991854SN/A return true; 992854SN/A} 993854SN/A 994854SN/Avoid 995879SN/ANSGigE::rxDmaReadDone() 996854SN/A{ 997854SN/A assert(rxDmaState == dmaReading); 9982566SN/A rxDmaState = dmaIdle; 9992566SN/A 10002566SN/A DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 10012566SN/A rxDmaAddr, rxDmaLen); 10022566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1003854SN/A 1004854SN/A // If the transmit state machine has a pending DMA, let it go first 1005854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1006854SN/A txKick(); 1007854SN/A 1008854SN/A rxKick(); 1009854SN/A} 1010854SN/A 1011854SN/Abool 1012879SN/ANSGigE::doRxDmaWrite() 1013854SN/A{ 1014854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1015854SN/A rxDmaState = dmaWriting; 1016854SN/A 101710913SN/A if (dmaPending() || drainState() != DrainState::Running) 10182566SN/A rxDmaState = dmaWriteWaiting; 10192566SN/A else 10202566SN/A dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 1021854SN/A return true; 1022854SN/A} 1023854SN/A 1024854SN/Avoid 1025879SN/ANSGigE::rxDmaWriteDone() 1026854SN/A{ 1027854SN/A assert(rxDmaState == dmaWriting); 10282566SN/A rxDmaState = dmaIdle; 10292566SN/A 10302566SN/A DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 10312566SN/A rxDmaAddr, rxDmaLen); 10322566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1033854SN/A 1034854SN/A // If the transmit state machine has a pending DMA, let it go first 1035854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1036854SN/A txKick(); 1037854SN/A 1038854SN/A rxKick(); 1039837SN/A} 1040837SN/A 1041837SN/Avoid 1042879SN/ANSGigE::rxKick() 1043837SN/A{ 10441909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 10451909SN/A 10461909SN/A DPRINTF(EthernetSM, 10471909SN/A "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 10481909SN/A NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 10491909SN/A 10501909SN/A Addr link, bufptr; 10511909SN/A uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 10521909SN/A uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1053837SN/A 10541801SN/A next: 10559417SN/A if (rxKickTick > curTick()) { 10569417SN/A DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 10579417SN/A rxKickTick); 10581801SN/A 10599417SN/A goto exit; 10609417SN/A } 10611801SN/A 10629417SN/A // Go to the next state machine clock tick. 10639417SN/A rxKickTick = clockEdge(Cycles(1)); 1064837SN/A 1065854SN/A switch(rxDmaState) { 1066854SN/A case dmaReadWaiting: 1067854SN/A if (doRxDmaRead()) 1068854SN/A goto exit; 1069854SN/A break; 1070854SN/A case dmaWriteWaiting: 1071854SN/A if (doRxDmaWrite()) 1072854SN/A goto exit; 1073854SN/A break; 1074854SN/A default: 1075854SN/A break; 1076854SN/A } 1077837SN/A 10781909SN/A link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 10791909SN/A bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 10801909SN/A 1081855SN/A // see state machine from spec for details 10821027SN/A // the way this works is, if you finish work on one state and can 10831027SN/A // go directly to another, you do that through jumping to the 10841027SN/A // label "next". however, if you have intermediate work, like DMA 10851027SN/A // so that you can't go to the next state yet, you go to exit and 10861027SN/A // exit the loop. however, when the DMA is done it will trigger 10871027SN/A // an event and come back to this loop. 1088854SN/A switch (rxState) { 1089854SN/A case rxIdle: 10901035SN/A if (!rxEnable) { 1091927SN/A DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1092854SN/A goto exit; 1093854SN/A } 1094837SN/A 1095854SN/A if (CRDD) { 1096854SN/A rxState = rxDescRefr; 1097837SN/A 1098854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 10991909SN/A rxDmaData = 11001909SN/A is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 11011909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1102854SN/A rxDmaFree = dmaDescFree; 1103854SN/A 1104961SN/A descDmaReads++; 1105961SN/A descDmaRdBytes += rxDmaLen; 1106961SN/A 1107854SN/A if (doRxDmaRead()) 1108854SN/A goto exit; 1109837SN/A } else { 1110837SN/A rxState = rxDescRead; 1111854SN/A 1112854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 11131909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 11141909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1115854SN/A rxDmaFree = dmaDescFree; 1116854SN/A 1117961SN/A descDmaReads++; 1118961SN/A descDmaRdBytes += rxDmaLen; 1119961SN/A 1120854SN/A if (doRxDmaRead()) 1121854SN/A goto exit; 1122837SN/A } 1123854SN/A break; 1124854SN/A 1125854SN/A case rxDescRefr: 1126854SN/A if (rxDmaState != dmaIdle) 1127854SN/A goto exit; 1128854SN/A 1129854SN/A rxState = rxAdvance; 1130854SN/A break; 1131854SN/A 1132854SN/A case rxDescRead: 1133854SN/A if (rxDmaState != dmaIdle) 1134854SN/A goto exit; 1135854SN/A 11361909SN/A DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 11371036SN/A regs.rxdp & 0x3fffffff); 11381036SN/A DPRINTF(EthernetDesc, 11391909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 11401909SN/A link, bufptr, cmdsts, extsts); 11411909SN/A 11421909SN/A if (cmdsts & CMDSTS_OWN) { 11431035SN/A devIntrPost(ISR_RXIDLE); 1144837SN/A rxState = rxIdle; 11451035SN/A goto exit; 1146837SN/A } else { 1147837SN/A rxState = rxFifoBlock; 11481909SN/A rxFragPtr = bufptr; 11491909SN/A rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1150854SN/A } 1151854SN/A break; 1152837SN/A 1153854SN/A case rxFifoBlock: 1154854SN/A if (!rxPacket) { 1155854SN/A /** 1156854SN/A * @todo in reality, we should be able to start processing 1157854SN/A * the packet as it arrives, and not have to wait for the 1158854SN/A * full packet ot be in the receive fifo. 1159854SN/A */ 1160854SN/A if (rxFifo.empty()) 1161854SN/A goto exit; 1162854SN/A 11631036SN/A DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1164927SN/A 1165854SN/A // If we don't have a packet, grab a new one from the fifo. 1166854SN/A rxPacket = rxFifo.front(); 1167854SN/A rxPktBytes = rxPacket->length; 1168854SN/A rxPacketBufPtr = rxPacket->data; 1169854SN/A 11701011SN/A#if TRACING_ON 1171927SN/A if (DTRACE(Ethernet)) { 11721114SN/A IpPtr ip(rxPacket); 11731078SN/A if (ip) { 11741078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 11751114SN/A TcpPtr tcp(ip); 11761078SN/A if (tcp) { 11771561SN/A DPRINTF(Ethernet, 11781561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 11791561SN/A tcp->sport(), tcp->dport(), tcp->seq(), 11801561SN/A tcp->ack()); 1181927SN/A } 1182927SN/A } 1183927SN/A } 11841011SN/A#endif 1185927SN/A 1186854SN/A // sanity check - i think the driver behaves like this 1187854SN/A assert(rxDescCnt >= rxPktBytes); 11881154SN/A rxFifo.pop(); 1189837SN/A } 1190837SN/A 1191837SN/A 11921027SN/A // dont' need the && rxDescCnt > 0 if driver sanity check 11931027SN/A // above holds 1194854SN/A if (rxPktBytes > 0) { 1195854SN/A rxState = rxFragWrite; 11961027SN/A // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 11971027SN/A // check holds 1198854SN/A rxXferLen = rxPktBytes; 1199854SN/A 1200854SN/A rxDmaAddr = rxFragPtr & 0x3fffffff; 1201854SN/A rxDmaData = rxPacketBufPtr; 1202854SN/A rxDmaLen = rxXferLen; 1203854SN/A rxDmaFree = dmaDataFree; 1204854SN/A 1205854SN/A if (doRxDmaWrite()) 1206854SN/A goto exit; 1207854SN/A 1208837SN/A } else { 1209854SN/A rxState = rxDescWrite; 1210837SN/A 1211854SN/A //if (rxPktBytes == 0) { /* packet is done */ 1212854SN/A assert(rxPktBytes == 0); 1213927SN/A DPRINTF(EthernetSM, "done with receiving packet\n"); 1214837SN/A 12151909SN/A cmdsts |= CMDSTS_OWN; 12161909SN/A cmdsts &= ~CMDSTS_MORE; 12171909SN/A cmdsts |= CMDSTS_OK; 12181909SN/A cmdsts &= 0xffff0000; 12191909SN/A cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1220837SN/A 12211114SN/A IpPtr ip(rxPacket); 12221114SN/A if (extstsEnable && ip) { 12231909SN/A extsts |= EXTSTS_IPPKT; 12241078SN/A rxIpChecksums++; 12251114SN/A if (cksum(ip) != 0) { 1226927SN/A DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 12271909SN/A extsts |= EXTSTS_IPERR; 1228927SN/A } 12291114SN/A TcpPtr tcp(ip); 12301114SN/A UdpPtr udp(ip); 12311114SN/A if (tcp) { 12321909SN/A extsts |= EXTSTS_TCPPKT; 12331078SN/A rxTcpChecksums++; 12341114SN/A if (cksum(tcp) != 0) { 1235927SN/A DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 12361909SN/A extsts |= EXTSTS_TCPERR; 1237961SN/A 1238927SN/A } 12391114SN/A } else if (udp) { 12401909SN/A extsts |= EXTSTS_UDPPKT; 12411078SN/A rxUdpChecksums++; 12421114SN/A if (cksum(udp) != 0) { 1243927SN/A DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 12441909SN/A extsts |= EXTSTS_UDPERR; 1245927SN/A } 1246837SN/A } 1247837SN/A } 1248881SN/A rxPacket = 0; 1249881SN/A 12501027SN/A /* 12511027SN/A * the driver seems to always receive into desc buffers 12521027SN/A * of size 1514, so you never have a pkt that is split 12531027SN/A * into multiple descriptors on the receive side, so 12541027SN/A * i don't implement that case, hence the assert above. 12551027SN/A */ 12561027SN/A 12571027SN/A DPRINTF(EthernetDesc, 12581909SN/A "rxDesc: addr=%08x writeback cmdsts extsts\n", 12591036SN/A regs.rxdp & 0x3fffffff); 12601036SN/A DPRINTF(EthernetDesc, 12611909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 12621909SN/A link, bufptr, cmdsts, extsts); 12631909SN/A 12641909SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 12651909SN/A rxDmaData = &cmdsts; 12661909SN/A if (is64bit) { 12671909SN/A rxDmaAddr += offsetof(ns_desc64, cmdsts); 12681909SN/A rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 12691909SN/A } else { 12701909SN/A rxDmaAddr += offsetof(ns_desc32, cmdsts); 12711909SN/A rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 12721909SN/A } 1273854SN/A rxDmaFree = dmaDescFree; 1274854SN/A 1275961SN/A descDmaWrites++; 1276961SN/A descDmaWrBytes += rxDmaLen; 1277961SN/A 1278854SN/A if (doRxDmaWrite()) 1279854SN/A goto exit; 1280837SN/A } 1281854SN/A break; 1282837SN/A 1283854SN/A case rxFragWrite: 1284854SN/A if (rxDmaState != dmaIdle) 1285854SN/A goto exit; 1286854SN/A 1287854SN/A rxPacketBufPtr += rxXferLen; 1288854SN/A rxFragPtr += rxXferLen; 1289854SN/A rxPktBytes -= rxXferLen; 1290854SN/A 1291854SN/A rxState = rxFifoBlock; 1292854SN/A break; 1293854SN/A 1294854SN/A case rxDescWrite: 1295854SN/A if (rxDmaState != dmaIdle) 1296854SN/A goto exit; 1297854SN/A 12981909SN/A assert(cmdsts & CMDSTS_OWN); 1299854SN/A 1300854SN/A assert(rxPacket == 0); 1301854SN/A devIntrPost(ISR_RXOK); 1302854SN/A 13031909SN/A if (cmdsts & CMDSTS_INTR) 1304854SN/A devIntrPost(ISR_RXDESC); 1305854SN/A 13061035SN/A if (!rxEnable) { 1307927SN/A DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1308854SN/A rxState = rxIdle; 13091035SN/A goto exit; 1310854SN/A } else 1311854SN/A rxState = rxAdvance; 1312854SN/A break; 1313854SN/A 1314854SN/A case rxAdvance: 13151909SN/A if (link == 0) { 13161035SN/A devIntrPost(ISR_RXIDLE); 1317854SN/A rxState = rxIdle; 13181035SN/A CRDD = true; 13191035SN/A goto exit; 1320854SN/A } else { 13211893SN/A if (rxDmaState != dmaIdle) 13221893SN/A goto exit; 1323854SN/A rxState = rxDescRead; 13241909SN/A regs.rxdp = link; 1325854SN/A CRDD = false; 1326854SN/A 1327854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 13281909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 13291909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1330854SN/A rxDmaFree = dmaDescFree; 1331854SN/A 1332854SN/A if (doRxDmaRead()) 1333854SN/A goto exit; 1334854SN/A } 1335854SN/A break; 1336854SN/A 1337854SN/A default: 1338854SN/A panic("Invalid rxState!"); 1339837SN/A } 1340837SN/A 13411036SN/A DPRINTF(EthernetSM, "entering next rxState=%s\n", 1342854SN/A NsRxStateStrings[rxState]); 1343854SN/A goto next; 1344837SN/A 1345854SN/A exit: 1346854SN/A /** 1347854SN/A * @todo do we want to schedule a future kick? 1348854SN/A */ 13491036SN/A DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1350854SN/A NsRxStateStrings[rxState]); 13511801SN/A 13529417SN/A if (!rxKickEvent.scheduled()) 13535606SN/A schedule(rxKickEvent, rxKickTick); 1354837SN/A} 1355837SN/A 1356837SN/Avoid 1357879SN/ANSGigE::transmit() 1358837SN/A{ 1359837SN/A if (txFifo.empty()) { 1360837SN/A DPRINTF(Ethernet, "nothing to transmit\n"); 1361837SN/A return; 1362837SN/A } 1363837SN/A 13641036SN/A DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 13651154SN/A txFifo.size()); 1366927SN/A if (interface->sendPacket(txFifo.front())) { 13671011SN/A#if TRACING_ON 1368927SN/A if (DTRACE(Ethernet)) { 13691114SN/A IpPtr ip(txFifo.front()); 13701078SN/A if (ip) { 13711078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 13721114SN/A TcpPtr tcp(ip); 13731078SN/A if (tcp) { 13741561SN/A DPRINTF(Ethernet, 13751561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 13761909SN/A tcp->sport(), tcp->dport(), tcp->seq(), 13771909SN/A tcp->ack()); 1378927SN/A } 1379927SN/A } 1380927SN/A } 13811011SN/A#endif 1382927SN/A 13831561SN/A DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1384837SN/A txBytes += txFifo.front()->length; 1385837SN/A txPackets++; 1386837SN/A 13871027SN/A DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 13881154SN/A txFifo.avail()); 13891154SN/A txFifo.pop(); 1390837SN/A 13911027SN/A /* 13921027SN/A * normally do a writeback of the descriptor here, and ONLY 13931027SN/A * after that is done, send this interrupt. but since our 13941027SN/A * stuff never actually fails, just do this interrupt here, 13951027SN/A * otherwise the code has to stray from this nice format. 13961027SN/A * besides, it's functionally the same. 13971027SN/A */ 1398854SN/A devIntrPost(ISR_TXOK); 13991027SN/A } 1400854SN/A 1401854SN/A if (!txFifo.empty() && !txEvent.scheduled()) { 1402854SN/A DPRINTF(Ethernet, "reschedule transmit\n"); 14037823SN/A schedule(txEvent, curTick() + retryTime); 1404854SN/A } 1405854SN/A} 1406854SN/A 1407854SN/Abool 1408879SN/ANSGigE::doTxDmaRead() 1409854SN/A{ 1410854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1411854SN/A txDmaState = dmaReading; 1412854SN/A 141310913SN/A if (dmaPending() || drainState() != DrainState::Running) 14142566SN/A txDmaState = dmaReadWaiting; 14152566SN/A else 14162566SN/A dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 14172566SN/A 1418854SN/A return true; 1419854SN/A} 1420837SN/A 1421854SN/Avoid 1422879SN/ANSGigE::txDmaReadDone() 1423854SN/A{ 1424854SN/A assert(txDmaState == dmaReading); 14252566SN/A txDmaState = dmaIdle; 14262566SN/A 14272566SN/A DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 14282566SN/A txDmaAddr, txDmaLen); 14292566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1430837SN/A 1431854SN/A // If the receive state machine has a pending DMA, let it go first 1432854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1433854SN/A rxKick(); 1434837SN/A 1435854SN/A txKick(); 1436854SN/A} 1437837SN/A 1438854SN/Abool 1439879SN/ANSGigE::doTxDmaWrite() 1440854SN/A{ 1441854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1442854SN/A txDmaState = dmaWriting; 1443854SN/A 144410913SN/A if (dmaPending() || drainState() != DrainState::Running) 14452566SN/A txDmaState = dmaWriteWaiting; 14462566SN/A else 14472566SN/A dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1448854SN/A return true; 1449854SN/A} 1450854SN/A 1451854SN/Avoid 1452879SN/ANSGigE::txDmaWriteDone() 1453854SN/A{ 1454854SN/A assert(txDmaState == dmaWriting); 14552566SN/A txDmaState = dmaIdle; 14562566SN/A 14572566SN/A DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 14582566SN/A txDmaAddr, txDmaLen); 14592566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1460854SN/A 1461854SN/A // If the receive state machine has a pending DMA, let it go first 1462854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1463854SN/A rxKick(); 1464854SN/A 1465854SN/A txKick(); 1466837SN/A} 1467837SN/A 1468837SN/Avoid 1469879SN/ANSGigE::txKick() 1470837SN/A{ 14711909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 14721909SN/A 14731909SN/A DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 14741909SN/A NsTxStateStrings[txState], is64bit ? 64 : 32); 14751909SN/A 14761909SN/A Addr link, bufptr; 14771909SN/A uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 14781909SN/A uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1479927SN/A 14801801SN/A next: 14819417SN/A if (txKickTick > curTick()) { 14829417SN/A DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 14839417SN/A txKickTick); 14849417SN/A goto exit; 14859417SN/A } 14861801SN/A 14879417SN/A // Go to the next state machine clock tick. 14889417SN/A txKickTick = clockEdge(Cycles(1)); 1489837SN/A 1490854SN/A switch(txDmaState) { 1491854SN/A case dmaReadWaiting: 1492854SN/A if (doTxDmaRead()) 1493854SN/A goto exit; 1494854SN/A break; 1495854SN/A case dmaWriteWaiting: 1496854SN/A if (doTxDmaWrite()) 1497854SN/A goto exit; 1498854SN/A break; 1499854SN/A default: 1500854SN/A break; 1501854SN/A } 1502837SN/A 15031909SN/A link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 15041909SN/A bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1505854SN/A switch (txState) { 1506854SN/A case txIdle: 15071035SN/A if (!txEnable) { 1508927SN/A DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1509854SN/A goto exit; 1510854SN/A } 1511837SN/A 1512854SN/A if (CTDD) { 1513854SN/A txState = txDescRefr; 1514837SN/A 1515881SN/A txDmaAddr = regs.txdp & 0x3fffffff; 15161909SN/A txDmaData = 15171909SN/A is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 15181909SN/A txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1519854SN/A txDmaFree = dmaDescFree; 1520837SN/A 1521961SN/A descDmaReads++; 1522961SN/A descDmaRdBytes += txDmaLen; 1523961SN/A 1524854SN/A if (doTxDmaRead()) 1525854SN/A goto exit; 1526854SN/A 1527854SN/A } else { 1528854SN/A txState = txDescRead; 1529854SN/A 1530854SN/A txDmaAddr = regs.txdp & 0x3fffffff; 15311909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 15321909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1533854SN/A txDmaFree = dmaDescFree; 1534854SN/A 1535961SN/A descDmaReads++; 1536961SN/A descDmaRdBytes += txDmaLen; 1537961SN/A 1538854SN/A if (doTxDmaRead()) 1539854SN/A goto exit; 1540837SN/A } 1541854SN/A break; 1542837SN/A 1543854SN/A case txDescRefr: 1544854SN/A if (txDmaState != dmaIdle) 1545854SN/A goto exit; 1546854SN/A 1547854SN/A txState = txAdvance; 1548854SN/A break; 1549854SN/A 1550854SN/A case txDescRead: 1551854SN/A if (txDmaState != dmaIdle) 1552854SN/A goto exit; 1553854SN/A 15541909SN/A DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 15551801SN/A regs.txdp & 0x3fffffff); 1556927SN/A DPRINTF(EthernetDesc, 15571909SN/A "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 15581909SN/A link, bufptr, cmdsts, extsts); 15591909SN/A 15601909SN/A if (cmdsts & CMDSTS_OWN) { 1561854SN/A txState = txFifoBlock; 15621909SN/A txFragPtr = bufptr; 15631909SN/A txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1564854SN/A } else { 15651035SN/A devIntrPost(ISR_TXIDLE); 1566854SN/A txState = txIdle; 15671035SN/A goto exit; 1568854SN/A } 1569854SN/A break; 1570854SN/A 1571854SN/A case txFifoBlock: 1572854SN/A if (!txPacket) { 15731036SN/A DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 157410469SN/A txPacket = make_shared<EthPacketData>(16384); 1575854SN/A txPacketBufPtr = txPacket->data; 1576854SN/A } 1577854SN/A 1578854SN/A if (txDescCnt == 0) { 1579927SN/A DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 15801909SN/A if (cmdsts & CMDSTS_MORE) { 1581927SN/A DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1582854SN/A txState = txDescWrite; 1583854SN/A 15841909SN/A cmdsts &= ~CMDSTS_OWN; 15851909SN/A 15861909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 15871909SN/A txDmaData = &cmdsts; 15881909SN/A if (is64bit) { 15891909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 15901909SN/A txDmaLen = sizeof(txDesc64.cmdsts); 15911909SN/A } else { 15921909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 15931909SN/A txDmaLen = sizeof(txDesc32.cmdsts); 15941909SN/A } 1595854SN/A txDmaFree = dmaDescFree; 1596854SN/A 1597854SN/A if (doTxDmaWrite()) 1598854SN/A goto exit; 1599854SN/A 1600854SN/A } else { /* this packet is totally done */ 1601927SN/A DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1602854SN/A /* deal with the the packet that just finished */ 1603854SN/A if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 16041114SN/A IpPtr ip(txPacket); 16051909SN/A if (extsts & EXTSTS_UDPPKT) { 16061114SN/A UdpPtr udp(ip); 16075484SN/A if (udp) { 16085484SN/A udp->sum(0); 16095484SN/A udp->sum(cksum(udp)); 16105484SN/A txUdpChecksums++; 16115484SN/A } else { 16128231SN/A Debug::breakpoint(); 16135484SN/A warn_once("UDPPKT set, but not UDP!\n"); 16145484SN/A } 16151909SN/A } else if (extsts & EXTSTS_TCPPKT) { 16161114SN/A TcpPtr tcp(ip); 16175484SN/A if (tcp) { 16185484SN/A tcp->sum(0); 16195484SN/A tcp->sum(cksum(tcp)); 16205484SN/A txTcpChecksums++; 16215484SN/A } else { 16225484SN/A warn_once("TCPPKT set, but not UDP!\n"); 16235484SN/A } 1624944SN/A } 16251909SN/A if (extsts & EXTSTS_IPPKT) { 16265484SN/A if (ip) { 16275484SN/A ip->sum(0); 16285484SN/A ip->sum(cksum(ip)); 16295484SN/A txIpChecksums++; 16305484SN/A } else { 16315484SN/A warn_once("IPPKT set, but not UDP!\n"); 16325484SN/A } 1633854SN/A } 1634854SN/A } 1635854SN/A 163611701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 1637854SN/A txPacket->length = txPacketBufPtr - txPacket->data; 16381027SN/A // this is just because the receive can't handle a 16391027SN/A // packet bigger want to make sure 16401909SN/A if (txPacket->length > 1514) 16411909SN/A panic("transmit packet too large, %s > 1514\n", 16421909SN/A txPacket->length); 16431909SN/A 16441205SN/A#ifndef NDEBUG 16451205SN/A bool success = 16461205SN/A#endif 16471205SN/A txFifo.push(txPacket); 16481205SN/A assert(success); 1649854SN/A 16501027SN/A /* 16511027SN/A * this following section is not tqo spec, but 16521027SN/A * functionally shouldn't be any different. normally, 16531027SN/A * the chip will wait til the transmit has occurred 16541027SN/A * before writing back the descriptor because it has 16551027SN/A * to wait to see that it was successfully transmitted 16561027SN/A * to decide whether to set CMDSTS_OK or not. 16571027SN/A * however, in the simulator since it is always 16581027SN/A * successfully transmitted, and writing it exactly to 16591027SN/A * spec would complicate the code, we just do it here 16601027SN/A */ 1661927SN/A 16621909SN/A cmdsts &= ~CMDSTS_OWN; 16631909SN/A cmdsts |= CMDSTS_OK; 1664854SN/A 1665927SN/A DPRINTF(EthernetDesc, 16661036SN/A "txDesc writeback: cmdsts=%08x extsts=%08x\n", 16671909SN/A cmdsts, extsts); 16681909SN/A 1669854SN/A txDmaFree = dmaDescFree; 16701909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16711909SN/A txDmaData = &cmdsts; 16721909SN/A if (is64bit) { 16731909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 16741909SN/A txDmaLen = 16751909SN/A sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 16761909SN/A } else { 16771909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 16781909SN/A txDmaLen = 16791909SN/A sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 16801909SN/A } 1681854SN/A 1682961SN/A descDmaWrites++; 1683961SN/A descDmaWrBytes += txDmaLen; 1684961SN/A 1685927SN/A transmit(); 1686854SN/A txPacket = 0; 1687854SN/A 16881035SN/A if (!txEnable) { 1689927SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 1690854SN/A txState = txIdle; 16911035SN/A goto exit; 1692854SN/A } else 1693854SN/A txState = txAdvance; 1694986SN/A 1695986SN/A if (doTxDmaWrite()) 1696986SN/A goto exit; 1697854SN/A } 1698854SN/A } else { 1699927SN/A DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 17001154SN/A if (!txFifo.full()) { 1701992SN/A txState = txFragRead; 1702992SN/A 17031027SN/A /* 17041027SN/A * The number of bytes transferred is either whatever 17051027SN/A * is left in the descriptor (txDescCnt), or if there 17061027SN/A * is not enough room in the fifo, just whatever room 17071027SN/A * is left in the fifo 17081027SN/A */ 17091154SN/A txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 1710992SN/A 1711992SN/A txDmaAddr = txFragPtr & 0x3fffffff; 1712992SN/A txDmaData = txPacketBufPtr; 1713992SN/A txDmaLen = txXferLen; 1714992SN/A txDmaFree = dmaDataFree; 1715992SN/A 1716992SN/A if (doTxDmaRead()) 1717992SN/A goto exit; 1718992SN/A } else { 1719992SN/A txState = txFifoBlock; 1720992SN/A transmit(); 1721992SN/A 1722998SN/A goto exit; 1723992SN/A } 1724992SN/A 1725854SN/A } 1726854SN/A break; 1727854SN/A 1728854SN/A case txFragRead: 1729854SN/A if (txDmaState != dmaIdle) 1730854SN/A goto exit; 1731854SN/A 1732854SN/A txPacketBufPtr += txXferLen; 1733854SN/A txFragPtr += txXferLen; 1734854SN/A txDescCnt -= txXferLen; 17351205SN/A txFifo.reserve(txXferLen); 1736854SN/A 1737854SN/A txState = txFifoBlock; 1738854SN/A break; 1739854SN/A 1740854SN/A case txDescWrite: 1741854SN/A if (txDmaState != dmaIdle) 1742854SN/A goto exit; 1743854SN/A 17441909SN/A if (cmdsts & CMDSTS_INTR) 1745854SN/A devIntrPost(ISR_TXDESC); 1746854SN/A 17471801SN/A if (!txEnable) { 17481801SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 17491801SN/A txState = txIdle; 17501801SN/A goto exit; 17511801SN/A } else 17521801SN/A txState = txAdvance; 1753854SN/A break; 1754854SN/A 1755854SN/A case txAdvance: 17561909SN/A if (link == 0) { 17571035SN/A devIntrPost(ISR_TXIDLE); 1758837SN/A txState = txIdle; 17591035SN/A goto exit; 1760837SN/A } else { 17611893SN/A if (txDmaState != dmaIdle) 17621893SN/A goto exit; 1763837SN/A txState = txDescRead; 17641909SN/A regs.txdp = link; 1765837SN/A CTDD = false; 1766854SN/A 17671909SN/A txDmaAddr = link & 0x3fffffff; 17681909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 17691909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1770854SN/A txDmaFree = dmaDescFree; 1771854SN/A 1772854SN/A if (doTxDmaRead()) 1773854SN/A goto exit; 1774837SN/A } 1775854SN/A break; 1776837SN/A 1777854SN/A default: 1778854SN/A panic("invalid state"); 1779837SN/A } 1780837SN/A 17811036SN/A DPRINTF(EthernetSM, "entering next txState=%s\n", 1782854SN/A NsTxStateStrings[txState]); 1783854SN/A goto next; 1784837SN/A 1785854SN/A exit: 1786854SN/A /** 1787854SN/A * @todo do we want to schedule a future kick? 1788854SN/A */ 17891036SN/A DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1790854SN/A NsTxStateStrings[txState]); 17911801SN/A 17929417SN/A if (!txKickEvent.scheduled()) 17935606SN/A schedule(txKickEvent, txKickTick); 1794837SN/A} 1795837SN/A 17961843SN/A/** 17971843SN/A * Advance the EEPROM state machine 17981843SN/A * Called on rising edge of EEPROM clock bit in MEAR 17991843SN/A */ 18001843SN/Avoid 18011843SN/ANSGigE::eepromKick() 18021843SN/A{ 18031843SN/A switch (eepromState) { 18041843SN/A 18051843SN/A case eepromStart: 18061843SN/A 18071843SN/A // Wait for start bit 18081843SN/A if (regs.mear & MEAR_EEDI) { 18091843SN/A // Set up to get 2 opcode bits 18101843SN/A eepromState = eepromGetOpcode; 18111843SN/A eepromBitsToRx = 2; 18121843SN/A eepromOpcode = 0; 18131843SN/A } 18141843SN/A break; 18151843SN/A 18161843SN/A case eepromGetOpcode: 18171843SN/A eepromOpcode <<= 1; 18181843SN/A eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 18191843SN/A --eepromBitsToRx; 18201843SN/A 18211843SN/A // Done getting opcode 18221843SN/A if (eepromBitsToRx == 0) { 18231843SN/A if (eepromOpcode != EEPROM_READ) 18241843SN/A panic("only EEPROM reads are implemented!"); 18251843SN/A 18261843SN/A // Set up to get address 18271843SN/A eepromState = eepromGetAddress; 18281843SN/A eepromBitsToRx = 6; 18291843SN/A eepromAddress = 0; 18301843SN/A } 18311843SN/A break; 18321843SN/A 18331843SN/A case eepromGetAddress: 18341843SN/A eepromAddress <<= 1; 18351843SN/A eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 18361843SN/A --eepromBitsToRx; 18371843SN/A 18381843SN/A // Done getting address 18391843SN/A if (eepromBitsToRx == 0) { 18401843SN/A 18411843SN/A if (eepromAddress >= EEPROM_SIZE) 18421843SN/A panic("EEPROM read access out of range!"); 18431843SN/A 18441843SN/A switch (eepromAddress) { 18451843SN/A 18461843SN/A case EEPROM_PMATCH2_ADDR: 18471843SN/A eepromData = rom.perfectMatch[5]; 18481843SN/A eepromData <<= 8; 18491843SN/A eepromData += rom.perfectMatch[4]; 18501843SN/A break; 18511843SN/A 18521843SN/A case EEPROM_PMATCH1_ADDR: 18531843SN/A eepromData = rom.perfectMatch[3]; 18541843SN/A eepromData <<= 8; 18551843SN/A eepromData += rom.perfectMatch[2]; 18561843SN/A break; 18571843SN/A 18581843SN/A case EEPROM_PMATCH0_ADDR: 18591843SN/A eepromData = rom.perfectMatch[1]; 18601843SN/A eepromData <<= 8; 18611843SN/A eepromData += rom.perfectMatch[0]; 18621843SN/A break; 18631843SN/A 18641843SN/A default: 18651843SN/A panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 18661843SN/A } 18671843SN/A // Set up to read data 18681843SN/A eepromState = eepromRead; 18691843SN/A eepromBitsToRx = 16; 18701843SN/A 18711843SN/A // Clear data in bit 18721843SN/A regs.mear &= ~MEAR_EEDI; 18731843SN/A } 18741843SN/A break; 18751843SN/A 18761843SN/A case eepromRead: 18771843SN/A // Clear Data Out bit 18781843SN/A regs.mear &= ~MEAR_EEDO; 18791843SN/A // Set bit to value of current EEPROM bit 18801843SN/A regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 18811843SN/A 18821843SN/A eepromData <<= 1; 18831843SN/A --eepromBitsToRx; 18841843SN/A 18851843SN/A // All done 18861843SN/A if (eepromBitsToRx == 0) { 18871843SN/A eepromState = eepromStart; 18881843SN/A } 18891843SN/A break; 18901843SN/A 18911843SN/A default: 18921843SN/A panic("invalid EEPROM state"); 18931843SN/A } 18941843SN/A 18951843SN/A} 18961843SN/A 1897837SN/Avoid 1898879SN/ANSGigE::transferDone() 1899837SN/A{ 19001036SN/A if (txFifo.empty()) { 19011036SN/A DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1902837SN/A return; 19031036SN/A } 19041036SN/A 19051036SN/A DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1906837SN/A 19079417SN/A reschedule(txEvent, clockEdge(Cycles(1)), true); 1908837SN/A} 1909837SN/A 1910837SN/Abool 19112566SN/ANSGigE::rxFilter(const EthPacketPtr &packet) 1912837SN/A{ 19131114SN/A EthPtr eth = packet; 1914837SN/A bool drop = true; 1915837SN/A string type; 1916837SN/A 19171114SN/A const EthAddr &dst = eth->dst(); 19181114SN/A if (dst.unicast()) { 1919837SN/A // If we're accepting all unicast addresses 1920837SN/A if (acceptUnicast) 1921837SN/A drop = false; 1922837SN/A 1923837SN/A // If we make a perfect match 19241114SN/A if (acceptPerfect && dst == rom.perfectMatch) 1925837SN/A drop = false; 1926837SN/A 19271078SN/A if (acceptArp && eth->type() == ETH_TYPE_ARP) 1928837SN/A drop = false; 1929837SN/A 19301114SN/A } else if (dst.broadcast()) { 1931837SN/A // if we're accepting broadcasts 1932837SN/A if (acceptBroadcast) 1933837SN/A drop = false; 1934837SN/A 19351114SN/A } else if (dst.multicast()) { 1936837SN/A // if we're accepting all multicasts 1937837SN/A if (acceptMulticast) 1938837SN/A drop = false; 1939837SN/A 19401843SN/A // Multicast hashing faked - all packets accepted 19411843SN/A if (multicastHashEnable) 19421843SN/A drop = false; 1943837SN/A } 1944837SN/A 1945837SN/A if (drop) { 1946837SN/A DPRINTF(Ethernet, "rxFilter drop\n"); 1947837SN/A DDUMP(EthernetData, packet->data, packet->length); 1948837SN/A } 1949837SN/A 1950837SN/A return drop; 1951837SN/A} 1952837SN/A 1953837SN/Abool 19542566SN/ANSGigE::recvPacket(EthPacketPtr packet) 1955837SN/A{ 1956837SN/A rxBytes += packet->length; 1957837SN/A rxPackets++; 1958837SN/A 19591036SN/A DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 19601154SN/A rxFifo.avail()); 1961927SN/A 19621035SN/A if (!rxEnable) { 1963837SN/A DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1964837SN/A return true; 1965837SN/A } 1966837SN/A 19671843SN/A if (!rxFilterEnable) { 19681843SN/A DPRINTF(Ethernet, 19691843SN/A "receive packet filtering disabled . . . packet dropped\n"); 19701843SN/A return true; 19711843SN/A } 19721843SN/A 19731843SN/A if (rxFilter(packet)) { 1974837SN/A DPRINTF(Ethernet, "packet filtered...dropped\n"); 1975837SN/A return true; 1976837SN/A } 1977837SN/A 19781154SN/A if (rxFifo.avail() < packet->length) { 19791561SN/A#if TRACING_ON 19801561SN/A IpPtr ip(packet); 19811561SN/A TcpPtr tcp(ip); 19821561SN/A if (ip) { 19831561SN/A DPRINTF(Ethernet, 19841561SN/A "packet won't fit in receive buffer...pkt ID %d dropped\n", 19851561SN/A ip->id()); 19861561SN/A if (tcp) { 19871561SN/A DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 19881561SN/A } 19891561SN/A } 19901561SN/A#endif 19911263SN/A droppedPackets++; 1992837SN/A devIntrPost(ISR_RXORN); 1993837SN/A return false; 1994837SN/A } 1995837SN/A 19961154SN/A rxFifo.push(packet); 1997837SN/A 1998854SN/A rxKick(); 1999837SN/A return true; 2000837SN/A} 2001837SN/A 20022901SN/A 20032901SN/Avoid 20049342SN/ANSGigE::drainResume() 20052901SN/A{ 20069342SN/A Drainable::drainResume(); 20072901SN/A 20082901SN/A // During drain we could have left the state machines in a waiting state and 20092901SN/A // they wouldn't get out until some other event occured to kick them. 20102901SN/A // This way they'll get out immediately 20112901SN/A txKick(); 20122901SN/A rxKick(); 20132901SN/A} 20142901SN/A 20152901SN/A 2016837SN/A//===================================================================== 2017837SN/A// 2018837SN/A// 2019837SN/Avoid 202010905SN/ANSGigE::serialize(CheckpointOut &cp) const 2021837SN/A{ 20229807SN/A // Serialize the PciDevice base class 202310905SN/A PciDevice::serialize(cp); 2024897SN/A 2025854SN/A /* 2026854SN/A * Finalize any DMA events now. 2027854SN/A */ 20282566SN/A // @todo will mem system save pending dma? 2029837SN/A 2030854SN/A /* 2031854SN/A * Serialize the device registers 2032854SN/A */ 2033854SN/A SERIALIZE_SCALAR(regs.command); 2034854SN/A SERIALIZE_SCALAR(regs.config); 2035854SN/A SERIALIZE_SCALAR(regs.mear); 2036854SN/A SERIALIZE_SCALAR(regs.ptscr); 2037854SN/A SERIALIZE_SCALAR(regs.isr); 2038854SN/A SERIALIZE_SCALAR(regs.imr); 2039854SN/A SERIALIZE_SCALAR(regs.ier); 2040854SN/A SERIALIZE_SCALAR(regs.ihr); 2041854SN/A SERIALIZE_SCALAR(regs.txdp); 2042854SN/A SERIALIZE_SCALAR(regs.txdp_hi); 2043854SN/A SERIALIZE_SCALAR(regs.txcfg); 2044854SN/A SERIALIZE_SCALAR(regs.gpior); 2045854SN/A SERIALIZE_SCALAR(regs.rxdp); 2046854SN/A SERIALIZE_SCALAR(regs.rxdp_hi); 2047854SN/A SERIALIZE_SCALAR(regs.rxcfg); 2048854SN/A SERIALIZE_SCALAR(regs.pqcr); 2049854SN/A SERIALIZE_SCALAR(regs.wcsr); 2050854SN/A SERIALIZE_SCALAR(regs.pcr); 2051854SN/A SERIALIZE_SCALAR(regs.rfcr); 2052854SN/A SERIALIZE_SCALAR(regs.rfdr); 20531843SN/A SERIALIZE_SCALAR(regs.brar); 20541843SN/A SERIALIZE_SCALAR(regs.brdr); 2055854SN/A SERIALIZE_SCALAR(regs.srr); 2056854SN/A SERIALIZE_SCALAR(regs.mibc); 2057854SN/A SERIALIZE_SCALAR(regs.vrcr); 2058854SN/A SERIALIZE_SCALAR(regs.vtcr); 2059854SN/A SERIALIZE_SCALAR(regs.vdr); 2060854SN/A SERIALIZE_SCALAR(regs.ccsr); 2061854SN/A SERIALIZE_SCALAR(regs.tbicr); 2062854SN/A SERIALIZE_SCALAR(regs.tbisr); 2063854SN/A SERIALIZE_SCALAR(regs.tanar); 2064854SN/A SERIALIZE_SCALAR(regs.tanlpar); 2065854SN/A SERIALIZE_SCALAR(regs.taner); 2066854SN/A SERIALIZE_SCALAR(regs.tesr); 2067837SN/A 20681114SN/A SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 20691843SN/A SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2070837SN/A 2071927SN/A SERIALIZE_SCALAR(ioEnable); 2072917SN/A 2073854SN/A /* 2074915SN/A * Serialize the data Fifos 2075915SN/A */ 207610905SN/A rxFifo.serialize("rxFifo", cp); 207710905SN/A txFifo.serialize("txFifo", cp); 2078915SN/A 2079915SN/A /* 2080854SN/A * Serialize the various helper variables 2081854SN/A */ 208210469SN/A bool txPacketExists = txPacket != nullptr; 2083915SN/A SERIALIZE_SCALAR(txPacketExists); 2084915SN/A if (txPacketExists) { 208511701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 20861337SN/A txPacket->length = txPacketBufPtr - txPacket->data; 208710905SN/A txPacket->serialize("txPacket", cp); 2088915SN/A uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2089915SN/A SERIALIZE_SCALAR(txPktBufPtr); 2090915SN/A } 2091915SN/A 209210469SN/A bool rxPacketExists = rxPacket != nullptr; 2093915SN/A SERIALIZE_SCALAR(rxPacketExists); 2094915SN/A if (rxPacketExists) { 209510905SN/A rxPacket->serialize("rxPacket", cp); 2096915SN/A uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2097915SN/A SERIALIZE_SCALAR(rxPktBufPtr); 2098915SN/A } 2099915SN/A 2100854SN/A SERIALIZE_SCALAR(txXferLen); 2101854SN/A SERIALIZE_SCALAR(rxXferLen); 2102837SN/A 2103854SN/A /* 21041909SN/A * Serialize Cached Descriptors 2105854SN/A */ 21061909SN/A SERIALIZE_SCALAR(rxDesc64.link); 21071909SN/A SERIALIZE_SCALAR(rxDesc64.bufptr); 21081909SN/A SERIALIZE_SCALAR(rxDesc64.cmdsts); 21091909SN/A SERIALIZE_SCALAR(rxDesc64.extsts); 21101909SN/A SERIALIZE_SCALAR(txDesc64.link); 21111909SN/A SERIALIZE_SCALAR(txDesc64.bufptr); 21121909SN/A SERIALIZE_SCALAR(txDesc64.cmdsts); 21131909SN/A SERIALIZE_SCALAR(txDesc64.extsts); 21141909SN/A SERIALIZE_SCALAR(rxDesc32.link); 21151909SN/A SERIALIZE_SCALAR(rxDesc32.bufptr); 21161909SN/A SERIALIZE_SCALAR(rxDesc32.cmdsts); 21171909SN/A SERIALIZE_SCALAR(rxDesc32.extsts); 21181909SN/A SERIALIZE_SCALAR(txDesc32.link); 21191909SN/A SERIALIZE_SCALAR(txDesc32.bufptr); 21201909SN/A SERIALIZE_SCALAR(txDesc32.cmdsts); 21211909SN/A SERIALIZE_SCALAR(txDesc32.extsts); 21221801SN/A SERIALIZE_SCALAR(extstsEnable); 2123837SN/A 2124854SN/A /* 2125854SN/A * Serialize tx state machine 2126854SN/A */ 2127854SN/A int txState = this->txState; 2128854SN/A SERIALIZE_SCALAR(txState); 21291035SN/A SERIALIZE_SCALAR(txEnable); 2130854SN/A SERIALIZE_SCALAR(CTDD); 2131854SN/A SERIALIZE_SCALAR(txFragPtr); 2132854SN/A SERIALIZE_SCALAR(txDescCnt); 2133854SN/A int txDmaState = this->txDmaState; 2134854SN/A SERIALIZE_SCALAR(txDmaState); 21351801SN/A SERIALIZE_SCALAR(txKickTick); 2136854SN/A 2137854SN/A /* 2138854SN/A * Serialize rx state machine 2139854SN/A */ 2140854SN/A int rxState = this->rxState; 2141854SN/A SERIALIZE_SCALAR(rxState); 21421035SN/A SERIALIZE_SCALAR(rxEnable); 2143854SN/A SERIALIZE_SCALAR(CRDD); 2144854SN/A SERIALIZE_SCALAR(rxPktBytes); 21451224SN/A SERIALIZE_SCALAR(rxFragPtr); 2146854SN/A SERIALIZE_SCALAR(rxDescCnt); 2147854SN/A int rxDmaState = this->rxDmaState; 2148854SN/A SERIALIZE_SCALAR(rxDmaState); 21491801SN/A SERIALIZE_SCALAR(rxKickTick); 2150854SN/A 2151915SN/A /* 21521843SN/A * Serialize EEPROM state machine 21531843SN/A */ 21541843SN/A int eepromState = this->eepromState; 21551843SN/A SERIALIZE_SCALAR(eepromState); 21561843SN/A SERIALIZE_SCALAR(eepromClk); 21571843SN/A SERIALIZE_SCALAR(eepromBitsToRx); 21581843SN/A SERIALIZE_SCALAR(eepromOpcode); 21591843SN/A SERIALIZE_SCALAR(eepromAddress); 21601843SN/A SERIALIZE_SCALAR(eepromData); 21611843SN/A 21621843SN/A /* 2163854SN/A * If there's a pending transmit, store the time so we can 2164854SN/A * reschedule it later 2165854SN/A */ 21667823SN/A Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0; 2167854SN/A SERIALIZE_SCALAR(transmitTick); 2168854SN/A 2169854SN/A /* 2170915SN/A * receive address filter settings 2171915SN/A */ 2172915SN/A SERIALIZE_SCALAR(rxFilterEnable); 2173915SN/A SERIALIZE_SCALAR(acceptBroadcast); 2174915SN/A SERIALIZE_SCALAR(acceptMulticast); 2175915SN/A SERIALIZE_SCALAR(acceptUnicast); 2176915SN/A SERIALIZE_SCALAR(acceptPerfect); 2177915SN/A SERIALIZE_SCALAR(acceptArp); 21781843SN/A SERIALIZE_SCALAR(multicastHashEnable); 2179915SN/A 2180915SN/A /* 2181854SN/A * Keep track of pending interrupt status. 2182854SN/A */ 2183854SN/A SERIALIZE_SCALAR(intrTick); 2184854SN/A SERIALIZE_SCALAR(cpuPendingIntr); 2185854SN/A Tick intrEventTick = 0; 2186854SN/A if (intrEvent) 2187854SN/A intrEventTick = intrEvent->when(); 2188854SN/A SERIALIZE_SCALAR(intrEventTick); 2189854SN/A 2190837SN/A} 2191837SN/A 2192837SN/Avoid 219310905SN/ANSGigE::unserialize(CheckpointIn &cp) 2194837SN/A{ 21959807SN/A // Unserialize the PciDevice base class 219610905SN/A PciDevice::unserialize(cp); 2197897SN/A 2198854SN/A UNSERIALIZE_SCALAR(regs.command); 2199854SN/A UNSERIALIZE_SCALAR(regs.config); 2200854SN/A UNSERIALIZE_SCALAR(regs.mear); 2201854SN/A UNSERIALIZE_SCALAR(regs.ptscr); 2202854SN/A UNSERIALIZE_SCALAR(regs.isr); 2203854SN/A UNSERIALIZE_SCALAR(regs.imr); 2204854SN/A UNSERIALIZE_SCALAR(regs.ier); 2205854SN/A UNSERIALIZE_SCALAR(regs.ihr); 2206854SN/A UNSERIALIZE_SCALAR(regs.txdp); 2207854SN/A UNSERIALIZE_SCALAR(regs.txdp_hi); 2208854SN/A UNSERIALIZE_SCALAR(regs.txcfg); 2209854SN/A UNSERIALIZE_SCALAR(regs.gpior); 2210854SN/A UNSERIALIZE_SCALAR(regs.rxdp); 2211854SN/A UNSERIALIZE_SCALAR(regs.rxdp_hi); 2212854SN/A UNSERIALIZE_SCALAR(regs.rxcfg); 2213854SN/A UNSERIALIZE_SCALAR(regs.pqcr); 2214854SN/A UNSERIALIZE_SCALAR(regs.wcsr); 2215854SN/A UNSERIALIZE_SCALAR(regs.pcr); 2216854SN/A UNSERIALIZE_SCALAR(regs.rfcr); 2217854SN/A UNSERIALIZE_SCALAR(regs.rfdr); 22181843SN/A UNSERIALIZE_SCALAR(regs.brar); 22191843SN/A UNSERIALIZE_SCALAR(regs.brdr); 2220854SN/A UNSERIALIZE_SCALAR(regs.srr); 2221854SN/A UNSERIALIZE_SCALAR(regs.mibc); 2222854SN/A UNSERIALIZE_SCALAR(regs.vrcr); 2223854SN/A UNSERIALIZE_SCALAR(regs.vtcr); 2224854SN/A UNSERIALIZE_SCALAR(regs.vdr); 2225854SN/A UNSERIALIZE_SCALAR(regs.ccsr); 2226854SN/A UNSERIALIZE_SCALAR(regs.tbicr); 2227854SN/A UNSERIALIZE_SCALAR(regs.tbisr); 2228854SN/A UNSERIALIZE_SCALAR(regs.tanar); 2229854SN/A UNSERIALIZE_SCALAR(regs.tanlpar); 2230854SN/A UNSERIALIZE_SCALAR(regs.taner); 2231854SN/A UNSERIALIZE_SCALAR(regs.tesr); 2232837SN/A 22331114SN/A UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 22341843SN/A UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2235837SN/A 2236927SN/A UNSERIALIZE_SCALAR(ioEnable); 2237917SN/A 2238854SN/A /* 2239915SN/A * unserialize the data fifos 2240915SN/A */ 224110905SN/A rxFifo.unserialize("rxFifo", cp); 224210905SN/A txFifo.unserialize("txFifo", cp); 2243915SN/A 2244915SN/A /* 2245854SN/A * unserialize the various helper variables 2246854SN/A */ 2247915SN/A bool txPacketExists; 2248915SN/A UNSERIALIZE_SCALAR(txPacketExists); 2249915SN/A if (txPacketExists) { 225011719Smichael.lebeane@amd.com txPacket = make_shared<EthPacketData>(16384); 225110905SN/A txPacket->unserialize("txPacket", cp); 2252915SN/A uint32_t txPktBufPtr; 2253915SN/A UNSERIALIZE_SCALAR(txPktBufPtr); 2254915SN/A txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2255915SN/A } else 2256915SN/A txPacket = 0; 2257915SN/A 2258915SN/A bool rxPacketExists; 2259915SN/A UNSERIALIZE_SCALAR(rxPacketExists); 2260915SN/A rxPacket = 0; 2261915SN/A if (rxPacketExists) { 226211701Smichael.lebeane@amd.com rxPacket = make_shared<EthPacketData>(); 226310905SN/A rxPacket->unserialize("rxPacket", cp); 2264915SN/A uint32_t rxPktBufPtr; 2265915SN/A UNSERIALIZE_SCALAR(rxPktBufPtr); 2266915SN/A rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2267915SN/A } else 2268915SN/A rxPacket = 0; 2269915SN/A 2270854SN/A UNSERIALIZE_SCALAR(txXferLen); 2271854SN/A UNSERIALIZE_SCALAR(rxXferLen); 2272837SN/A 2273854SN/A /* 22741909SN/A * Unserialize Cached Descriptors 2275854SN/A */ 22761909SN/A UNSERIALIZE_SCALAR(rxDesc64.link); 22771909SN/A UNSERIALIZE_SCALAR(rxDesc64.bufptr); 22781909SN/A UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 22791909SN/A UNSERIALIZE_SCALAR(rxDesc64.extsts); 22801909SN/A UNSERIALIZE_SCALAR(txDesc64.link); 22811909SN/A UNSERIALIZE_SCALAR(txDesc64.bufptr); 22821909SN/A UNSERIALIZE_SCALAR(txDesc64.cmdsts); 22831909SN/A UNSERIALIZE_SCALAR(txDesc64.extsts); 22841909SN/A UNSERIALIZE_SCALAR(rxDesc32.link); 22851909SN/A UNSERIALIZE_SCALAR(rxDesc32.bufptr); 22861909SN/A UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 22871909SN/A UNSERIALIZE_SCALAR(rxDesc32.extsts); 22881909SN/A UNSERIALIZE_SCALAR(txDesc32.link); 22891909SN/A UNSERIALIZE_SCALAR(txDesc32.bufptr); 22901909SN/A UNSERIALIZE_SCALAR(txDesc32.cmdsts); 22911909SN/A UNSERIALIZE_SCALAR(txDesc32.extsts); 22921801SN/A UNSERIALIZE_SCALAR(extstsEnable); 2293854SN/A 2294854SN/A /* 2295854SN/A * unserialize tx state machine 2296854SN/A */ 2297854SN/A int txState; 2298854SN/A UNSERIALIZE_SCALAR(txState); 2299854SN/A this->txState = (TxState) txState; 23001035SN/A UNSERIALIZE_SCALAR(txEnable); 2301854SN/A UNSERIALIZE_SCALAR(CTDD); 2302854SN/A UNSERIALIZE_SCALAR(txFragPtr); 2303854SN/A UNSERIALIZE_SCALAR(txDescCnt); 2304854SN/A int txDmaState; 2305854SN/A UNSERIALIZE_SCALAR(txDmaState); 2306854SN/A this->txDmaState = (DmaState) txDmaState; 23071801SN/A UNSERIALIZE_SCALAR(txKickTick); 23081801SN/A if (txKickTick) 23095606SN/A schedule(txKickEvent, txKickTick); 2310854SN/A 2311854SN/A /* 2312854SN/A * unserialize rx state machine 2313854SN/A */ 2314854SN/A int rxState; 2315854SN/A UNSERIALIZE_SCALAR(rxState); 2316854SN/A this->rxState = (RxState) rxState; 23171035SN/A UNSERIALIZE_SCALAR(rxEnable); 2318854SN/A UNSERIALIZE_SCALAR(CRDD); 2319854SN/A UNSERIALIZE_SCALAR(rxPktBytes); 23201224SN/A UNSERIALIZE_SCALAR(rxFragPtr); 2321854SN/A UNSERIALIZE_SCALAR(rxDescCnt); 2322854SN/A int rxDmaState; 2323854SN/A UNSERIALIZE_SCALAR(rxDmaState); 2324854SN/A this->rxDmaState = (DmaState) rxDmaState; 23251801SN/A UNSERIALIZE_SCALAR(rxKickTick); 23261801SN/A if (rxKickTick) 23275606SN/A schedule(rxKickEvent, rxKickTick); 2328854SN/A 23291843SN/A /* 23301843SN/A * Unserialize EEPROM state machine 23311843SN/A */ 23321843SN/A int eepromState; 23331843SN/A UNSERIALIZE_SCALAR(eepromState); 23341843SN/A this->eepromState = (EEPROMState) eepromState; 23351843SN/A UNSERIALIZE_SCALAR(eepromClk); 23361843SN/A UNSERIALIZE_SCALAR(eepromBitsToRx); 23371843SN/A UNSERIALIZE_SCALAR(eepromOpcode); 23381843SN/A UNSERIALIZE_SCALAR(eepromAddress); 23391843SN/A UNSERIALIZE_SCALAR(eepromData); 23401843SN/A 23411843SN/A /* 2342915SN/A * If there's a pending transmit, reschedule it now 2343854SN/A */ 2344854SN/A Tick transmitTick; 2345854SN/A UNSERIALIZE_SCALAR(transmitTick); 2346854SN/A if (transmitTick) 23477823SN/A schedule(txEvent, curTick() + transmitTick); 2348854SN/A 2349854SN/A /* 2350915SN/A * unserialize receive address filter settings 2351915SN/A */ 2352915SN/A UNSERIALIZE_SCALAR(rxFilterEnable); 2353915SN/A UNSERIALIZE_SCALAR(acceptBroadcast); 2354915SN/A UNSERIALIZE_SCALAR(acceptMulticast); 2355915SN/A UNSERIALIZE_SCALAR(acceptUnicast); 2356915SN/A UNSERIALIZE_SCALAR(acceptPerfect); 2357915SN/A UNSERIALIZE_SCALAR(acceptArp); 23581843SN/A UNSERIALIZE_SCALAR(multicastHashEnable); 2359915SN/A 2360915SN/A /* 2361854SN/A * Keep track of pending interrupt status. 2362854SN/A */ 2363854SN/A UNSERIALIZE_SCALAR(intrTick); 2364854SN/A UNSERIALIZE_SCALAR(cpuPendingIntr); 2365854SN/A Tick intrEventTick; 2366854SN/A UNSERIALIZE_SCALAR(intrEventTick); 2367854SN/A if (intrEventTick) { 236812087Sspwilson2@wisc.edu intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); }, 236912087Sspwilson2@wisc.edu name(), true); 23705606SN/A schedule(intrEvent, intrEventTick); 2371854SN/A } 2372854SN/A} 2373927SN/A 23744762SN/ANSGigE * 23754762SN/ANSGigEParams::create() 2376837SN/A{ 23774762SN/A return new NSGigE(this); 2378837SN/A} 2379