ns_gige.cc revision 11701
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), 1144093SN/A rxDmaReadEvent(this), rxDmaWriteEvent(this), 115854SN/A txDmaReadEvent(this), txDmaWriteEvent(this), 1161149SN/A dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1171149SN/A txDelay(p->tx_delay), rxDelay(p->rx_delay), 1181801SN/A rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1194093SN/A txEvent(this), rxFilterEnable(p->rx_filter), 1204093SN/A acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), 1211843SN/A acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1224093SN/A intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false), 123995SN/A intrEvent(0), interface(0) 124837SN/A{ 125854SN/A 126854SN/A 1274981SN/A interface = new NSGigEInt(name() + ".int0", this); 1284981SN/A 129837SN/A regsReset(); 1304762SN/A memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN); 1311909SN/A 1321909SN/A memset(&rxDesc32, 0, sizeof(rxDesc32)); 1331909SN/A memset(&txDesc32, 0, sizeof(txDesc32)); 1341909SN/A memset(&rxDesc64, 0, sizeof(rxDesc64)); 1351909SN/A memset(&txDesc64, 0, sizeof(txDesc64)); 136837SN/A} 137837SN/A 138879SN/ANSGigE::~NSGigE() 1399086SN/A{ 1409086SN/A delete interface; 1419086SN/A} 142837SN/A 143855SN/A/** 144855SN/A * This is to write to the PCI general configuration registers 145855SN/A */ 1462846SN/ATick 1473349SN/ANSGigE::writeConfig(PacketPtr pkt) 148837SN/A{ 1492846SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 150837SN/A if (offset < PCI_DEVICE_SPECIFIC) 1519807SN/A PciDevice::writeConfig(pkt); 152837SN/A else 153897SN/A panic("Device specific PCI config space not implemented!\n"); 154897SN/A 155897SN/A switch (offset) { 1561027SN/A // seems to work fine without all these PCI settings, but i 1571027SN/A // put in the IO to double check, an assertion will fail if we 1581027SN/A // need to properly implement it 159917SN/A case PCI_COMMAND: 160917SN/A if (config.data[offset] & PCI_CMD_IOSE) 161927SN/A ioEnable = true; 162917SN/A else 163927SN/A ioEnable = false; 164897SN/A break; 165897SN/A } 1664875SN/A 1672846SN/A return configDelay; 168837SN/A} 169837SN/A 1704981SN/AEtherInt* 1714981SN/ANSGigE::getEthPort(const std::string &if_name, int idx) 1724981SN/A{ 1734981SN/A if (if_name == "interface") { 1744981SN/A if (interface->getPeer()) 1754981SN/A panic("interface already connected to\n"); 1764981SN/A return interface; 1774981SN/A } 1784981SN/A return NULL; 1794981SN/A} 1804981SN/A 181855SN/A/** 182855SN/A * This reads the device registers, which are detailed in the NS83820 183855SN/A * spec sheet 184855SN/A */ 1852566SN/ATick 1863349SN/ANSGigE::read(PacketPtr pkt) 187837SN/A{ 188927SN/A assert(ioEnable); 189917SN/A 190855SN/A //The mask is to give you only the offset into the device register file 1912641SN/A Addr daddr = pkt->getAddr() & 0xfff; 1922566SN/A DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n", 1932641SN/A daddr, pkt->getAddr(), pkt->getSize()); 194837SN/A 195855SN/A 1961027SN/A // there are some reserved registers, you can see ns_gige_reg.h and 1971027SN/A // the spec sheet for details 198854SN/A if (daddr > LAST && daddr <= RESERVED) { 199837SN/A panic("Accessing reserved register"); 200854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 2012846SN/A return readConfig(pkt); 202854SN/A } else if (daddr >= MIB_START && daddr <= MIB_END) { 203854SN/A // don't implement all the MIB's. hopefully the kernel 204854SN/A // doesn't actually DEPEND upon their values 205855SN/A // MIB are just hardware stats keepers 2062630SN/A pkt->set<uint32_t>(0); 2074870SN/A pkt->makeAtomicResponse(); 2082566SN/A return pioDelay; 209854SN/A } else if (daddr > 0x3FC) 210854SN/A panic("Something is messed up!\n"); 211837SN/A 2122641SN/A assert(pkt->getSize() == sizeof(uint32_t)); 2132630SN/A uint32_t ® = *pkt->getPtr<uint32_t>(); 2142566SN/A uint16_t rfaddr; 2152566SN/A 2162566SN/A switch (daddr) { 2172566SN/A case CR: 2182566SN/A reg = regs.command; 2192566SN/A //these are supposed to be cleared on a read 2202566SN/A reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 2212566SN/A break; 2222566SN/A 2232566SN/A case CFGR: 2242566SN/A reg = regs.config; 2252566SN/A break; 2262566SN/A 2272566SN/A case MEAR: 2282566SN/A reg = regs.mear; 2292566SN/A break; 2302566SN/A 2312566SN/A case PTSCR: 2322566SN/A reg = regs.ptscr; 2332566SN/A break; 2342566SN/A 2352566SN/A case ISR: 2362566SN/A reg = regs.isr; 2372566SN/A devIntrClear(ISR_ALL); 2382566SN/A break; 2392566SN/A 2402566SN/A case IMR: 2412566SN/A reg = regs.imr; 2422566SN/A break; 2432566SN/A 2442566SN/A case IER: 2452566SN/A reg = regs.ier; 2462566SN/A break; 2472566SN/A 2482566SN/A case IHR: 2492566SN/A reg = regs.ihr; 2502566SN/A break; 2512566SN/A 2522566SN/A case TXDP: 2532566SN/A reg = regs.txdp; 2542566SN/A break; 2552566SN/A 2562566SN/A case TXDP_HI: 2572566SN/A reg = regs.txdp_hi; 2582566SN/A break; 2592566SN/A 2602566SN/A case TX_CFG: 2612566SN/A reg = regs.txcfg; 2622566SN/A break; 2632566SN/A 2642566SN/A case GPIOR: 2652566SN/A reg = regs.gpior; 2662566SN/A break; 2672566SN/A 2682566SN/A case RXDP: 2692566SN/A reg = regs.rxdp; 2702566SN/A break; 2712566SN/A 2722566SN/A case RXDP_HI: 2732566SN/A reg = regs.rxdp_hi; 2742566SN/A break; 2752566SN/A 2762566SN/A case RX_CFG: 2772566SN/A reg = regs.rxcfg; 2782566SN/A break; 2792566SN/A 2802566SN/A case PQCR: 2812566SN/A reg = regs.pqcr; 2822566SN/A break; 2832566SN/A 2842566SN/A case WCSR: 2852566SN/A reg = regs.wcsr; 2862566SN/A break; 2872566SN/A 2882566SN/A case PCR: 2892566SN/A reg = regs.pcr; 2902566SN/A break; 2912566SN/A 2922566SN/A // see the spec sheet for how RFCR and RFDR work 2932566SN/A // basically, you write to RFCR to tell the machine 2942566SN/A // what you want to do next, then you act upon RFDR, 2952566SN/A // and the device will be prepared b/c of what you 2962566SN/A // wrote to RFCR 2972566SN/A case RFCR: 2982566SN/A reg = regs.rfcr; 2992566SN/A break; 3002566SN/A 3012566SN/A case RFDR: 3022566SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 3032566SN/A switch (rfaddr) { 3042566SN/A // Read from perfect match ROM octets 3052566SN/A case 0x000: 3062566SN/A reg = rom.perfectMatch[1]; 3072566SN/A reg = reg << 8; 3082566SN/A reg += rom.perfectMatch[0]; 309837SN/A break; 3102566SN/A case 0x002: 3112566SN/A reg = rom.perfectMatch[3] << 8; 3122566SN/A reg += rom.perfectMatch[2]; 313837SN/A break; 3142566SN/A case 0x004: 3152566SN/A reg = rom.perfectMatch[5] << 8; 3162566SN/A reg += rom.perfectMatch[4]; 317837SN/A break; 3182566SN/A default: 3192566SN/A // Read filter hash table 3202566SN/A if (rfaddr >= FHASH_ADDR && 3212566SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 3222566SN/A 3232566SN/A // Only word-aligned reads supported 3242566SN/A if (rfaddr % 2) 3252566SN/A panic("unaligned read from filter hash table!"); 3262566SN/A 3272566SN/A reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 3282566SN/A reg += rom.filterHash[rfaddr - FHASH_ADDR]; 329837SN/A break; 330837SN/A } 3312566SN/A 3322566SN/A panic("reading RFDR for something other than pattern" 3332566SN/A " matching or hashing! %#x\n", rfaddr); 334837SN/A } 3352566SN/A break; 3362566SN/A 3372566SN/A case SRR: 3382566SN/A reg = regs.srr; 3392566SN/A break; 3402566SN/A 3412566SN/A case MIBC: 3422566SN/A reg = regs.mibc; 3432566SN/A reg &= ~(MIBC_MIBS | MIBC_ACLR); 3442566SN/A break; 3452566SN/A 3462566SN/A case VRCR: 3472566SN/A reg = regs.vrcr; 3482566SN/A break; 3492566SN/A 3502566SN/A case VTCR: 3512566SN/A reg = regs.vtcr; 3522566SN/A break; 3532566SN/A 3542566SN/A case VDR: 3552566SN/A reg = regs.vdr; 3562566SN/A break; 3572566SN/A 3582566SN/A case CCSR: 3592566SN/A reg = regs.ccsr; 3602566SN/A break; 3612566SN/A 3622566SN/A case TBICR: 3632566SN/A reg = regs.tbicr; 3642566SN/A break; 3652566SN/A 3662566SN/A case TBISR: 3672566SN/A reg = regs.tbisr; 3682566SN/A break; 3692566SN/A 3702566SN/A case TANAR: 3712566SN/A reg = regs.tanar; 3722566SN/A break; 3732566SN/A 3742566SN/A case TANLPAR: 3752566SN/A reg = regs.tanlpar; 3762566SN/A break; 3772566SN/A 3782566SN/A case TANER: 3792566SN/A reg = regs.taner; 3802566SN/A break; 3812566SN/A 3822566SN/A case TESR: 3832566SN/A reg = regs.tesr; 3842566SN/A break; 3852566SN/A 3862566SN/A case M5REG: 3872566SN/A reg = 0; 3882566SN/A if (params()->rx_thread) 3892566SN/A reg |= M5REG_RX_THREAD; 3902566SN/A if (params()->tx_thread) 3912566SN/A reg |= M5REG_TX_THREAD; 3922566SN/A if (params()->rss) 3932566SN/A reg |= M5REG_RSS; 3942566SN/A break; 3952566SN/A 3962566SN/A default: 3972566SN/A panic("reading unimplemented register: addr=%#x", daddr); 398837SN/A } 3992566SN/A 4002566SN/A DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 4012566SN/A daddr, reg, reg); 4022566SN/A 4034870SN/A pkt->makeAtomicResponse(); 4042566SN/A return pioDelay; 405837SN/A} 406837SN/A 4072566SN/ATick 4083349SN/ANSGigE::write(PacketPtr pkt) 409837SN/A{ 410927SN/A assert(ioEnable); 411917SN/A 4122641SN/A Addr daddr = pkt->getAddr() & 0xfff; 4132566SN/A DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", 4142641SN/A daddr, pkt->getAddr(), pkt->getSize()); 4152630SN/A 416854SN/A if (daddr > LAST && daddr <= RESERVED) { 417837SN/A panic("Accessing reserved register"); 418854SN/A } else if (daddr > RESERVED && daddr <= 0x3FC) { 4192846SN/A return writeConfig(pkt); 420854SN/A } else if (daddr > 0x3FC) 421854SN/A panic("Something is messed up!\n"); 422837SN/A 4232641SN/A if (pkt->getSize() == sizeof(uint32_t)) { 4242630SN/A uint32_t reg = pkt->get<uint32_t>(); 4251848SN/A uint16_t rfaddr; 4261848SN/A 427854SN/A DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 428837SN/A 429837SN/A switch (daddr) { 430837SN/A case CR: 431837SN/A regs.command = reg; 4321035SN/A if (reg & CR_TXD) { 4331035SN/A txEnable = false; 434837SN/A } else if (reg & CR_TXE) { 4352126SN/A txEnable = true; 4362126SN/A 4372126SN/A // the kernel is enabling the transmit machine 4382126SN/A if (txState == txIdle) 4392126SN/A txKick(); 440837SN/A } 441837SN/A 4421035SN/A if (reg & CR_RXD) { 4431035SN/A rxEnable = false; 444837SN/A } else if (reg & CR_RXE) { 4452126SN/A rxEnable = true; 4462126SN/A 4472126SN/A if (rxState == rxIdle) 4482126SN/A rxKick(); 449837SN/A } 450837SN/A 451837SN/A if (reg & CR_TXR) 452837SN/A txReset(); 453837SN/A 454837SN/A if (reg & CR_RXR) 455837SN/A rxReset(); 456837SN/A 457837SN/A if (reg & CR_SWI) 458837SN/A devIntrPost(ISR_SWI); 459837SN/A 460837SN/A if (reg & CR_RST) { 461837SN/A txReset(); 462837SN/A rxReset(); 463854SN/A 464837SN/A regsReset(); 465837SN/A } 466837SN/A break; 467837SN/A 4681690SN/A case CFGR: 4691690SN/A if (reg & CFGR_LNKSTS || 4701690SN/A reg & CFGR_SPDSTS || 4711690SN/A reg & CFGR_DUPSTS || 4721690SN/A reg & CFGR_RESERVED || 4731690SN/A reg & CFGR_T64ADDR || 4748726SN/A reg & CFGR_PCI64_DET) { 4758726SN/A // First clear all writable bits 4768726SN/A regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4778726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4788726SN/A CFGR_PCI64_DET; 4798726SN/A // Now set the appropriate writable bits 4808726SN/A regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 4818726SN/A CFGR_RESERVED | CFGR_T64ADDR | 4828726SN/A CFGR_PCI64_DET); 4838726SN/A } 4841027SN/A 4851027SN/A// all these #if 0's are because i don't THINK the kernel needs to 4861027SN/A// have these implemented. if there is a problem relating to one of 4871027SN/A// these, you may need to add functionality in. 4888737SN/A 4898737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy 4908737SN/A#if 0 4911690SN/A if (reg & CFGR_TBI_EN) ; 4921690SN/A if (reg & CFGR_MODE_1000) ; 493837SN/A 4941690SN/A if (reg & CFGR_PINT_DUPSTS || 4951690SN/A reg & CFGR_PINT_LNKSTS || 4961690SN/A reg & CFGR_PINT_SPDSTS) 4971027SN/A ; 4981027SN/A 4991690SN/A if (reg & CFGR_TMRTEST) ; 5001690SN/A if (reg & CFGR_MRM_DIS) ; 5011690SN/A if (reg & CFGR_MWI_DIS) ; 5021690SN/A 5031690SN/A if (reg & CFGR_DATA64_EN) ; 5041690SN/A if (reg & CFGR_M64ADDR) ; 5051690SN/A if (reg & CFGR_PHY_RST) ; 5061690SN/A if (reg & CFGR_PHY_DIS) ; 507837SN/A 5081909SN/A if (reg & CFGR_REQALG) ; 5091909SN/A if (reg & CFGR_SB) ; 5101909SN/A if (reg & CFGR_POW) ; 5111909SN/A if (reg & CFGR_EXD) ; 5121909SN/A if (reg & CFGR_PESEL) ; 5131909SN/A if (reg & CFGR_BROM_DIS) ; 5141909SN/A if (reg & CFGR_EXT_125) ; 5151909SN/A if (reg & CFGR_BEM) ; 5168737SN/A 5178737SN/A if (reg & CFGR_T64ADDR) ; 5188737SN/A // panic("CFGR_T64ADDR is read only register!\n"); 5198737SN/A#endif 5208737SN/A if (reg & CFGR_AUTO_1000) 5218737SN/A panic("CFGR_AUTO_1000 not implemented!\n"); 5228737SN/A 5238737SN/A if (reg & CFGR_PCI64_DET) 5248737SN/A panic("CFGR_PCI64_DET is read only register!\n"); 5258737SN/A 5268737SN/A if (reg & CFGR_EXTSTS_EN) 5278737SN/A extstsEnable = true; 5288737SN/A else 5298737SN/A extstsEnable = false; 530837SN/A break; 531837SN/A 532837SN/A case MEAR: 5331843SN/A // Clear writable bits 5341843SN/A regs.mear &= MEAR_EEDO; 5351843SN/A // Set appropriate writable bits 5361843SN/A regs.mear |= reg & ~MEAR_EEDO; 5371843SN/A 5381843SN/A // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 5391843SN/A // even though it could get it through RFDR 5401843SN/A if (reg & MEAR_EESEL) { 5411843SN/A // Rising edge of clock 5421843SN/A if (reg & MEAR_EECLK && !eepromClk) 5431843SN/A eepromKick(); 5441843SN/A } 5451843SN/A else { 5461843SN/A eepromState = eepromStart; 5471843SN/A regs.mear &= ~MEAR_EEDI; 5481843SN/A } 5491843SN/A 5501843SN/A eepromClk = reg & MEAR_EECLK; 5511843SN/A 5521027SN/A // since phy is completely faked, MEAR_MD* don't matter 5538737SN/A 5548737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy 5558737SN/A#if 0 556837SN/A if (reg & MEAR_MDIO) ; 557837SN/A if (reg & MEAR_MDDIR) ; 558837SN/A if (reg & MEAR_MDC) ; 5598737SN/A#endif 560837SN/A break; 561837SN/A 562837SN/A case PTSCR: 563854SN/A regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 5641027SN/A // these control BISTs for various parts of chip - we 5651027SN/A // don't care or do just fake that the BIST is done 566854SN/A if (reg & PTSCR_RBIST_EN) 567854SN/A regs.ptscr |= PTSCR_RBIST_DONE; 568854SN/A if (reg & PTSCR_EEBIST_EN) 569854SN/A regs.ptscr &= ~PTSCR_EEBIST_EN; 570854SN/A if (reg & PTSCR_EELOAD_EN) 571854SN/A regs.ptscr &= ~PTSCR_EELOAD_EN; 572837SN/A break; 573837SN/A 574837SN/A case ISR: /* writing to the ISR has no effect */ 575837SN/A panic("ISR is a read only register!\n"); 576837SN/A 577837SN/A case IMR: 578837SN/A regs.imr = reg; 579837SN/A devIntrChangeMask(); 580837SN/A break; 581837SN/A 582837SN/A case IER: 583837SN/A regs.ier = reg; 584837SN/A break; 585837SN/A 586837SN/A case IHR: 587837SN/A regs.ihr = reg; 588837SN/A /* not going to implement real interrupt holdoff */ 589837SN/A break; 590837SN/A 591837SN/A case TXDP: 592837SN/A regs.txdp = (reg & 0xFFFFFFFC); 593837SN/A assert(txState == txIdle); 594837SN/A CTDD = false; 595837SN/A break; 596837SN/A 597837SN/A case TXDP_HI: 598837SN/A regs.txdp_hi = reg; 599837SN/A break; 600837SN/A 6011690SN/A case TX_CFG: 602837SN/A regs.txcfg = reg; 603837SN/A#if 0 6041690SN/A if (reg & TX_CFG_CSI) ; 6051690SN/A if (reg & TX_CFG_HBI) ; 6061690SN/A if (reg & TX_CFG_MLB) ; 6071690SN/A if (reg & TX_CFG_ATP) ; 6081690SN/A if (reg & TX_CFG_ECRETRY) { 6091027SN/A /* 6101027SN/A * this could easily be implemented, but considering 6111027SN/A * the network is just a fake pipe, wouldn't make 6121027SN/A * sense to do this 6131027SN/A */ 6141027SN/A } 615837SN/A 6161690SN/A if (reg & TX_CFG_BRST_DIS) ; 617837SN/A#endif 618837SN/A 6191027SN/A#if 0 620854SN/A /* we handle our own DMA, ignore the kernel's exhortations */ 6211690SN/A if (reg & TX_CFG_MXDMA) ; 6221027SN/A#endif 6231027SN/A 6241027SN/A // also, we currently don't care about fill/drain 6251027SN/A // thresholds though this may change in the future with 6261027SN/A // more realistic networks or a driver which changes it 6271027SN/A // according to feedback 628837SN/A 629837SN/A break; 630837SN/A 631837SN/A case GPIOR: 6321843SN/A // Only write writable bits 6331843SN/A regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 6341843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 6351843SN/A regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 6361843SN/A | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 637837SN/A /* these just control general purpose i/o pins, don't matter */ 638837SN/A break; 639837SN/A 640854SN/A case RXDP: 641854SN/A regs.rxdp = reg; 6421035SN/A CRDD = false; 643854SN/A break; 644854SN/A 645854SN/A case RXDP_HI: 646854SN/A regs.rxdp_hi = reg; 647854SN/A break; 648854SN/A 6491690SN/A case RX_CFG: 650837SN/A regs.rxcfg = reg; 651837SN/A#if 0 6521690SN/A if (reg & RX_CFG_AEP) ; 6531690SN/A if (reg & RX_CFG_ARP) ; 6541690SN/A if (reg & RX_CFG_STRIPCRC) ; 6551690SN/A if (reg & RX_CFG_RX_RD) ; 6561690SN/A if (reg & RX_CFG_ALP) ; 6571690SN/A if (reg & RX_CFG_AIRL) ; 658837SN/A 659854SN/A /* we handle our own DMA, ignore what kernel says about it */ 6601690SN/A if (reg & RX_CFG_MXDMA) ; 6611027SN/A 662927SN/A //also, we currently don't care about fill/drain thresholds 663927SN/A //though this may change in the future with more realistic 664927SN/A //networks or a driver which changes it according to feedback 6651690SN/A if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 666837SN/A#endif 667837SN/A break; 668837SN/A 669837SN/A case PQCR: 670837SN/A /* there is no priority queueing used in the linux 2.6 driver */ 671837SN/A regs.pqcr = reg; 672837SN/A break; 673837SN/A 674837SN/A case WCSR: 675837SN/A /* not going to implement wake on LAN */ 676837SN/A regs.wcsr = reg; 677837SN/A break; 678837SN/A 679837SN/A case PCR: 680837SN/A /* not going to implement pause control */ 681837SN/A regs.pcr = reg; 682837SN/A break; 683837SN/A 684837SN/A case RFCR: 685837SN/A regs.rfcr = reg; 686854SN/A 687837SN/A rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 688837SN/A acceptBroadcast = (reg & RFCR_AAB) ? true : false; 689837SN/A acceptMulticast = (reg & RFCR_AAM) ? true : false; 690837SN/A acceptUnicast = (reg & RFCR_AAU) ? true : false; 691837SN/A acceptPerfect = (reg & RFCR_APM) ? true : false; 692837SN/A acceptArp = (reg & RFCR_AARP) ? true : false; 6931843SN/A multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 694837SN/A 6951027SN/A#if 0 6961027SN/A if (reg & RFCR_APAT) 6971027SN/A panic("RFCR_APAT not implemented!\n"); 6981027SN/A#endif 6991843SN/A if (reg & RFCR_UHEN) 7001843SN/A panic("Unicast hash filtering not used by drivers!\n"); 701837SN/A 702837SN/A if (reg & RFCR_ULM) 703837SN/A panic("RFCR_ULM not implemented!\n"); 704837SN/A 705837SN/A break; 706837SN/A 707837SN/A case RFDR: 7081848SN/A rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 7091843SN/A switch (rfaddr) { 7101843SN/A case 0x000: 7111843SN/A rom.perfectMatch[0] = (uint8_t)reg; 7121843SN/A rom.perfectMatch[1] = (uint8_t)(reg >> 8); 7131843SN/A break; 7141843SN/A case 0x002: 7151843SN/A rom.perfectMatch[2] = (uint8_t)reg; 7161843SN/A rom.perfectMatch[3] = (uint8_t)(reg >> 8); 7171843SN/A break; 7181843SN/A case 0x004: 7191843SN/A rom.perfectMatch[4] = (uint8_t)reg; 7201843SN/A rom.perfectMatch[5] = (uint8_t)(reg >> 8); 7211843SN/A break; 7221843SN/A default: 7231843SN/A 7241843SN/A if (rfaddr >= FHASH_ADDR && 7251843SN/A rfaddr < FHASH_ADDR + FHASH_SIZE) { 7261843SN/A 7271843SN/A // Only word-aligned writes supported 7281843SN/A if (rfaddr % 2) 7291843SN/A panic("unaligned write to filter hash table!"); 7301843SN/A 7311843SN/A rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 7321843SN/A rom.filterHash[rfaddr - FHASH_ADDR + 1] 7331843SN/A = (uint8_t)(reg >> 8); 7341843SN/A break; 7351843SN/A } 73610367SN/A panic("writing RFDR for something other than pattern matching " 73710367SN/A "or hashing! %#x\n", rfaddr); 7381843SN/A } 739837SN/A 740837SN/A case BRAR: 7411843SN/A regs.brar = reg; 7421843SN/A break; 743837SN/A 744837SN/A case BRDR: 745837SN/A panic("the driver never uses BRDR, something is wrong!\n"); 746837SN/A 747837SN/A case SRR: 748837SN/A panic("SRR is read only register!\n"); 749837SN/A 750837SN/A case MIBC: 751837SN/A panic("the driver never uses MIBC, something is wrong!\n"); 752837SN/A 753837SN/A case VRCR: 754837SN/A regs.vrcr = reg; 755837SN/A break; 756837SN/A 757837SN/A case VTCR: 758837SN/A regs.vtcr = reg; 759837SN/A break; 760837SN/A 761837SN/A case VDR: 762837SN/A panic("the driver never uses VDR, something is wrong!\n"); 763837SN/A 764837SN/A case CCSR: 765837SN/A /* not going to implement clockrun stuff */ 766837SN/A regs.ccsr = reg; 767837SN/A break; 768837SN/A 769837SN/A case TBICR: 770837SN/A regs.tbicr = reg; 771837SN/A if (reg & TBICR_MR_LOOPBACK) 772837SN/A panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 773837SN/A 774837SN/A if (reg & TBICR_MR_AN_ENABLE) { 775837SN/A regs.tanlpar = regs.tanar; 776837SN/A regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 777837SN/A } 778837SN/A 779837SN/A#if 0 780837SN/A if (reg & TBICR_MR_RESTART_AN) ; 781837SN/A#endif 782837SN/A 783837SN/A break; 784837SN/A 785837SN/A case TBISR: 786837SN/A panic("TBISR is read only register!\n"); 787837SN/A 788837SN/A case TANAR: 7891843SN/A // Only write the writable bits 7901843SN/A regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 7911843SN/A regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 7921843SN/A 7931843SN/A // Pause capability unimplemented 7941843SN/A#if 0 7951843SN/A if (reg & TANAR_PS2) ; 7961843SN/A if (reg & TANAR_PS1) ; 7971843SN/A#endif 7981843SN/A 799837SN/A break; 800837SN/A 801837SN/A case TANLPAR: 802837SN/A panic("this should only be written to by the fake phy!\n"); 803837SN/A 804837SN/A case TANER: 805837SN/A panic("TANER is read only register!\n"); 806837SN/A 807837SN/A case TESR: 808837SN/A regs.tesr = reg; 809837SN/A break; 810837SN/A 811837SN/A default: 8121027SN/A panic("invalid register access daddr=%#x", daddr); 813837SN/A } 8141027SN/A } else { 815837SN/A panic("Invalid Request Size"); 8161027SN/A } 8174870SN/A pkt->makeAtomicResponse(); 8182566SN/A return pioDelay; 819837SN/A} 820837SN/A 821837SN/Avoid 822879SN/ANSGigE::devIntrPost(uint32_t interrupts) 823837SN/A{ 824854SN/A if (interrupts & ISR_RESERVE) 825854SN/A panic("Cannot set a reserved interrupt"); 826837SN/A 8271057SN/A if (interrupts & ISR_NOIMPL) 8281057SN/A warn("interrupt not implemented %#x\n", interrupts); 8291057SN/A 8301883SN/A interrupts &= ISR_IMPL; 8311057SN/A regs.isr |= interrupts; 8321057SN/A 8331263SN/A if (interrupts & regs.imr) { 8341263SN/A if (interrupts & ISR_SWI) { 8351263SN/A totalSwi++; 8361263SN/A } 8371263SN/A if (interrupts & ISR_RXIDLE) { 8381263SN/A totalRxIdle++; 8391263SN/A } 8401263SN/A if (interrupts & ISR_RXOK) { 8411263SN/A totalRxOk++; 8421263SN/A } 8431263SN/A if (interrupts & ISR_RXDESC) { 8441263SN/A totalRxDesc++; 8451263SN/A } 8461263SN/A if (interrupts & ISR_TXOK) { 8471263SN/A totalTxOk++; 8481263SN/A } 8491263SN/A if (interrupts & ISR_TXIDLE) { 8501263SN/A totalTxIdle++; 8511263SN/A } 8521263SN/A if (interrupts & ISR_TXDESC) { 8531263SN/A totalTxDesc++; 8541263SN/A } 8551263SN/A if (interrupts & ISR_RXORN) { 8561263SN/A totalRxOrn++; 8571263SN/A } 8581263SN/A } 8591263SN/A 8601057SN/A DPRINTF(EthernetIntr, 8611057SN/A "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 8621057SN/A interrupts, regs.isr, regs.imr); 863837SN/A 864854SN/A if ((regs.isr & regs.imr)) { 8657823SN/A Tick when = curTick(); 8661883SN/A if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 867854SN/A when += intrDelay; 8685485SN/A postedInterrupts++; 869854SN/A cpuIntrPost(when); 870854SN/A } 871837SN/A} 872837SN/A 8731263SN/A/* writing this interrupt counting stats inside this means that this function 8741263SN/A is now limited to being used to clear all interrupts upon the kernel 8751263SN/A reading isr and servicing. just telling you in case you were thinking 8761263SN/A of expanding use. 8771263SN/A*/ 878837SN/Avoid 879879SN/ANSGigE::devIntrClear(uint32_t interrupts) 880837SN/A{ 881837SN/A if (interrupts & ISR_RESERVE) 882837SN/A panic("Cannot clear a reserved interrupt"); 883837SN/A 8841263SN/A if (regs.isr & regs.imr & ISR_SWI) { 8851263SN/A postedSwi++; 8861263SN/A } 8871263SN/A if (regs.isr & regs.imr & ISR_RXIDLE) { 8881263SN/A postedRxIdle++; 8891263SN/A } 8901263SN/A if (regs.isr & regs.imr & ISR_RXOK) { 8911263SN/A postedRxOk++; 8921263SN/A } 8931263SN/A if (regs.isr & regs.imr & ISR_RXDESC) { 8941263SN/A postedRxDesc++; 8951263SN/A } 8961263SN/A if (regs.isr & regs.imr & ISR_TXOK) { 8971263SN/A postedTxOk++; 8981263SN/A } 8991263SN/A if (regs.isr & regs.imr & ISR_TXIDLE) { 9001263SN/A postedTxIdle++; 9011263SN/A } 9021263SN/A if (regs.isr & regs.imr & ISR_TXDESC) { 9031263SN/A postedTxDesc++; 9041263SN/A } 9051263SN/A if (regs.isr & regs.imr & ISR_RXORN) { 9061263SN/A postedRxOrn++; 9071263SN/A } 9081263SN/A 9091057SN/A interrupts &= ~ISR_NOIMPL; 9101057SN/A regs.isr &= ~interrupts; 911837SN/A 9121027SN/A DPRINTF(EthernetIntr, 9131027SN/A "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 914881SN/A interrupts, regs.isr, regs.imr); 9151036SN/A 9161036SN/A if (!(regs.isr & regs.imr)) 9171036SN/A cpuIntrClear(); 918837SN/A} 919837SN/A 920837SN/Avoid 921879SN/ANSGigE::devIntrChangeMask() 922837SN/A{ 9231036SN/A DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 9241036SN/A regs.isr, regs.imr, regs.isr & regs.imr); 925837SN/A 926837SN/A if (regs.isr & regs.imr) 9277823SN/A cpuIntrPost(curTick()); 928837SN/A else 929837SN/A cpuIntrClear(); 930837SN/A} 931837SN/A 932837SN/Avoid 933879SN/ANSGigE::cpuIntrPost(Tick when) 934837SN/A{ 9351027SN/A // If the interrupt you want to post is later than an interrupt 9361027SN/A // already scheduled, just let it post in the coming one and don't 9371027SN/A // schedule another. 9381027SN/A // HOWEVER, must be sure that the scheduled intrTick is in the 9391027SN/A // future (this was formerly the source of a bug) 9401035SN/A /** 9411035SN/A * @todo this warning should be removed and the intrTick code should 9421035SN/A * be fixed. 9431035SN/A */ 9447823SN/A assert(when >= curTick()); 9457823SN/A assert(intrTick >= curTick() || intrTick == 0); 9461072SN/A if (when > intrTick && intrTick != 0) { 9471072SN/A DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 9481072SN/A intrTick); 9491072SN/A return; 9501035SN/A } 951854SN/A 952854SN/A intrTick = when; 9537823SN/A if (intrTick < curTick()) { 9547823SN/A intrTick = curTick(); 9551072SN/A } 9561072SN/A 9571072SN/A DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 9581072SN/A intrTick); 9591072SN/A 9601072SN/A if (intrEvent) 961854SN/A intrEvent->squash(); 9625606SN/A intrEvent = new IntrEvent(this, true); 9635606SN/A schedule(intrEvent, intrTick); 964854SN/A} 965854SN/A 966854SN/Avoid 967879SN/ANSGigE::cpuInterrupt() 968854SN/A{ 9697823SN/A assert(intrTick == curTick()); 9701072SN/A 9711072SN/A // Whether or not there's a pending interrupt, we don't care about 9721072SN/A // it anymore 9731072SN/A intrEvent = 0; 9741072SN/A intrTick = 0; 9751072SN/A 976854SN/A // Don't send an interrupt if there's already one 977927SN/A if (cpuPendingIntr) { 978927SN/A DPRINTF(EthernetIntr, 979927SN/A "would send an interrupt now, but there's already pending\n"); 9801072SN/A } else { 9811072SN/A // Send interrupt 9821072SN/A cpuPendingIntr = true; 9831072SN/A 9841149SN/A DPRINTF(EthernetIntr, "posting interrupt\n"); 9851149SN/A intrPost(); 986927SN/A } 987837SN/A} 988837SN/A 989837SN/Avoid 990879SN/ANSGigE::cpuIntrClear() 991837SN/A{ 9921027SN/A if (!cpuPendingIntr) 9931027SN/A return; 9941027SN/A 9951072SN/A if (intrEvent) { 9961072SN/A intrEvent->squash(); 9971072SN/A intrEvent = 0; 9981072SN/A } 9991072SN/A 10001072SN/A intrTick = 0; 10011072SN/A 10021027SN/A cpuPendingIntr = false; 10031057SN/A 10041149SN/A DPRINTF(EthernetIntr, "clearing interrupt\n"); 10051149SN/A intrClear(); 1006837SN/A} 1007837SN/A 1008837SN/Abool 1009879SN/ANSGigE::cpuIntrPending() const 1010837SN/A{ return cpuPendingIntr; } 1011837SN/A 1012837SN/Avoid 1013879SN/ANSGigE::txReset() 1014837SN/A{ 1015837SN/A 1016837SN/A DPRINTF(Ethernet, "transmit reset\n"); 1017837SN/A 1018837SN/A CTDD = false; 10191035SN/A txEnable = false;; 1020854SN/A txFragPtr = 0; 1021854SN/A assert(txDescCnt == 0); 1022837SN/A txFifo.clear(); 1023837SN/A txState = txIdle; 1024854SN/A assert(txDmaState == dmaIdle); 1025837SN/A} 1026837SN/A 1027837SN/Avoid 1028879SN/ANSGigE::rxReset() 1029837SN/A{ 1030837SN/A DPRINTF(Ethernet, "receive reset\n"); 1031837SN/A 1032837SN/A CRDD = false; 1033854SN/A assert(rxPktBytes == 0); 10341035SN/A rxEnable = false; 1035854SN/A rxFragPtr = 0; 1036854SN/A assert(rxDescCnt == 0); 1037854SN/A assert(rxDmaState == dmaIdle); 1038837SN/A rxFifo.clear(); 1039837SN/A rxState = rxIdle; 1040837SN/A} 1041837SN/A 10421036SN/Avoid 10431036SN/ANSGigE::regsReset() 1044915SN/A{ 1045915SN/A memset(®s, 0, sizeof(regs)); 10461817SN/A regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 10471843SN/A regs.mear = 0x12; 10481057SN/A regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 10491057SN/A // fill threshold to 32 bytes 10501057SN/A regs.rxcfg = 0x4; // set drain threshold to 16 bytes 10511057SN/A regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 10521057SN/A regs.mibc = MIBC_FRZ; 10531057SN/A regs.vdr = 0x81; // set the vlan tag type to 802.1q 10541057SN/A regs.tesr = 0xc000; // TBI capable of both full and half duplex 10551843SN/A regs.brar = 0xffffffff; 1056927SN/A 1057927SN/A extstsEnable = false; 1058927SN/A acceptBroadcast = false; 1059927SN/A acceptMulticast = false; 1060927SN/A acceptUnicast = false; 1061927SN/A acceptPerfect = false; 1062927SN/A acceptArp = false; 1063915SN/A} 1064915SN/A 1065854SN/Abool 1066879SN/ANSGigE::doRxDmaRead() 1067854SN/A{ 1068854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1069854SN/A rxDmaState = dmaReading; 1070854SN/A 107110913SN/A if (dmaPending() || drainState() != DrainState::Running) 10722566SN/A rxDmaState = dmaReadWaiting; 10732566SN/A else 10742566SN/A dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); 10752566SN/A 1076854SN/A return true; 1077854SN/A} 1078854SN/A 1079854SN/Avoid 1080879SN/ANSGigE::rxDmaReadDone() 1081854SN/A{ 1082854SN/A assert(rxDmaState == dmaReading); 10832566SN/A rxDmaState = dmaIdle; 10842566SN/A 10852566SN/A DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 10862566SN/A rxDmaAddr, rxDmaLen); 10872566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1088854SN/A 1089854SN/A // If the transmit state machine has a pending DMA, let it go first 1090854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1091854SN/A txKick(); 1092854SN/A 1093854SN/A rxKick(); 1094854SN/A} 1095854SN/A 1096854SN/Abool 1097879SN/ANSGigE::doRxDmaWrite() 1098854SN/A{ 1099854SN/A assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1100854SN/A rxDmaState = dmaWriting; 1101854SN/A 110210913SN/A if (dmaPending() || drainState() != DrainState::Running) 11032566SN/A rxDmaState = dmaWriteWaiting; 11042566SN/A else 11052566SN/A dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); 1106854SN/A return true; 1107854SN/A} 1108854SN/A 1109854SN/Avoid 1110879SN/ANSGigE::rxDmaWriteDone() 1111854SN/A{ 1112854SN/A assert(rxDmaState == dmaWriting); 11132566SN/A rxDmaState = dmaIdle; 11142566SN/A 11152566SN/A DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 11162566SN/A rxDmaAddr, rxDmaLen); 11172566SN/A DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1118854SN/A 1119854SN/A // If the transmit state machine has a pending DMA, let it go first 1120854SN/A if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1121854SN/A txKick(); 1122854SN/A 1123854SN/A rxKick(); 1124837SN/A} 1125837SN/A 1126837SN/Avoid 1127879SN/ANSGigE::rxKick() 1128837SN/A{ 11291909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 11301909SN/A 11311909SN/A DPRINTF(EthernetSM, 11321909SN/A "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 11331909SN/A NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 11341909SN/A 11351909SN/A Addr link, bufptr; 11361909SN/A uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 11371909SN/A uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1138837SN/A 11391801SN/A next: 11409417SN/A if (rxKickTick > curTick()) { 11419417SN/A DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 11429417SN/A rxKickTick); 11431801SN/A 11449417SN/A goto exit; 11459417SN/A } 11461801SN/A 11479417SN/A // Go to the next state machine clock tick. 11489417SN/A rxKickTick = clockEdge(Cycles(1)); 1149837SN/A 1150854SN/A switch(rxDmaState) { 1151854SN/A case dmaReadWaiting: 1152854SN/A if (doRxDmaRead()) 1153854SN/A goto exit; 1154854SN/A break; 1155854SN/A case dmaWriteWaiting: 1156854SN/A if (doRxDmaWrite()) 1157854SN/A goto exit; 1158854SN/A break; 1159854SN/A default: 1160854SN/A break; 1161854SN/A } 1162837SN/A 11631909SN/A link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 11641909SN/A bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 11651909SN/A 1166855SN/A // see state machine from spec for details 11671027SN/A // the way this works is, if you finish work on one state and can 11681027SN/A // go directly to another, you do that through jumping to the 11691027SN/A // label "next". however, if you have intermediate work, like DMA 11701027SN/A // so that you can't go to the next state yet, you go to exit and 11711027SN/A // exit the loop. however, when the DMA is done it will trigger 11721027SN/A // an event and come back to this loop. 1173854SN/A switch (rxState) { 1174854SN/A case rxIdle: 11751035SN/A if (!rxEnable) { 1176927SN/A DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1177854SN/A goto exit; 1178854SN/A } 1179837SN/A 1180854SN/A if (CRDD) { 1181854SN/A rxState = rxDescRefr; 1182837SN/A 1183854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 11841909SN/A rxDmaData = 11851909SN/A is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 11861909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1187854SN/A rxDmaFree = dmaDescFree; 1188854SN/A 1189961SN/A descDmaReads++; 1190961SN/A descDmaRdBytes += rxDmaLen; 1191961SN/A 1192854SN/A if (doRxDmaRead()) 1193854SN/A goto exit; 1194837SN/A } else { 1195837SN/A rxState = rxDescRead; 1196854SN/A 1197854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 11981909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 11991909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1200854SN/A rxDmaFree = dmaDescFree; 1201854SN/A 1202961SN/A descDmaReads++; 1203961SN/A descDmaRdBytes += rxDmaLen; 1204961SN/A 1205854SN/A if (doRxDmaRead()) 1206854SN/A goto exit; 1207837SN/A } 1208854SN/A break; 1209854SN/A 1210854SN/A case rxDescRefr: 1211854SN/A if (rxDmaState != dmaIdle) 1212854SN/A goto exit; 1213854SN/A 1214854SN/A rxState = rxAdvance; 1215854SN/A break; 1216854SN/A 1217854SN/A case rxDescRead: 1218854SN/A if (rxDmaState != dmaIdle) 1219854SN/A goto exit; 1220854SN/A 12211909SN/A DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 12221036SN/A regs.rxdp & 0x3fffffff); 12231036SN/A DPRINTF(EthernetDesc, 12241909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 12251909SN/A link, bufptr, cmdsts, extsts); 12261909SN/A 12271909SN/A if (cmdsts & CMDSTS_OWN) { 12281035SN/A devIntrPost(ISR_RXIDLE); 1229837SN/A rxState = rxIdle; 12301035SN/A goto exit; 1231837SN/A } else { 1232837SN/A rxState = rxFifoBlock; 12331909SN/A rxFragPtr = bufptr; 12341909SN/A rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1235854SN/A } 1236854SN/A break; 1237837SN/A 1238854SN/A case rxFifoBlock: 1239854SN/A if (!rxPacket) { 1240854SN/A /** 1241854SN/A * @todo in reality, we should be able to start processing 1242854SN/A * the packet as it arrives, and not have to wait for the 1243854SN/A * full packet ot be in the receive fifo. 1244854SN/A */ 1245854SN/A if (rxFifo.empty()) 1246854SN/A goto exit; 1247854SN/A 12481036SN/A DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1249927SN/A 1250854SN/A // If we don't have a packet, grab a new one from the fifo. 1251854SN/A rxPacket = rxFifo.front(); 1252854SN/A rxPktBytes = rxPacket->length; 1253854SN/A rxPacketBufPtr = rxPacket->data; 1254854SN/A 12551011SN/A#if TRACING_ON 1256927SN/A if (DTRACE(Ethernet)) { 12571114SN/A IpPtr ip(rxPacket); 12581078SN/A if (ip) { 12591078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 12601114SN/A TcpPtr tcp(ip); 12611078SN/A if (tcp) { 12621561SN/A DPRINTF(Ethernet, 12631561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 12641561SN/A tcp->sport(), tcp->dport(), tcp->seq(), 12651561SN/A tcp->ack()); 1266927SN/A } 1267927SN/A } 1268927SN/A } 12691011SN/A#endif 1270927SN/A 1271854SN/A // sanity check - i think the driver behaves like this 1272854SN/A assert(rxDescCnt >= rxPktBytes); 12731154SN/A rxFifo.pop(); 1274837SN/A } 1275837SN/A 1276837SN/A 12771027SN/A // dont' need the && rxDescCnt > 0 if driver sanity check 12781027SN/A // above holds 1279854SN/A if (rxPktBytes > 0) { 1280854SN/A rxState = rxFragWrite; 12811027SN/A // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 12821027SN/A // check holds 1283854SN/A rxXferLen = rxPktBytes; 1284854SN/A 1285854SN/A rxDmaAddr = rxFragPtr & 0x3fffffff; 1286854SN/A rxDmaData = rxPacketBufPtr; 1287854SN/A rxDmaLen = rxXferLen; 1288854SN/A rxDmaFree = dmaDataFree; 1289854SN/A 1290854SN/A if (doRxDmaWrite()) 1291854SN/A goto exit; 1292854SN/A 1293837SN/A } else { 1294854SN/A rxState = rxDescWrite; 1295837SN/A 1296854SN/A //if (rxPktBytes == 0) { /* packet is done */ 1297854SN/A assert(rxPktBytes == 0); 1298927SN/A DPRINTF(EthernetSM, "done with receiving packet\n"); 1299837SN/A 13001909SN/A cmdsts |= CMDSTS_OWN; 13011909SN/A cmdsts &= ~CMDSTS_MORE; 13021909SN/A cmdsts |= CMDSTS_OK; 13031909SN/A cmdsts &= 0xffff0000; 13041909SN/A cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1305837SN/A 1306854SN/A#if 0 13071027SN/A /* 13081027SN/A * all the driver uses these are for its own stats keeping 13091027SN/A * which we don't care about, aren't necessary for 13101027SN/A * functionality and doing this would just slow us down. 13111027SN/A * if they end up using this in a later version for 13121027SN/A * functional purposes, just undef 13131027SN/A */ 1314837SN/A if (rxFilterEnable) { 13151909SN/A cmdsts &= ~CMDSTS_DEST_MASK; 13161114SN/A const EthAddr &dst = rxFifoFront()->dst(); 13171114SN/A if (dst->unicast()) 13181909SN/A cmdsts |= CMDSTS_DEST_SELF; 13191114SN/A if (dst->multicast()) 13201909SN/A cmdsts |= CMDSTS_DEST_MULTI; 13211114SN/A if (dst->broadcast()) 13221909SN/A cmdsts |= CMDSTS_DEST_MASK; 1323837SN/A } 1324854SN/A#endif 1325837SN/A 13261114SN/A IpPtr ip(rxPacket); 13271114SN/A if (extstsEnable && ip) { 13281909SN/A extsts |= EXTSTS_IPPKT; 13291078SN/A rxIpChecksums++; 13301114SN/A if (cksum(ip) != 0) { 1331927SN/A DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 13321909SN/A extsts |= EXTSTS_IPERR; 1333927SN/A } 13341114SN/A TcpPtr tcp(ip); 13351114SN/A UdpPtr udp(ip); 13361114SN/A if (tcp) { 13371909SN/A extsts |= EXTSTS_TCPPKT; 13381078SN/A rxTcpChecksums++; 13391114SN/A if (cksum(tcp) != 0) { 1340927SN/A DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 13411909SN/A extsts |= EXTSTS_TCPERR; 1342961SN/A 1343927SN/A } 13441114SN/A } else if (udp) { 13451909SN/A extsts |= EXTSTS_UDPPKT; 13461078SN/A rxUdpChecksums++; 13471114SN/A if (cksum(udp) != 0) { 1348927SN/A DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 13491909SN/A extsts |= EXTSTS_UDPERR; 1350927SN/A } 1351837SN/A } 1352837SN/A } 1353881SN/A rxPacket = 0; 1354881SN/A 13551027SN/A /* 13561027SN/A * the driver seems to always receive into desc buffers 13571027SN/A * of size 1514, so you never have a pkt that is split 13581027SN/A * into multiple descriptors on the receive side, so 13591027SN/A * i don't implement that case, hence the assert above. 13601027SN/A */ 13611027SN/A 13621027SN/A DPRINTF(EthernetDesc, 13631909SN/A "rxDesc: addr=%08x writeback cmdsts extsts\n", 13641036SN/A regs.rxdp & 0x3fffffff); 13651036SN/A DPRINTF(EthernetDesc, 13661909SN/A "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 13671909SN/A link, bufptr, cmdsts, extsts); 13681909SN/A 13691909SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 13701909SN/A rxDmaData = &cmdsts; 13711909SN/A if (is64bit) { 13721909SN/A rxDmaAddr += offsetof(ns_desc64, cmdsts); 13731909SN/A rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 13741909SN/A } else { 13751909SN/A rxDmaAddr += offsetof(ns_desc32, cmdsts); 13761909SN/A rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 13771909SN/A } 1378854SN/A rxDmaFree = dmaDescFree; 1379854SN/A 1380961SN/A descDmaWrites++; 1381961SN/A descDmaWrBytes += rxDmaLen; 1382961SN/A 1383854SN/A if (doRxDmaWrite()) 1384854SN/A goto exit; 1385837SN/A } 1386854SN/A break; 1387837SN/A 1388854SN/A case rxFragWrite: 1389854SN/A if (rxDmaState != dmaIdle) 1390854SN/A goto exit; 1391854SN/A 1392854SN/A rxPacketBufPtr += rxXferLen; 1393854SN/A rxFragPtr += rxXferLen; 1394854SN/A rxPktBytes -= rxXferLen; 1395854SN/A 1396854SN/A rxState = rxFifoBlock; 1397854SN/A break; 1398854SN/A 1399854SN/A case rxDescWrite: 1400854SN/A if (rxDmaState != dmaIdle) 1401854SN/A goto exit; 1402854SN/A 14031909SN/A assert(cmdsts & CMDSTS_OWN); 1404854SN/A 1405854SN/A assert(rxPacket == 0); 1406854SN/A devIntrPost(ISR_RXOK); 1407854SN/A 14081909SN/A if (cmdsts & CMDSTS_INTR) 1409854SN/A devIntrPost(ISR_RXDESC); 1410854SN/A 14111035SN/A if (!rxEnable) { 1412927SN/A DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1413854SN/A rxState = rxIdle; 14141035SN/A goto exit; 1415854SN/A } else 1416854SN/A rxState = rxAdvance; 1417854SN/A break; 1418854SN/A 1419854SN/A case rxAdvance: 14201909SN/A if (link == 0) { 14211035SN/A devIntrPost(ISR_RXIDLE); 1422854SN/A rxState = rxIdle; 14231035SN/A CRDD = true; 14241035SN/A goto exit; 1425854SN/A } else { 14261893SN/A if (rxDmaState != dmaIdle) 14271893SN/A goto exit; 1428854SN/A rxState = rxDescRead; 14291909SN/A regs.rxdp = link; 1430854SN/A CRDD = false; 1431854SN/A 1432854SN/A rxDmaAddr = regs.rxdp & 0x3fffffff; 14331909SN/A rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 14341909SN/A rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1435854SN/A rxDmaFree = dmaDescFree; 1436854SN/A 1437854SN/A if (doRxDmaRead()) 1438854SN/A goto exit; 1439854SN/A } 1440854SN/A break; 1441854SN/A 1442854SN/A default: 1443854SN/A panic("Invalid rxState!"); 1444837SN/A } 1445837SN/A 14461036SN/A DPRINTF(EthernetSM, "entering next rxState=%s\n", 1447854SN/A NsRxStateStrings[rxState]); 1448854SN/A goto next; 1449837SN/A 1450854SN/A exit: 1451854SN/A /** 1452854SN/A * @todo do we want to schedule a future kick? 1453854SN/A */ 14541036SN/A DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1455854SN/A NsRxStateStrings[rxState]); 14561801SN/A 14579417SN/A if (!rxKickEvent.scheduled()) 14585606SN/A schedule(rxKickEvent, rxKickTick); 1459837SN/A} 1460837SN/A 1461837SN/Avoid 1462879SN/ANSGigE::transmit() 1463837SN/A{ 1464837SN/A if (txFifo.empty()) { 1465837SN/A DPRINTF(Ethernet, "nothing to transmit\n"); 1466837SN/A return; 1467837SN/A } 1468837SN/A 14691036SN/A DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 14701154SN/A txFifo.size()); 1471927SN/A if (interface->sendPacket(txFifo.front())) { 14721011SN/A#if TRACING_ON 1473927SN/A if (DTRACE(Ethernet)) { 14741114SN/A IpPtr ip(txFifo.front()); 14751078SN/A if (ip) { 14761078SN/A DPRINTF(Ethernet, "ID is %d\n", ip->id()); 14771114SN/A TcpPtr tcp(ip); 14781078SN/A if (tcp) { 14791561SN/A DPRINTF(Ethernet, 14801561SN/A "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 14811909SN/A tcp->sport(), tcp->dport(), tcp->seq(), 14821909SN/A tcp->ack()); 1483927SN/A } 1484927SN/A } 1485927SN/A } 14861011SN/A#endif 1487927SN/A 14881561SN/A DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1489837SN/A txBytes += txFifo.front()->length; 1490837SN/A txPackets++; 1491837SN/A 14921027SN/A DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 14931154SN/A txFifo.avail()); 14941154SN/A txFifo.pop(); 1495837SN/A 14961027SN/A /* 14971027SN/A * normally do a writeback of the descriptor here, and ONLY 14981027SN/A * after that is done, send this interrupt. but since our 14991027SN/A * stuff never actually fails, just do this interrupt here, 15001027SN/A * otherwise the code has to stray from this nice format. 15011027SN/A * besides, it's functionally the same. 15021027SN/A */ 1503854SN/A devIntrPost(ISR_TXOK); 15041027SN/A } 1505854SN/A 1506854SN/A if (!txFifo.empty() && !txEvent.scheduled()) { 1507854SN/A DPRINTF(Ethernet, "reschedule transmit\n"); 15087823SN/A schedule(txEvent, curTick() + retryTime); 1509854SN/A } 1510854SN/A} 1511854SN/A 1512854SN/Abool 1513879SN/ANSGigE::doTxDmaRead() 1514854SN/A{ 1515854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1516854SN/A txDmaState = dmaReading; 1517854SN/A 151810913SN/A if (dmaPending() || drainState() != DrainState::Running) 15192566SN/A txDmaState = dmaReadWaiting; 15202566SN/A else 15212566SN/A dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); 15222566SN/A 1523854SN/A return true; 1524854SN/A} 1525837SN/A 1526854SN/Avoid 1527879SN/ANSGigE::txDmaReadDone() 1528854SN/A{ 1529854SN/A assert(txDmaState == dmaReading); 15302566SN/A txDmaState = dmaIdle; 15312566SN/A 15322566SN/A DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 15332566SN/A txDmaAddr, txDmaLen); 15342566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1535837SN/A 1536854SN/A // If the receive state machine has a pending DMA, let it go first 1537854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1538854SN/A rxKick(); 1539837SN/A 1540854SN/A txKick(); 1541854SN/A} 1542837SN/A 1543854SN/Abool 1544879SN/ANSGigE::doTxDmaWrite() 1545854SN/A{ 1546854SN/A assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1547854SN/A txDmaState = dmaWriting; 1548854SN/A 154910913SN/A if (dmaPending() || drainState() != DrainState::Running) 15502566SN/A txDmaState = dmaWriteWaiting; 15512566SN/A else 15522566SN/A dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); 1553854SN/A return true; 1554854SN/A} 1555854SN/A 1556854SN/Avoid 1557879SN/ANSGigE::txDmaWriteDone() 1558854SN/A{ 1559854SN/A assert(txDmaState == dmaWriting); 15602566SN/A txDmaState = dmaIdle; 15612566SN/A 15622566SN/A DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 15632566SN/A txDmaAddr, txDmaLen); 15642566SN/A DDUMP(EthernetDMA, txDmaData, txDmaLen); 1565854SN/A 1566854SN/A // If the receive state machine has a pending DMA, let it go first 1567854SN/A if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1568854SN/A rxKick(); 1569854SN/A 1570854SN/A txKick(); 1571837SN/A} 1572837SN/A 1573837SN/Avoid 1574879SN/ANSGigE::txKick() 1575837SN/A{ 15761909SN/A bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 15771909SN/A 15781909SN/A DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 15791909SN/A NsTxStateStrings[txState], is64bit ? 64 : 32); 15801909SN/A 15811909SN/A Addr link, bufptr; 15821909SN/A uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 15831909SN/A uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 1584927SN/A 15851801SN/A next: 15869417SN/A if (txKickTick > curTick()) { 15879417SN/A DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 15889417SN/A txKickTick); 15899417SN/A goto exit; 15909417SN/A } 15911801SN/A 15929417SN/A // Go to the next state machine clock tick. 15939417SN/A txKickTick = clockEdge(Cycles(1)); 1594837SN/A 1595854SN/A switch(txDmaState) { 1596854SN/A case dmaReadWaiting: 1597854SN/A if (doTxDmaRead()) 1598854SN/A goto exit; 1599854SN/A break; 1600854SN/A case dmaWriteWaiting: 1601854SN/A if (doTxDmaWrite()) 1602854SN/A goto exit; 1603854SN/A break; 1604854SN/A default: 1605854SN/A break; 1606854SN/A } 1607837SN/A 16081909SN/A link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 16091909SN/A bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 1610854SN/A switch (txState) { 1611854SN/A case txIdle: 16121035SN/A if (!txEnable) { 1613927SN/A DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1614854SN/A goto exit; 1615854SN/A } 1616837SN/A 1617854SN/A if (CTDD) { 1618854SN/A txState = txDescRefr; 1619837SN/A 1620881SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16211909SN/A txDmaData = 16221909SN/A is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 16231909SN/A txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 1624854SN/A txDmaFree = dmaDescFree; 1625837SN/A 1626961SN/A descDmaReads++; 1627961SN/A descDmaRdBytes += txDmaLen; 1628961SN/A 1629854SN/A if (doTxDmaRead()) 1630854SN/A goto exit; 1631854SN/A 1632854SN/A } else { 1633854SN/A txState = txDescRead; 1634854SN/A 1635854SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16361909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 16371909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1638854SN/A txDmaFree = dmaDescFree; 1639854SN/A 1640961SN/A descDmaReads++; 1641961SN/A descDmaRdBytes += txDmaLen; 1642961SN/A 1643854SN/A if (doTxDmaRead()) 1644854SN/A goto exit; 1645837SN/A } 1646854SN/A break; 1647837SN/A 1648854SN/A case txDescRefr: 1649854SN/A if (txDmaState != dmaIdle) 1650854SN/A goto exit; 1651854SN/A 1652854SN/A txState = txAdvance; 1653854SN/A break; 1654854SN/A 1655854SN/A case txDescRead: 1656854SN/A if (txDmaState != dmaIdle) 1657854SN/A goto exit; 1658854SN/A 16591909SN/A DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 16601801SN/A regs.txdp & 0x3fffffff); 1661927SN/A DPRINTF(EthernetDesc, 16621909SN/A "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 16631909SN/A link, bufptr, cmdsts, extsts); 16641909SN/A 16651909SN/A if (cmdsts & CMDSTS_OWN) { 1666854SN/A txState = txFifoBlock; 16671909SN/A txFragPtr = bufptr; 16681909SN/A txDescCnt = cmdsts & CMDSTS_LEN_MASK; 1669854SN/A } else { 16701035SN/A devIntrPost(ISR_TXIDLE); 1671854SN/A txState = txIdle; 16721035SN/A goto exit; 1673854SN/A } 1674854SN/A break; 1675854SN/A 1676854SN/A case txFifoBlock: 1677854SN/A if (!txPacket) { 16781036SN/A DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 167910469SN/A txPacket = make_shared<EthPacketData>(16384); 1680854SN/A txPacketBufPtr = txPacket->data; 1681854SN/A } 1682854SN/A 1683854SN/A if (txDescCnt == 0) { 1684927SN/A DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 16851909SN/A if (cmdsts & CMDSTS_MORE) { 1686927SN/A DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1687854SN/A txState = txDescWrite; 1688854SN/A 16891909SN/A cmdsts &= ~CMDSTS_OWN; 16901909SN/A 16911909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 16921909SN/A txDmaData = &cmdsts; 16931909SN/A if (is64bit) { 16941909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 16951909SN/A txDmaLen = sizeof(txDesc64.cmdsts); 16961909SN/A } else { 16971909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 16981909SN/A txDmaLen = sizeof(txDesc32.cmdsts); 16991909SN/A } 1700854SN/A txDmaFree = dmaDescFree; 1701854SN/A 1702854SN/A if (doTxDmaWrite()) 1703854SN/A goto exit; 1704854SN/A 1705854SN/A } else { /* this packet is totally done */ 1706927SN/A DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1707854SN/A /* deal with the the packet that just finished */ 1708854SN/A if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 17091114SN/A IpPtr ip(txPacket); 17101909SN/A if (extsts & EXTSTS_UDPPKT) { 17111114SN/A UdpPtr udp(ip); 17125484SN/A if (udp) { 17135484SN/A udp->sum(0); 17145484SN/A udp->sum(cksum(udp)); 17155484SN/A txUdpChecksums++; 17165484SN/A } else { 17178231SN/A Debug::breakpoint(); 17185484SN/A warn_once("UDPPKT set, but not UDP!\n"); 17195484SN/A } 17201909SN/A } else if (extsts & EXTSTS_TCPPKT) { 17211114SN/A TcpPtr tcp(ip); 17225484SN/A if (tcp) { 17235484SN/A tcp->sum(0); 17245484SN/A tcp->sum(cksum(tcp)); 17255484SN/A txTcpChecksums++; 17265484SN/A } else { 17275484SN/A warn_once("TCPPKT set, but not UDP!\n"); 17285484SN/A } 1729944SN/A } 17301909SN/A if (extsts & EXTSTS_IPPKT) { 17315484SN/A if (ip) { 17325484SN/A ip->sum(0); 17335484SN/A ip->sum(cksum(ip)); 17345484SN/A txIpChecksums++; 17355484SN/A } else { 17365484SN/A warn_once("IPPKT set, but not UDP!\n"); 17375484SN/A } 1738854SN/A } 1739854SN/A } 1740854SN/A 174111701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 1742854SN/A txPacket->length = txPacketBufPtr - txPacket->data; 17431027SN/A // this is just because the receive can't handle a 17441027SN/A // packet bigger want to make sure 17451909SN/A if (txPacket->length > 1514) 17461909SN/A panic("transmit packet too large, %s > 1514\n", 17471909SN/A txPacket->length); 17481909SN/A 17491205SN/A#ifndef NDEBUG 17501205SN/A bool success = 17511205SN/A#endif 17521205SN/A txFifo.push(txPacket); 17531205SN/A assert(success); 1754854SN/A 17551027SN/A /* 17561027SN/A * this following section is not tqo spec, but 17571027SN/A * functionally shouldn't be any different. normally, 17581027SN/A * the chip will wait til the transmit has occurred 17591027SN/A * before writing back the descriptor because it has 17601027SN/A * to wait to see that it was successfully transmitted 17611027SN/A * to decide whether to set CMDSTS_OK or not. 17621027SN/A * however, in the simulator since it is always 17631027SN/A * successfully transmitted, and writing it exactly to 17641027SN/A * spec would complicate the code, we just do it here 17651027SN/A */ 1766927SN/A 17671909SN/A cmdsts &= ~CMDSTS_OWN; 17681909SN/A cmdsts |= CMDSTS_OK; 1769854SN/A 1770927SN/A DPRINTF(EthernetDesc, 17711036SN/A "txDesc writeback: cmdsts=%08x extsts=%08x\n", 17721909SN/A cmdsts, extsts); 17731909SN/A 1774854SN/A txDmaFree = dmaDescFree; 17751909SN/A txDmaAddr = regs.txdp & 0x3fffffff; 17761909SN/A txDmaData = &cmdsts; 17771909SN/A if (is64bit) { 17781909SN/A txDmaAddr += offsetof(ns_desc64, cmdsts); 17791909SN/A txDmaLen = 17801909SN/A sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 17811909SN/A } else { 17821909SN/A txDmaAddr += offsetof(ns_desc32, cmdsts); 17831909SN/A txDmaLen = 17841909SN/A sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 17851909SN/A } 1786854SN/A 1787961SN/A descDmaWrites++; 1788961SN/A descDmaWrBytes += txDmaLen; 1789961SN/A 1790927SN/A transmit(); 1791854SN/A txPacket = 0; 1792854SN/A 17931035SN/A if (!txEnable) { 1794927SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 1795854SN/A txState = txIdle; 17961035SN/A goto exit; 1797854SN/A } else 1798854SN/A txState = txAdvance; 1799986SN/A 1800986SN/A if (doTxDmaWrite()) 1801986SN/A goto exit; 1802854SN/A } 1803854SN/A } else { 1804927SN/A DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 18051154SN/A if (!txFifo.full()) { 1806992SN/A txState = txFragRead; 1807992SN/A 18081027SN/A /* 18091027SN/A * The number of bytes transferred is either whatever 18101027SN/A * is left in the descriptor (txDescCnt), or if there 18111027SN/A * is not enough room in the fifo, just whatever room 18121027SN/A * is left in the fifo 18131027SN/A */ 18141154SN/A txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 1815992SN/A 1816992SN/A txDmaAddr = txFragPtr & 0x3fffffff; 1817992SN/A txDmaData = txPacketBufPtr; 1818992SN/A txDmaLen = txXferLen; 1819992SN/A txDmaFree = dmaDataFree; 1820992SN/A 1821992SN/A if (doTxDmaRead()) 1822992SN/A goto exit; 1823992SN/A } else { 1824992SN/A txState = txFifoBlock; 1825992SN/A transmit(); 1826992SN/A 1827998SN/A goto exit; 1828992SN/A } 1829992SN/A 1830854SN/A } 1831854SN/A break; 1832854SN/A 1833854SN/A case txFragRead: 1834854SN/A if (txDmaState != dmaIdle) 1835854SN/A goto exit; 1836854SN/A 1837854SN/A txPacketBufPtr += txXferLen; 1838854SN/A txFragPtr += txXferLen; 1839854SN/A txDescCnt -= txXferLen; 18401205SN/A txFifo.reserve(txXferLen); 1841854SN/A 1842854SN/A txState = txFifoBlock; 1843854SN/A break; 1844854SN/A 1845854SN/A case txDescWrite: 1846854SN/A if (txDmaState != dmaIdle) 1847854SN/A goto exit; 1848854SN/A 18491909SN/A if (cmdsts & CMDSTS_INTR) 1850854SN/A devIntrPost(ISR_TXDESC); 1851854SN/A 18521801SN/A if (!txEnable) { 18531801SN/A DPRINTF(EthernetSM, "halting TX state machine\n"); 18541801SN/A txState = txIdle; 18551801SN/A goto exit; 18561801SN/A } else 18571801SN/A txState = txAdvance; 1858854SN/A break; 1859854SN/A 1860854SN/A case txAdvance: 18611909SN/A if (link == 0) { 18621035SN/A devIntrPost(ISR_TXIDLE); 1863837SN/A txState = txIdle; 18641035SN/A goto exit; 1865837SN/A } else { 18661893SN/A if (txDmaState != dmaIdle) 18671893SN/A goto exit; 1868837SN/A txState = txDescRead; 18691909SN/A regs.txdp = link; 1870837SN/A CTDD = false; 1871854SN/A 18721909SN/A txDmaAddr = link & 0x3fffffff; 18731909SN/A txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 18741909SN/A txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 1875854SN/A txDmaFree = dmaDescFree; 1876854SN/A 1877854SN/A if (doTxDmaRead()) 1878854SN/A goto exit; 1879837SN/A } 1880854SN/A break; 1881837SN/A 1882854SN/A default: 1883854SN/A panic("invalid state"); 1884837SN/A } 1885837SN/A 18861036SN/A DPRINTF(EthernetSM, "entering next txState=%s\n", 1887854SN/A NsTxStateStrings[txState]); 1888854SN/A goto next; 1889837SN/A 1890854SN/A exit: 1891854SN/A /** 1892854SN/A * @todo do we want to schedule a future kick? 1893854SN/A */ 18941036SN/A DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1895854SN/A NsTxStateStrings[txState]); 18961801SN/A 18979417SN/A if (!txKickEvent.scheduled()) 18985606SN/A schedule(txKickEvent, txKickTick); 1899837SN/A} 1900837SN/A 19011843SN/A/** 19021843SN/A * Advance the EEPROM state machine 19031843SN/A * Called on rising edge of EEPROM clock bit in MEAR 19041843SN/A */ 19051843SN/Avoid 19061843SN/ANSGigE::eepromKick() 19071843SN/A{ 19081843SN/A switch (eepromState) { 19091843SN/A 19101843SN/A case eepromStart: 19111843SN/A 19121843SN/A // Wait for start bit 19131843SN/A if (regs.mear & MEAR_EEDI) { 19141843SN/A // Set up to get 2 opcode bits 19151843SN/A eepromState = eepromGetOpcode; 19161843SN/A eepromBitsToRx = 2; 19171843SN/A eepromOpcode = 0; 19181843SN/A } 19191843SN/A break; 19201843SN/A 19211843SN/A case eepromGetOpcode: 19221843SN/A eepromOpcode <<= 1; 19231843SN/A eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 19241843SN/A --eepromBitsToRx; 19251843SN/A 19261843SN/A // Done getting opcode 19271843SN/A if (eepromBitsToRx == 0) { 19281843SN/A if (eepromOpcode != EEPROM_READ) 19291843SN/A panic("only EEPROM reads are implemented!"); 19301843SN/A 19311843SN/A // Set up to get address 19321843SN/A eepromState = eepromGetAddress; 19331843SN/A eepromBitsToRx = 6; 19341843SN/A eepromAddress = 0; 19351843SN/A } 19361843SN/A break; 19371843SN/A 19381843SN/A case eepromGetAddress: 19391843SN/A eepromAddress <<= 1; 19401843SN/A eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 19411843SN/A --eepromBitsToRx; 19421843SN/A 19431843SN/A // Done getting address 19441843SN/A if (eepromBitsToRx == 0) { 19451843SN/A 19461843SN/A if (eepromAddress >= EEPROM_SIZE) 19471843SN/A panic("EEPROM read access out of range!"); 19481843SN/A 19491843SN/A switch (eepromAddress) { 19501843SN/A 19511843SN/A case EEPROM_PMATCH2_ADDR: 19521843SN/A eepromData = rom.perfectMatch[5]; 19531843SN/A eepromData <<= 8; 19541843SN/A eepromData += rom.perfectMatch[4]; 19551843SN/A break; 19561843SN/A 19571843SN/A case EEPROM_PMATCH1_ADDR: 19581843SN/A eepromData = rom.perfectMatch[3]; 19591843SN/A eepromData <<= 8; 19601843SN/A eepromData += rom.perfectMatch[2]; 19611843SN/A break; 19621843SN/A 19631843SN/A case EEPROM_PMATCH0_ADDR: 19641843SN/A eepromData = rom.perfectMatch[1]; 19651843SN/A eepromData <<= 8; 19661843SN/A eepromData += rom.perfectMatch[0]; 19671843SN/A break; 19681843SN/A 19691843SN/A default: 19701843SN/A panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 19711843SN/A } 19721843SN/A // Set up to read data 19731843SN/A eepromState = eepromRead; 19741843SN/A eepromBitsToRx = 16; 19751843SN/A 19761843SN/A // Clear data in bit 19771843SN/A regs.mear &= ~MEAR_EEDI; 19781843SN/A } 19791843SN/A break; 19801843SN/A 19811843SN/A case eepromRead: 19821843SN/A // Clear Data Out bit 19831843SN/A regs.mear &= ~MEAR_EEDO; 19841843SN/A // Set bit to value of current EEPROM bit 19851843SN/A regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 19861843SN/A 19871843SN/A eepromData <<= 1; 19881843SN/A --eepromBitsToRx; 19891843SN/A 19901843SN/A // All done 19911843SN/A if (eepromBitsToRx == 0) { 19921843SN/A eepromState = eepromStart; 19931843SN/A } 19941843SN/A break; 19951843SN/A 19961843SN/A default: 19971843SN/A panic("invalid EEPROM state"); 19981843SN/A } 19991843SN/A 20001843SN/A} 20011843SN/A 2002837SN/Avoid 2003879SN/ANSGigE::transferDone() 2004837SN/A{ 20051036SN/A if (txFifo.empty()) { 20061036SN/A DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2007837SN/A return; 20081036SN/A } 20091036SN/A 20101036SN/A DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2011837SN/A 20129417SN/A reschedule(txEvent, clockEdge(Cycles(1)), true); 2013837SN/A} 2014837SN/A 2015837SN/Abool 20162566SN/ANSGigE::rxFilter(const EthPacketPtr &packet) 2017837SN/A{ 20181114SN/A EthPtr eth = packet; 2019837SN/A bool drop = true; 2020837SN/A string type; 2021837SN/A 20221114SN/A const EthAddr &dst = eth->dst(); 20231114SN/A if (dst.unicast()) { 2024837SN/A // If we're accepting all unicast addresses 2025837SN/A if (acceptUnicast) 2026837SN/A drop = false; 2027837SN/A 2028837SN/A // If we make a perfect match 20291114SN/A if (acceptPerfect && dst == rom.perfectMatch) 2030837SN/A drop = false; 2031837SN/A 20321078SN/A if (acceptArp && eth->type() == ETH_TYPE_ARP) 2033837SN/A drop = false; 2034837SN/A 20351114SN/A } else if (dst.broadcast()) { 2036837SN/A // if we're accepting broadcasts 2037837SN/A if (acceptBroadcast) 2038837SN/A drop = false; 2039837SN/A 20401114SN/A } else if (dst.multicast()) { 2041837SN/A // if we're accepting all multicasts 2042837SN/A if (acceptMulticast) 2043837SN/A drop = false; 2044837SN/A 20451843SN/A // Multicast hashing faked - all packets accepted 20461843SN/A if (multicastHashEnable) 20471843SN/A drop = false; 2048837SN/A } 2049837SN/A 2050837SN/A if (drop) { 2051837SN/A DPRINTF(Ethernet, "rxFilter drop\n"); 2052837SN/A DDUMP(EthernetData, packet->data, packet->length); 2053837SN/A } 2054837SN/A 2055837SN/A return drop; 2056837SN/A} 2057837SN/A 2058837SN/Abool 20592566SN/ANSGigE::recvPacket(EthPacketPtr packet) 2060837SN/A{ 2061837SN/A rxBytes += packet->length; 2062837SN/A rxPackets++; 2063837SN/A 20641036SN/A DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 20651154SN/A rxFifo.avail()); 2066927SN/A 20671035SN/A if (!rxEnable) { 2068837SN/A DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2069837SN/A return true; 2070837SN/A } 2071837SN/A 20721843SN/A if (!rxFilterEnable) { 20731843SN/A DPRINTF(Ethernet, 20741843SN/A "receive packet filtering disabled . . . packet dropped\n"); 20751843SN/A return true; 20761843SN/A } 20771843SN/A 20781843SN/A if (rxFilter(packet)) { 2079837SN/A DPRINTF(Ethernet, "packet filtered...dropped\n"); 2080837SN/A return true; 2081837SN/A } 2082837SN/A 20831154SN/A if (rxFifo.avail() < packet->length) { 20841561SN/A#if TRACING_ON 20851561SN/A IpPtr ip(packet); 20861561SN/A TcpPtr tcp(ip); 20871561SN/A if (ip) { 20881561SN/A DPRINTF(Ethernet, 20891561SN/A "packet won't fit in receive buffer...pkt ID %d dropped\n", 20901561SN/A ip->id()); 20911561SN/A if (tcp) { 20921561SN/A DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 20931561SN/A } 20941561SN/A } 20951561SN/A#endif 20961263SN/A droppedPackets++; 2097837SN/A devIntrPost(ISR_RXORN); 2098837SN/A return false; 2099837SN/A } 2100837SN/A 21011154SN/A rxFifo.push(packet); 2102837SN/A 2103854SN/A rxKick(); 2104837SN/A return true; 2105837SN/A} 2106837SN/A 21072901SN/A 21082901SN/Avoid 21099342SN/ANSGigE::drainResume() 21102901SN/A{ 21119342SN/A Drainable::drainResume(); 21122901SN/A 21132901SN/A // During drain we could have left the state machines in a waiting state and 21142901SN/A // they wouldn't get out until some other event occured to kick them. 21152901SN/A // This way they'll get out immediately 21162901SN/A txKick(); 21172901SN/A rxKick(); 21182901SN/A} 21192901SN/A 21202901SN/A 2121837SN/A//===================================================================== 2122837SN/A// 2123837SN/A// 2124837SN/Avoid 212510905SN/ANSGigE::serialize(CheckpointOut &cp) const 2126837SN/A{ 21279807SN/A // Serialize the PciDevice base class 212810905SN/A PciDevice::serialize(cp); 2129897SN/A 2130854SN/A /* 2131854SN/A * Finalize any DMA events now. 2132854SN/A */ 21332566SN/A // @todo will mem system save pending dma? 2134837SN/A 2135854SN/A /* 2136854SN/A * Serialize the device registers 2137854SN/A */ 2138854SN/A SERIALIZE_SCALAR(regs.command); 2139854SN/A SERIALIZE_SCALAR(regs.config); 2140854SN/A SERIALIZE_SCALAR(regs.mear); 2141854SN/A SERIALIZE_SCALAR(regs.ptscr); 2142854SN/A SERIALIZE_SCALAR(regs.isr); 2143854SN/A SERIALIZE_SCALAR(regs.imr); 2144854SN/A SERIALIZE_SCALAR(regs.ier); 2145854SN/A SERIALIZE_SCALAR(regs.ihr); 2146854SN/A SERIALIZE_SCALAR(regs.txdp); 2147854SN/A SERIALIZE_SCALAR(regs.txdp_hi); 2148854SN/A SERIALIZE_SCALAR(regs.txcfg); 2149854SN/A SERIALIZE_SCALAR(regs.gpior); 2150854SN/A SERIALIZE_SCALAR(regs.rxdp); 2151854SN/A SERIALIZE_SCALAR(regs.rxdp_hi); 2152854SN/A SERIALIZE_SCALAR(regs.rxcfg); 2153854SN/A SERIALIZE_SCALAR(regs.pqcr); 2154854SN/A SERIALIZE_SCALAR(regs.wcsr); 2155854SN/A SERIALIZE_SCALAR(regs.pcr); 2156854SN/A SERIALIZE_SCALAR(regs.rfcr); 2157854SN/A SERIALIZE_SCALAR(regs.rfdr); 21581843SN/A SERIALIZE_SCALAR(regs.brar); 21591843SN/A SERIALIZE_SCALAR(regs.brdr); 2160854SN/A SERIALIZE_SCALAR(regs.srr); 2161854SN/A SERIALIZE_SCALAR(regs.mibc); 2162854SN/A SERIALIZE_SCALAR(regs.vrcr); 2163854SN/A SERIALIZE_SCALAR(regs.vtcr); 2164854SN/A SERIALIZE_SCALAR(regs.vdr); 2165854SN/A SERIALIZE_SCALAR(regs.ccsr); 2166854SN/A SERIALIZE_SCALAR(regs.tbicr); 2167854SN/A SERIALIZE_SCALAR(regs.tbisr); 2168854SN/A SERIALIZE_SCALAR(regs.tanar); 2169854SN/A SERIALIZE_SCALAR(regs.tanlpar); 2170854SN/A SERIALIZE_SCALAR(regs.taner); 2171854SN/A SERIALIZE_SCALAR(regs.tesr); 2172837SN/A 21731114SN/A SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 21741843SN/A SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2175837SN/A 2176927SN/A SERIALIZE_SCALAR(ioEnable); 2177917SN/A 2178854SN/A /* 2179915SN/A * Serialize the data Fifos 2180915SN/A */ 218110905SN/A rxFifo.serialize("rxFifo", cp); 218210905SN/A txFifo.serialize("txFifo", cp); 2183915SN/A 2184915SN/A /* 2185854SN/A * Serialize the various helper variables 2186854SN/A */ 218710469SN/A bool txPacketExists = txPacket != nullptr; 2188915SN/A SERIALIZE_SCALAR(txPacketExists); 2189915SN/A if (txPacketExists) { 219011701Smichael.lebeane@amd.com txPacket->simLength = txPacketBufPtr - txPacket->data; 21911337SN/A txPacket->length = txPacketBufPtr - txPacket->data; 219210905SN/A txPacket->serialize("txPacket", cp); 2193915SN/A uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2194915SN/A SERIALIZE_SCALAR(txPktBufPtr); 2195915SN/A } 2196915SN/A 219710469SN/A bool rxPacketExists = rxPacket != nullptr; 2198915SN/A SERIALIZE_SCALAR(rxPacketExists); 2199915SN/A if (rxPacketExists) { 220010905SN/A rxPacket->serialize("rxPacket", cp); 2201915SN/A uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2202915SN/A SERIALIZE_SCALAR(rxPktBufPtr); 2203915SN/A } 2204915SN/A 2205854SN/A SERIALIZE_SCALAR(txXferLen); 2206854SN/A SERIALIZE_SCALAR(rxXferLen); 2207837SN/A 2208854SN/A /* 22091909SN/A * Serialize Cached Descriptors 2210854SN/A */ 22111909SN/A SERIALIZE_SCALAR(rxDesc64.link); 22121909SN/A SERIALIZE_SCALAR(rxDesc64.bufptr); 22131909SN/A SERIALIZE_SCALAR(rxDesc64.cmdsts); 22141909SN/A SERIALIZE_SCALAR(rxDesc64.extsts); 22151909SN/A SERIALIZE_SCALAR(txDesc64.link); 22161909SN/A SERIALIZE_SCALAR(txDesc64.bufptr); 22171909SN/A SERIALIZE_SCALAR(txDesc64.cmdsts); 22181909SN/A SERIALIZE_SCALAR(txDesc64.extsts); 22191909SN/A SERIALIZE_SCALAR(rxDesc32.link); 22201909SN/A SERIALIZE_SCALAR(rxDesc32.bufptr); 22211909SN/A SERIALIZE_SCALAR(rxDesc32.cmdsts); 22221909SN/A SERIALIZE_SCALAR(rxDesc32.extsts); 22231909SN/A SERIALIZE_SCALAR(txDesc32.link); 22241909SN/A SERIALIZE_SCALAR(txDesc32.bufptr); 22251909SN/A SERIALIZE_SCALAR(txDesc32.cmdsts); 22261909SN/A SERIALIZE_SCALAR(txDesc32.extsts); 22271801SN/A SERIALIZE_SCALAR(extstsEnable); 2228837SN/A 2229854SN/A /* 2230854SN/A * Serialize tx state machine 2231854SN/A */ 2232854SN/A int txState = this->txState; 2233854SN/A SERIALIZE_SCALAR(txState); 22341035SN/A SERIALIZE_SCALAR(txEnable); 2235854SN/A SERIALIZE_SCALAR(CTDD); 2236854SN/A SERIALIZE_SCALAR(txFragPtr); 2237854SN/A SERIALIZE_SCALAR(txDescCnt); 2238854SN/A int txDmaState = this->txDmaState; 2239854SN/A SERIALIZE_SCALAR(txDmaState); 22401801SN/A SERIALIZE_SCALAR(txKickTick); 2241854SN/A 2242854SN/A /* 2243854SN/A * Serialize rx state machine 2244854SN/A */ 2245854SN/A int rxState = this->rxState; 2246854SN/A SERIALIZE_SCALAR(rxState); 22471035SN/A SERIALIZE_SCALAR(rxEnable); 2248854SN/A SERIALIZE_SCALAR(CRDD); 2249854SN/A SERIALIZE_SCALAR(rxPktBytes); 22501224SN/A SERIALIZE_SCALAR(rxFragPtr); 2251854SN/A SERIALIZE_SCALAR(rxDescCnt); 2252854SN/A int rxDmaState = this->rxDmaState; 2253854SN/A SERIALIZE_SCALAR(rxDmaState); 22541801SN/A SERIALIZE_SCALAR(rxKickTick); 2255854SN/A 2256915SN/A /* 22571843SN/A * Serialize EEPROM state machine 22581843SN/A */ 22591843SN/A int eepromState = this->eepromState; 22601843SN/A SERIALIZE_SCALAR(eepromState); 22611843SN/A SERIALIZE_SCALAR(eepromClk); 22621843SN/A SERIALIZE_SCALAR(eepromBitsToRx); 22631843SN/A SERIALIZE_SCALAR(eepromOpcode); 22641843SN/A SERIALIZE_SCALAR(eepromAddress); 22651843SN/A SERIALIZE_SCALAR(eepromData); 22661843SN/A 22671843SN/A /* 2268854SN/A * If there's a pending transmit, store the time so we can 2269854SN/A * reschedule it later 2270854SN/A */ 22717823SN/A Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0; 2272854SN/A SERIALIZE_SCALAR(transmitTick); 2273854SN/A 2274854SN/A /* 2275915SN/A * receive address filter settings 2276915SN/A */ 2277915SN/A SERIALIZE_SCALAR(rxFilterEnable); 2278915SN/A SERIALIZE_SCALAR(acceptBroadcast); 2279915SN/A SERIALIZE_SCALAR(acceptMulticast); 2280915SN/A SERIALIZE_SCALAR(acceptUnicast); 2281915SN/A SERIALIZE_SCALAR(acceptPerfect); 2282915SN/A SERIALIZE_SCALAR(acceptArp); 22831843SN/A SERIALIZE_SCALAR(multicastHashEnable); 2284915SN/A 2285915SN/A /* 2286854SN/A * Keep track of pending interrupt status. 2287854SN/A */ 2288854SN/A SERIALIZE_SCALAR(intrTick); 2289854SN/A SERIALIZE_SCALAR(cpuPendingIntr); 2290854SN/A Tick intrEventTick = 0; 2291854SN/A if (intrEvent) 2292854SN/A intrEventTick = intrEvent->when(); 2293854SN/A SERIALIZE_SCALAR(intrEventTick); 2294854SN/A 2295837SN/A} 2296837SN/A 2297837SN/Avoid 229810905SN/ANSGigE::unserialize(CheckpointIn &cp) 2299837SN/A{ 23009807SN/A // Unserialize the PciDevice base class 230110905SN/A PciDevice::unserialize(cp); 2302897SN/A 2303854SN/A UNSERIALIZE_SCALAR(regs.command); 2304854SN/A UNSERIALIZE_SCALAR(regs.config); 2305854SN/A UNSERIALIZE_SCALAR(regs.mear); 2306854SN/A UNSERIALIZE_SCALAR(regs.ptscr); 2307854SN/A UNSERIALIZE_SCALAR(regs.isr); 2308854SN/A UNSERIALIZE_SCALAR(regs.imr); 2309854SN/A UNSERIALIZE_SCALAR(regs.ier); 2310854SN/A UNSERIALIZE_SCALAR(regs.ihr); 2311854SN/A UNSERIALIZE_SCALAR(regs.txdp); 2312854SN/A UNSERIALIZE_SCALAR(regs.txdp_hi); 2313854SN/A UNSERIALIZE_SCALAR(regs.txcfg); 2314854SN/A UNSERIALIZE_SCALAR(regs.gpior); 2315854SN/A UNSERIALIZE_SCALAR(regs.rxdp); 2316854SN/A UNSERIALIZE_SCALAR(regs.rxdp_hi); 2317854SN/A UNSERIALIZE_SCALAR(regs.rxcfg); 2318854SN/A UNSERIALIZE_SCALAR(regs.pqcr); 2319854SN/A UNSERIALIZE_SCALAR(regs.wcsr); 2320854SN/A UNSERIALIZE_SCALAR(regs.pcr); 2321854SN/A UNSERIALIZE_SCALAR(regs.rfcr); 2322854SN/A UNSERIALIZE_SCALAR(regs.rfdr); 23231843SN/A UNSERIALIZE_SCALAR(regs.brar); 23241843SN/A UNSERIALIZE_SCALAR(regs.brdr); 2325854SN/A UNSERIALIZE_SCALAR(regs.srr); 2326854SN/A UNSERIALIZE_SCALAR(regs.mibc); 2327854SN/A UNSERIALIZE_SCALAR(regs.vrcr); 2328854SN/A UNSERIALIZE_SCALAR(regs.vtcr); 2329854SN/A UNSERIALIZE_SCALAR(regs.vdr); 2330854SN/A UNSERIALIZE_SCALAR(regs.ccsr); 2331854SN/A UNSERIALIZE_SCALAR(regs.tbicr); 2332854SN/A UNSERIALIZE_SCALAR(regs.tbisr); 2333854SN/A UNSERIALIZE_SCALAR(regs.tanar); 2334854SN/A UNSERIALIZE_SCALAR(regs.tanlpar); 2335854SN/A UNSERIALIZE_SCALAR(regs.taner); 2336854SN/A UNSERIALIZE_SCALAR(regs.tesr); 2337837SN/A 23381114SN/A UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 23391843SN/A UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2340837SN/A 2341927SN/A UNSERIALIZE_SCALAR(ioEnable); 2342917SN/A 2343854SN/A /* 2344915SN/A * unserialize the data fifos 2345915SN/A */ 234610905SN/A rxFifo.unserialize("rxFifo", cp); 234710905SN/A txFifo.unserialize("txFifo", cp); 2348915SN/A 2349915SN/A /* 2350854SN/A * unserialize the various helper variables 2351854SN/A */ 2352915SN/A bool txPacketExists; 2353915SN/A UNSERIALIZE_SCALAR(txPacketExists); 2354915SN/A if (txPacketExists) { 235511701Smichael.lebeane@amd.com txPacket = make_shared<EthPacketData>(); 235610905SN/A txPacket->unserialize("txPacket", cp); 2357915SN/A uint32_t txPktBufPtr; 2358915SN/A UNSERIALIZE_SCALAR(txPktBufPtr); 2359915SN/A txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2360915SN/A } else 2361915SN/A txPacket = 0; 2362915SN/A 2363915SN/A bool rxPacketExists; 2364915SN/A UNSERIALIZE_SCALAR(rxPacketExists); 2365915SN/A rxPacket = 0; 2366915SN/A if (rxPacketExists) { 236711701Smichael.lebeane@amd.com rxPacket = make_shared<EthPacketData>(); 236810905SN/A rxPacket->unserialize("rxPacket", cp); 2369915SN/A uint32_t rxPktBufPtr; 2370915SN/A UNSERIALIZE_SCALAR(rxPktBufPtr); 2371915SN/A rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2372915SN/A } else 2373915SN/A rxPacket = 0; 2374915SN/A 2375854SN/A UNSERIALIZE_SCALAR(txXferLen); 2376854SN/A UNSERIALIZE_SCALAR(rxXferLen); 2377837SN/A 2378854SN/A /* 23791909SN/A * Unserialize Cached Descriptors 2380854SN/A */ 23811909SN/A UNSERIALIZE_SCALAR(rxDesc64.link); 23821909SN/A UNSERIALIZE_SCALAR(rxDesc64.bufptr); 23831909SN/A UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 23841909SN/A UNSERIALIZE_SCALAR(rxDesc64.extsts); 23851909SN/A UNSERIALIZE_SCALAR(txDesc64.link); 23861909SN/A UNSERIALIZE_SCALAR(txDesc64.bufptr); 23871909SN/A UNSERIALIZE_SCALAR(txDesc64.cmdsts); 23881909SN/A UNSERIALIZE_SCALAR(txDesc64.extsts); 23891909SN/A UNSERIALIZE_SCALAR(rxDesc32.link); 23901909SN/A UNSERIALIZE_SCALAR(rxDesc32.bufptr); 23911909SN/A UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 23921909SN/A UNSERIALIZE_SCALAR(rxDesc32.extsts); 23931909SN/A UNSERIALIZE_SCALAR(txDesc32.link); 23941909SN/A UNSERIALIZE_SCALAR(txDesc32.bufptr); 23951909SN/A UNSERIALIZE_SCALAR(txDesc32.cmdsts); 23961909SN/A UNSERIALIZE_SCALAR(txDesc32.extsts); 23971801SN/A UNSERIALIZE_SCALAR(extstsEnable); 2398854SN/A 2399854SN/A /* 2400854SN/A * unserialize tx state machine 2401854SN/A */ 2402854SN/A int txState; 2403854SN/A UNSERIALIZE_SCALAR(txState); 2404854SN/A this->txState = (TxState) txState; 24051035SN/A UNSERIALIZE_SCALAR(txEnable); 2406854SN/A UNSERIALIZE_SCALAR(CTDD); 2407854SN/A UNSERIALIZE_SCALAR(txFragPtr); 2408854SN/A UNSERIALIZE_SCALAR(txDescCnt); 2409854SN/A int txDmaState; 2410854SN/A UNSERIALIZE_SCALAR(txDmaState); 2411854SN/A this->txDmaState = (DmaState) txDmaState; 24121801SN/A UNSERIALIZE_SCALAR(txKickTick); 24131801SN/A if (txKickTick) 24145606SN/A schedule(txKickEvent, txKickTick); 2415854SN/A 2416854SN/A /* 2417854SN/A * unserialize rx state machine 2418854SN/A */ 2419854SN/A int rxState; 2420854SN/A UNSERIALIZE_SCALAR(rxState); 2421854SN/A this->rxState = (RxState) rxState; 24221035SN/A UNSERIALIZE_SCALAR(rxEnable); 2423854SN/A UNSERIALIZE_SCALAR(CRDD); 2424854SN/A UNSERIALIZE_SCALAR(rxPktBytes); 24251224SN/A UNSERIALIZE_SCALAR(rxFragPtr); 2426854SN/A UNSERIALIZE_SCALAR(rxDescCnt); 2427854SN/A int rxDmaState; 2428854SN/A UNSERIALIZE_SCALAR(rxDmaState); 2429854SN/A this->rxDmaState = (DmaState) rxDmaState; 24301801SN/A UNSERIALIZE_SCALAR(rxKickTick); 24311801SN/A if (rxKickTick) 24325606SN/A schedule(rxKickEvent, rxKickTick); 2433854SN/A 24341843SN/A /* 24351843SN/A * Unserialize EEPROM state machine 24361843SN/A */ 24371843SN/A int eepromState; 24381843SN/A UNSERIALIZE_SCALAR(eepromState); 24391843SN/A this->eepromState = (EEPROMState) eepromState; 24401843SN/A UNSERIALIZE_SCALAR(eepromClk); 24411843SN/A UNSERIALIZE_SCALAR(eepromBitsToRx); 24421843SN/A UNSERIALIZE_SCALAR(eepromOpcode); 24431843SN/A UNSERIALIZE_SCALAR(eepromAddress); 24441843SN/A UNSERIALIZE_SCALAR(eepromData); 24451843SN/A 24461843SN/A /* 2447915SN/A * If there's a pending transmit, reschedule it now 2448854SN/A */ 2449854SN/A Tick transmitTick; 2450854SN/A UNSERIALIZE_SCALAR(transmitTick); 2451854SN/A if (transmitTick) 24527823SN/A schedule(txEvent, curTick() + transmitTick); 2453854SN/A 2454854SN/A /* 2455915SN/A * unserialize receive address filter settings 2456915SN/A */ 2457915SN/A UNSERIALIZE_SCALAR(rxFilterEnable); 2458915SN/A UNSERIALIZE_SCALAR(acceptBroadcast); 2459915SN/A UNSERIALIZE_SCALAR(acceptMulticast); 2460915SN/A UNSERIALIZE_SCALAR(acceptUnicast); 2461915SN/A UNSERIALIZE_SCALAR(acceptPerfect); 2462915SN/A UNSERIALIZE_SCALAR(acceptArp); 24631843SN/A UNSERIALIZE_SCALAR(multicastHashEnable); 2464915SN/A 2465915SN/A /* 2466854SN/A * Keep track of pending interrupt status. 2467854SN/A */ 2468854SN/A UNSERIALIZE_SCALAR(intrTick); 2469854SN/A UNSERIALIZE_SCALAR(cpuPendingIntr); 2470854SN/A Tick intrEventTick; 2471854SN/A UNSERIALIZE_SCALAR(intrEventTick); 2472854SN/A if (intrEventTick) { 24735606SN/A intrEvent = new IntrEvent(this, true); 24745606SN/A schedule(intrEvent, intrEventTick); 2475854SN/A } 2476854SN/A} 2477927SN/A 24784762SN/ANSGigE * 24794762SN/ANSGigEParams::create() 2480837SN/A{ 24814762SN/A return new NSGigE(this); 2482837SN/A} 2483