X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=dev%2Fns_gige.cc;h=9010850ab8a67cc1e09c497d768cbf1540cc0022;hb=1166d4f0bfe67a9dc178be3454b4f0eac38663ad;hp=0d446214d947a08daf30d1e184236a00a63f177a;hpb=eaeb1b6ff084b4797a31908fa5fb1d688c55dd60;p=gem5.git diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index 0d446214d..9010850ab 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -98,24 +98,25 @@ NSGigE::NSGigE(Params *p) txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), rxEnable(false), CRDD(false), rxPktBytes(0), rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), - rxDmaReadEvent(this), rxDmaWriteEvent(this), + eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), txDmaReadEvent(this), txDmaWriteEvent(this), dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), txDelay(p->tx_delay), rxDelay(p->rx_delay), rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), - acceptPerfect(false), acceptArp(false), + acceptPerfect(false), acceptArp(false), multicastHashEnable(false), physmem(p->pmem), intrTick(0), cpuPendingIntr(false), intrEvent(0), interface(0) { - if (p->header_bus) { - pioInterface = newPioInterface(name(), p->hier, - p->header_bus, this, + if (p->pio_bus) { + pioInterface = newPioInterface(name() + ".pio", p->hier, + p->pio_bus, this, &NSGigE::cacheAccess); + pioLatency = p->pio_latency * p->pio_bus->clockRate; + } - pioLatency = p->pio_latency * p->header_bus->clockRate; - + if (p->header_bus) { if (p->payload_bus) dmaInterface = new DMAInterface(name() + ".dma", p->header_bus, @@ -126,19 +127,10 @@ NSGigE::NSGigE(Params *p) p->header_bus, p->header_bus, 1, p->dma_no_allocate); - } else if (p->payload_bus) { - pioInterface = newPioInterface(name(), p->hier, - p->payload_bus, this, - &NSGigE::cacheAccess); - - pioLatency = p->pio_latency * p->payload_bus->clockRate; - - dmaInterface = new DMAInterface(name() + ".dma", - p->payload_bus, - p->payload_bus, 1, - p->dma_no_allocate); - } + } else if (p->payload_bus) + panic("Must define a header bus if defining a payload bus"); + pioDelayWrite = p->pio_delay_write && pioInterface; intrDelay = p->intr_delay; dmaReadDelay = p->dma_read_delay; @@ -148,6 +140,11 @@ NSGigE::NSGigE(Params *p) regsReset(); memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); + + memset(&rxDesc32, 0, sizeof(rxDesc32)); + memset(&txDesc32, 0, sizeof(txDesc32)); + memset(&rxDesc64, 0, sizeof(rxDesc64)); + memset(&txDesc64, 0, sizeof(txDesc64)); } NSGigE::~NSGigE() @@ -310,7 +307,7 @@ NSGigE::regStats() totalSwi .name(name() + ".totalSwi") - .desc("number of total Swi written to ISR") + .desc("total number of Swi written to ISR") .precision(0) ; @@ -328,7 +325,7 @@ NSGigE::regStats() totalRxIdle .name(name() + ".totalRxIdle") - .desc("number of total RxIdle written to ISR") + .desc("total number of RxIdle written to ISR") .precision(0) ; @@ -346,7 +343,7 @@ NSGigE::regStats() totalRxOk .name(name() + ".totalRxOk") - .desc("number of total RxOk written to ISR") + .desc("total number of RxOk written to ISR") .precision(0) ; @@ -364,7 +361,7 @@ NSGigE::regStats() totalRxDesc .name(name() + ".totalRxDesc") - .desc("number of total RxDesc written to ISR") + .desc("total number of RxDesc written to ISR") .precision(0) ; @@ -382,7 +379,7 @@ NSGigE::regStats() totalTxOk .name(name() + ".totalTxOk") - .desc("number of total TxOk written to ISR") + .desc("total number of TxOk written to ISR") .precision(0) ; @@ -400,7 +397,7 @@ NSGigE::regStats() totalTxIdle .name(name() + ".totalTxIdle") - .desc("number of total TxIdle written to ISR") + .desc("total number of TxIdle written to ISR") .precision(0) ; @@ -418,7 +415,7 @@ NSGigE::regStats() totalTxDesc .name(name() + ".totalTxDesc") - .desc("number of total TxDesc written to ISR") + .desc("total number of TxDesc written to ISR") .precision(0) ; @@ -436,7 +433,7 @@ NSGigE::regStats() totalRxOrn .name(name() + ".totalRxOrn") - .desc("number of total RxOrn written to ISR") + .desc("total number of RxOrn written to ISR") .precision(0) ; @@ -491,10 +488,10 @@ NSGigE::regStats() * This is to read the PCI general configuration registers */ void -NSGigE::ReadConfig(int offset, int size, uint8_t *data) +NSGigE::readConfig(int offset, int size, uint8_t *data) { if (offset < PCI_DEVICE_SPECIFIC) - PciDev::ReadConfig(offset, size, data); + PciDev::readConfig(offset, size, data); else panic("Device specific PCI config space not implemented!\n"); } @@ -503,10 +500,10 @@ NSGigE::ReadConfig(int offset, int size, uint8_t *data) * This is to write to the PCI general configuration registers */ void -NSGigE::WriteConfig(int offset, int size, uint32_t data) +NSGigE::writeConfig(int offset, int size, const uint8_t* data) { if (offset < PCI_DEVICE_SPECIFIC) - PciDev::WriteConfig(offset, size, data); + PciDev::writeConfig(offset, size, data); else panic("Device specific PCI config space not implemented!\n"); @@ -577,7 +574,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { - ReadConfig(daddr & 0xff, req->size, data); + readConfig(daddr & 0xff, req->size, data); return No_Fault; } else if (daddr >= MIB_START && daddr <= MIB_END) { // don't implement all the MIB's. hopefully the kernel @@ -593,6 +590,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) case sizeof(uint32_t): { uint32_t ® = *(uint32_t *)data; + uint16_t rfaddr; switch (daddr) { case CR: @@ -680,7 +678,9 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) break; case RFDR: - switch (regs.rfcr & RFCR_RFADDR) { + rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); + switch (rfaddr) { + // Read from perfect match ROM octets case 0x000: reg = rom.perfectMatch[1]; reg = reg << 8; @@ -695,9 +695,21 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) reg += rom.perfectMatch[4]; break; default: - panic("reading RFDR for something other than PMATCH!\n"); - // didn't implement other RFDR functionality b/c - // driver didn't use it + // Read filter hash table + if (rfaddr >= FHASH_ADDR && + rfaddr < FHASH_ADDR + FHASH_SIZE) { + + // Only word-aligned reads supported + if (rfaddr % 2) + panic("unaligned read from filter hash table!"); + + reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; + reg += rom.filterHash[rfaddr - FHASH_ADDR]; + break; + } + + panic("reading RFDR for something other than pattern" + " matching or hashing! %#x\n", rfaddr); } break; @@ -751,7 +763,11 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) break; case M5REG: - reg = params()->m5reg; + reg = 0; + if (params()->rx_thread) + reg |= M5REG_RX_THREAD; + if (params()->tx_thread) + reg |= M5REG_TX_THREAD; break; default: @@ -783,13 +799,22 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (daddr > LAST && daddr <= RESERVED) { panic("Accessing reserved register"); } else if (daddr > RESERVED && daddr <= 0x3FC) { - WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); + writeConfig(daddr & 0xff, req->size, data); return No_Fault; } else if (daddr > 0x3FC) panic("Something is messed up!\n"); + if (pioDelayWrite) { + int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; + if (cpu >= writeQueue.size()) + writeQueue.resize(cpu + 1); + writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data)); + } + if (req->size == sizeof(uint32_t)) { uint32_t reg = *(uint32_t *)data; + uint16_t rfaddr; + DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); switch (daddr) { @@ -798,20 +823,24 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & CR_TXD) { txEnable = false; } else if (reg & CR_TXE) { - txEnable = true; + if (!pioDelayWrite) { + txEnable = true; - // the kernel is enabling the transmit machine - if (txState == txIdle) - txKick(); + // the kernel is enabling the transmit machine + if (txState == txIdle) + txKick(); + } } if (reg & CR_RXD) { rxEnable = false; } else if (reg & CR_RXE) { - rxEnable = true; + if (!pioDelayWrite) { + rxEnable = true; - if (rxState == rxIdle) - rxKick(); + if (rxState == rxIdle) + rxKick(); + } } if (reg & CR_TXR) @@ -838,8 +867,12 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) reg & CFGR_RESERVED || reg & CFGR_T64ADDR || reg & CFGR_PCI64_DET) - panic("writing to read-only or reserved CFGR bits!\n"); + // First clear all writable bits + regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | + CFGR_RESERVED | CFGR_T64ADDR | + CFGR_PCI64_DET; + // Now set the appropriate writable bits regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | CFGR_RESERVED | CFGR_T64ADDR | CFGR_PCI64_DET); @@ -847,15 +880,12 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) // all these #if 0's are because i don't THINK the kernel needs to // have these implemented. if there is a problem relating to one of // these, you may need to add functionality in. -#if 0 if (reg & CFGR_TBI_EN) ; if (reg & CFGR_MODE_1000) ; -#endif if (reg & CFGR_AUTO_1000) panic("CFGR_AUTO_1000 not implemented!\n"); -#if 0 if (reg & CFGR_PINT_DUPSTS || reg & CFGR_PINT_LNKSTS || reg & CFGR_PINT_SPDSTS) @@ -865,8 +895,8 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & CFGR_MRM_DIS) ; if (reg & CFGR_MWI_DIS) ; - if (reg & CFGR_T64ADDR) - panic("CFGR_T64ADDR is read only register!\n"); + if (reg & CFGR_T64ADDR) ; + // panic("CFGR_T64ADDR is read only register!\n"); if (reg & CFGR_PCI64_DET) panic("CFGR_PCI64_DET is read only register!\n"); @@ -875,39 +905,46 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) if (reg & CFGR_M64ADDR) ; if (reg & CFGR_PHY_RST) ; if (reg & CFGR_PHY_DIS) ; -#endif if (reg & CFGR_EXTSTS_EN) extstsEnable = true; else extstsEnable = false; -#if 0 - if (reg & CFGR_REQALG) ; - if (reg & CFGR_SB) ; - if (reg & CFGR_POW) ; - if (reg & CFGR_EXD) ; - if (reg & CFGR_PESEL) ; - if (reg & CFGR_BROM_DIS) ; - if (reg & CFGR_EXT_125) ; - if (reg & CFGR_BEM) ; -#endif + if (reg & CFGR_REQALG) ; + if (reg & CFGR_SB) ; + if (reg & CFGR_POW) ; + if (reg & CFGR_EXD) ; + if (reg & CFGR_PESEL) ; + if (reg & CFGR_BROM_DIS) ; + if (reg & CFGR_EXT_125) ; + if (reg & CFGR_BEM) ; break; case MEAR: - regs.mear = reg; + // Clear writable bits + regs.mear &= MEAR_EEDO; + // Set appropriate writable bits + regs.mear |= reg & ~MEAR_EEDO; + + // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) + // even though it could get it through RFDR + if (reg & MEAR_EESEL) { + // Rising edge of clock + if (reg & MEAR_EECLK && !eepromClk) + eepromKick(); + } + else { + eepromState = eepromStart; + regs.mear &= ~MEAR_EEDI; + } + + eepromClk = reg & MEAR_EECLK; + // since phy is completely faked, MEAR_MD* don't matter - // and since the driver never uses MEAR_EE*, they don't - // matter -#if 0 - if (reg & MEAR_EEDI) ; - if (reg & MEAR_EEDO) ; // this one is read only - if (reg & MEAR_EECLK) ; - if (reg & MEAR_EESEL) ; if (reg & MEAR_MDIO) ; if (reg & MEAR_MDDIR) ; if (reg & MEAR_MDC) ; -#endif break; case PTSCR: @@ -980,7 +1017,11 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) break; case GPIOR: - regs.gpior = reg; + // Only write writable bits + regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN + | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; + regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN + | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); /* these just control general purpose i/o pins, don't matter */ break; @@ -1037,14 +1078,14 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) acceptUnicast = (reg & RFCR_AAU) ? true : false; acceptPerfect = (reg & RFCR_APM) ? true : false; acceptArp = (reg & RFCR_AARP) ? true : false; + multicastHashEnable = (reg & RFCR_MHEN) ? true : false; #if 0 if (reg & RFCR_APAT) panic("RFCR_APAT not implemented!\n"); #endif - - if (reg & RFCR_MHEN || reg & RFCR_UHEN) - panic("hash filtering not implemented!\n"); + if (reg & RFCR_UHEN) + panic("Unicast hash filtering not used by drivers!\n"); if (reg & RFCR_ULM) panic("RFCR_ULM not implemented!\n"); @@ -1052,10 +1093,41 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) break; case RFDR: - panic("the driver never writes to RFDR, something is wrong!\n"); + rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); + switch (rfaddr) { + case 0x000: + rom.perfectMatch[0] = (uint8_t)reg; + rom.perfectMatch[1] = (uint8_t)(reg >> 8); + break; + case 0x002: + rom.perfectMatch[2] = (uint8_t)reg; + rom.perfectMatch[3] = (uint8_t)(reg >> 8); + break; + case 0x004: + rom.perfectMatch[4] = (uint8_t)reg; + rom.perfectMatch[5] = (uint8_t)(reg >> 8); + break; + default: + + if (rfaddr >= FHASH_ADDR && + rfaddr < FHASH_ADDR + FHASH_SIZE) { + + // Only word-aligned writes supported + if (rfaddr % 2) + panic("unaligned write to filter hash table!"); + + rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; + rom.filterHash[rfaddr - FHASH_ADDR + 1] + = (uint8_t)(reg >> 8); + break; + } + panic("writing RFDR for something other than pattern matching\ + or hashing! %#x\n", rfaddr); + } case BRAR: - panic("the driver never uses BRAR, something is wrong!\n"); + regs.brar = reg; + break; case BRDR: panic("the driver never uses BRDR, something is wrong!\n"); @@ -1076,7 +1148,6 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) case VDR: panic("the driver never uses VDR, something is wrong!\n"); - break; case CCSR: /* not going to implement clockrun stuff */ @@ -1103,12 +1174,16 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data) panic("TBISR is read only register!\n"); case TANAR: - regs.tanar = reg; - if (reg & TANAR_PS2) - panic("this isn't used in driver, something wrong!\n"); + // Only write the writable bits + regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; + regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); + + // Pause capability unimplemented +#if 0 + if (reg & TANAR_PS2) ; + if (reg & TANAR_PS1) ; +#endif - if (reg & TANAR_PS1) - panic("this isn't used in driver, something wrong!\n"); break; case TANLPAR: @@ -1140,7 +1215,7 @@ NSGigE::devIntrPost(uint32_t interrupts) if (interrupts & ISR_NOIMPL) warn("interrupt not implemented %#x\n", interrupts); - interrupts &= ~ISR_NOIMPL; + interrupts &= ISR_IMPL; regs.isr |= interrupts; if (interrupts & regs.imr) { @@ -1176,7 +1251,7 @@ NSGigE::devIntrPost(uint32_t interrupts) if ((regs.isr & regs.imr)) { Tick when = curTick; - if (!(regs.isr & regs.imr & ISR_NODELAY)) + if ((regs.isr & regs.imr & ISR_NODELAY) == 0) when += intrDelay; cpuIntrPost(when); } @@ -1218,8 +1293,7 @@ NSGigE::devIntrClear(uint32_t interrupts) postedRxOrn++; } - if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC | - ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) ) + if (regs.isr & regs.imr & ISR_IMPL) postedInterrupts++; interrupts &= ~ISR_NOIMPL; @@ -1361,7 +1435,7 @@ NSGigE::regsReset() { memset(®s, 0, sizeof(regs)); regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); - regs.mear = 0x22; + regs.mear = 0x12; regs.txcfg = 0x120; // set drain threshold to 1024 bytes and // fill threshold to 32 bytes regs.rxcfg = 0x4; // set drain threshold to 16 bytes @@ -1369,6 +1443,7 @@ NSGigE::regsReset() regs.mibc = MIBC_FRZ; regs.vdr = 0x81; // set the vlan tag type to 802.1q regs.tesr = 0xc000; // TBI capable of both full and half duplex + regs.brar = 0xffffffff; extstsEnable = false; acceptBroadcast = false; @@ -1485,8 +1560,15 @@ NSGigE::rxDmaWriteDone() void NSGigE::rxKick() { - DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n", - NsRxStateStrings[rxState], rxFifo.size()); + bool is64bit = (bool)(regs.config & CFGR_M64ADDR); + + DPRINTF(EthernetSM, + "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", + NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); + + Addr link, bufptr; + uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; + uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; next: if (clock) { @@ -1514,6 +1596,9 @@ NSGigE::rxKick() break; } + link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; + bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; + // see state machine from spec for details // the way this works is, if you finish work on one state and can // go directly to another, you do that through jumping to the @@ -1532,8 +1617,9 @@ NSGigE::rxKick() rxState = rxDescRefr; rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = &rxDescCache + offsetof(ns_desc, link); - rxDmaLen = sizeof(rxDescCache.link); + rxDmaData = + is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; + rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); rxDmaFree = dmaDescFree; descDmaReads++; @@ -1545,8 +1631,8 @@ NSGigE::rxKick() rxState = rxDescRead; rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = &rxDescCache; - rxDmaLen = sizeof(ns_desc); + rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; + rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); rxDmaFree = dmaDescFree; descDmaReads++; @@ -1568,21 +1654,20 @@ NSGigE::rxKick() if (rxDmaState != dmaIdle) goto exit; - DPRINTF(EthernetDesc, "rxDescCache: addr=%08x read descriptor\n", + DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", regs.rxdp & 0x3fffffff); DPRINTF(EthernetDesc, - "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", - rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, - rxDescCache.extsts); + "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", + link, bufptr, cmdsts, extsts); - if (rxDescCache.cmdsts & CMDSTS_OWN) { + if (cmdsts & CMDSTS_OWN) { devIntrPost(ISR_RXIDLE); rxState = rxIdle; goto exit; } else { rxState = rxFifoBlock; - rxFragPtr = rxDescCache.bufptr; - rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; + rxFragPtr = bufptr; + rxDescCnt = cmdsts & CMDSTS_LEN_MASK; } break; @@ -1648,11 +1733,11 @@ NSGigE::rxKick() assert(rxPktBytes == 0); DPRINTF(EthernetSM, "done with receiving packet\n"); - rxDescCache.cmdsts |= CMDSTS_OWN; - rxDescCache.cmdsts &= ~CMDSTS_MORE; - rxDescCache.cmdsts |= CMDSTS_OK; - rxDescCache.cmdsts &= 0xffff0000; - rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE + cmdsts |= CMDSTS_OWN; + cmdsts &= ~CMDSTS_MORE; + cmdsts |= CMDSTS_OK; + cmdsts &= 0xffff0000; + cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE #if 0 /* @@ -1663,41 +1748,41 @@ NSGigE::rxKick() * functional purposes, just undef */ if (rxFilterEnable) { - rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; + cmdsts &= ~CMDSTS_DEST_MASK; const EthAddr &dst = rxFifoFront()->dst(); if (dst->unicast()) - rxDescCache.cmdsts |= CMDSTS_DEST_SELF; + cmdsts |= CMDSTS_DEST_SELF; if (dst->multicast()) - rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; + cmdsts |= CMDSTS_DEST_MULTI; if (dst->broadcast()) - rxDescCache.cmdsts |= CMDSTS_DEST_MASK; + cmdsts |= CMDSTS_DEST_MASK; } #endif IpPtr ip(rxPacket); if (extstsEnable && ip) { - rxDescCache.extsts |= EXTSTS_IPPKT; + extsts |= EXTSTS_IPPKT; rxIpChecksums++; if (cksum(ip) != 0) { DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); - rxDescCache.extsts |= EXTSTS_IPERR; + extsts |= EXTSTS_IPERR; } TcpPtr tcp(ip); UdpPtr udp(ip); if (tcp) { - rxDescCache.extsts |= EXTSTS_TCPPKT; + extsts |= EXTSTS_TCPPKT; rxTcpChecksums++; if (cksum(tcp) != 0) { DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); - rxDescCache.extsts |= EXTSTS_TCPERR; + extsts |= EXTSTS_TCPERR; } } else if (udp) { - rxDescCache.extsts |= EXTSTS_UDPPKT; + extsts |= EXTSTS_UDPPKT; rxUdpChecksums++; if (cksum(udp) != 0) { DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); - rxDescCache.extsts |= EXTSTS_UDPERR; + extsts |= EXTSTS_UDPERR; } } } @@ -1711,16 +1796,21 @@ NSGigE::rxKick() */ DPRINTF(EthernetDesc, - "rxDescCache: addr=%08x writeback cmdsts extsts\n", + "rxDesc: addr=%08x writeback cmdsts extsts\n", regs.rxdp & 0x3fffffff); DPRINTF(EthernetDesc, - "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", - rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, - rxDescCache.extsts); + "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", + link, bufptr, cmdsts, extsts); - rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; - rxDmaData = &(rxDescCache.cmdsts); - rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); + rxDmaAddr = regs.rxdp & 0x3fffffff; + rxDmaData = &cmdsts; + if (is64bit) { + rxDmaAddr += offsetof(ns_desc64, cmdsts); + rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); + } else { + rxDmaAddr += offsetof(ns_desc32, cmdsts); + rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); + } rxDmaFree = dmaDescFree; descDmaWrites++; @@ -1746,12 +1836,12 @@ NSGigE::rxKick() if (rxDmaState != dmaIdle) goto exit; - assert(rxDescCache.cmdsts & CMDSTS_OWN); + assert(cmdsts & CMDSTS_OWN); assert(rxPacket == 0); devIntrPost(ISR_RXOK); - if (rxDescCache.cmdsts & CMDSTS_INTR) + if (cmdsts & CMDSTS_INTR) devIntrPost(ISR_RXDESC); if (!rxEnable) { @@ -1763,19 +1853,21 @@ NSGigE::rxKick() break; case rxAdvance: - if (rxDescCache.link == 0) { + if (link == 0) { devIntrPost(ISR_RXIDLE); rxState = rxIdle; CRDD = true; goto exit; } else { + if (rxDmaState != dmaIdle) + goto exit; rxState = rxDescRead; - regs.rxdp = rxDescCache.link; + regs.rxdp = link; CRDD = false; rxDmaAddr = regs.rxdp & 0x3fffffff; - rxDmaData = &rxDescCache; - rxDmaLen = sizeof(ns_desc); + rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; + rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); rxDmaFree = dmaDescFree; if (doRxDmaRead()) @@ -1822,7 +1914,8 @@ NSGigE::transmit() if (tcp) { DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", - tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack()); + tcp->sport(), tcp->dport(), tcp->seq(), + tcp->ack()); } } } @@ -1959,8 +2052,14 @@ NSGigE::txDmaWriteDone() void NSGigE::txKick() { - DPRINTF(EthernetSM, "transmit kick txState=%s\n", - NsTxStateStrings[txState]); + bool is64bit = (bool)(regs.config & CFGR_M64ADDR); + + DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", + NsTxStateStrings[txState], is64bit ? 64 : 32); + + Addr link, bufptr; + uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; + uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; next: if (clock) { @@ -1987,6 +2086,8 @@ NSGigE::txKick() break; } + link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; + bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; switch (txState) { case txIdle: if (!txEnable) { @@ -1998,8 +2099,9 @@ NSGigE::txKick() txState = txDescRefr; txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = &txDescCache + offsetof(ns_desc, link); - txDmaLen = sizeof(txDescCache.link); + txDmaData = + is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; + txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); txDmaFree = dmaDescFree; descDmaReads++; @@ -2012,8 +2114,8 @@ NSGigE::txKick() txState = txDescRead; txDmaAddr = regs.txdp & 0x3fffffff; - txDmaData = &txDescCache; - txDmaLen = sizeof(ns_desc); + txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; + txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); txDmaFree = dmaDescFree; descDmaReads++; @@ -2035,17 +2137,16 @@ NSGigE::txKick() if (txDmaState != dmaIdle) goto exit; - DPRINTF(EthernetDesc, "txDescCache: addr=%08x read descriptor\n", + DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", regs.txdp & 0x3fffffff); DPRINTF(EthernetDesc, - "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n", - txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, - txDescCache.extsts); + "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", + link, bufptr, cmdsts, extsts); - if (txDescCache.cmdsts & CMDSTS_OWN) { + if (cmdsts & CMDSTS_OWN) { txState = txFifoBlock; - txFragPtr = txDescCache.bufptr; - txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; + txFragPtr = bufptr; + txDescCnt = cmdsts & CMDSTS_LEN_MASK; } else { devIntrPost(ISR_TXIDLE); txState = txIdle; @@ -2062,16 +2163,21 @@ NSGigE::txKick() if (txDescCnt == 0) { DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); - if (txDescCache.cmdsts & CMDSTS_MORE) { + if (cmdsts & CMDSTS_MORE) { DPRINTF(EthernetSM, "there are more descriptors to come\n"); txState = txDescWrite; - txDescCache.cmdsts &= ~CMDSTS_OWN; + cmdsts &= ~CMDSTS_OWN; - txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); - txDmaAddr &= 0x3fffffff; - txDmaData = &(txDescCache.cmdsts); - txDmaLen = sizeof(txDescCache.cmdsts); + txDmaAddr = regs.txdp & 0x3fffffff; + txDmaData = &cmdsts; + if (is64bit) { + txDmaAddr += offsetof(ns_desc64, cmdsts); + txDmaLen = sizeof(txDesc64.cmdsts); + } else { + txDmaAddr += offsetof(ns_desc32, cmdsts); + txDmaLen = sizeof(txDesc32.cmdsts); + } txDmaFree = dmaDescFree; if (doTxDmaWrite()) @@ -2082,18 +2188,18 @@ NSGigE::txKick() /* deal with the the packet that just finished */ if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { IpPtr ip(txPacket); - if (txDescCache.extsts & EXTSTS_UDPPKT) { + if (extsts & EXTSTS_UDPPKT) { UdpPtr udp(ip); udp->sum(0); udp->sum(cksum(udp)); txUdpChecksums++; - } else if (txDescCache.extsts & EXTSTS_TCPPKT) { + } else if (extsts & EXTSTS_TCPPKT) { TcpPtr tcp(ip); tcp->sum(0); tcp->sum(cksum(tcp)); txTcpChecksums++; } - if (txDescCache.extsts & EXTSTS_IPPKT) { + if (extsts & EXTSTS_IPPKT) { ip->sum(0); ip->sum(cksum(ip)); txIpChecksums++; @@ -2103,7 +2209,10 @@ NSGigE::txKick() txPacket->length = txPacketBufPtr - txPacket->data; // this is just because the receive can't handle a // packet bigger want to make sure - assert(txPacket->length <= 1514); + if (txPacket->length > 1514) + panic("transmit packet too large, %s > 1514\n", + txPacket->length); + #ifndef NDEBUG bool success = #endif @@ -2122,19 +2231,25 @@ NSGigE::txKick() * spec would complicate the code, we just do it here */ - txDescCache.cmdsts &= ~CMDSTS_OWN; - txDescCache.cmdsts |= CMDSTS_OK; + cmdsts &= ~CMDSTS_OWN; + cmdsts |= CMDSTS_OK; DPRINTF(EthernetDesc, "txDesc writeback: cmdsts=%08x extsts=%08x\n", - txDescCache.cmdsts, txDescCache.extsts); + cmdsts, extsts); - txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); - txDmaAddr &= 0x3fffffff; - txDmaData = &(txDescCache.cmdsts); - txDmaLen = sizeof(txDescCache.cmdsts) + - sizeof(txDescCache.extsts); txDmaFree = dmaDescFree; + txDmaAddr = regs.txdp & 0x3fffffff; + txDmaData = &cmdsts; + if (is64bit) { + txDmaAddr += offsetof(ns_desc64, cmdsts); + txDmaLen = + sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); + } else { + txDmaAddr += offsetof(ns_desc32, cmdsts); + txDmaLen = + sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); + } descDmaWrites++; descDmaWrBytes += txDmaLen; @@ -2198,7 +2313,7 @@ NSGigE::txKick() if (txDmaState != dmaIdle) goto exit; - if (txDescCache.cmdsts & CMDSTS_INTR) + if (cmdsts & CMDSTS_INTR) devIntrPost(ISR_TXDESC); if (!txEnable) { @@ -2210,18 +2325,20 @@ NSGigE::txKick() break; case txAdvance: - if (txDescCache.link == 0) { + if (link == 0) { devIntrPost(ISR_TXIDLE); txState = txIdle; goto exit; } else { + if (txDmaState != dmaIdle) + goto exit; txState = txDescRead; - regs.txdp = txDescCache.link; + regs.txdp = link; CTDD = false; - txDmaAddr = txDescCache.link & 0x3fffffff; - txDmaData = &txDescCache; - txDmaLen = sizeof(ns_desc); + txDmaAddr = link & 0x3fffffff; + txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; + txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); txDmaFree = dmaDescFree; if (doTxDmaRead()) @@ -2248,6 +2365,107 @@ NSGigE::txKick() txKickEvent.schedule(txKickTick); } +/** + * Advance the EEPROM state machine + * Called on rising edge of EEPROM clock bit in MEAR + */ +void +NSGigE::eepromKick() +{ + switch (eepromState) { + + case eepromStart: + + // Wait for start bit + if (regs.mear & MEAR_EEDI) { + // Set up to get 2 opcode bits + eepromState = eepromGetOpcode; + eepromBitsToRx = 2; + eepromOpcode = 0; + } + break; + + case eepromGetOpcode: + eepromOpcode <<= 1; + eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; + --eepromBitsToRx; + + // Done getting opcode + if (eepromBitsToRx == 0) { + if (eepromOpcode != EEPROM_READ) + panic("only EEPROM reads are implemented!"); + + // Set up to get address + eepromState = eepromGetAddress; + eepromBitsToRx = 6; + eepromAddress = 0; + } + break; + + case eepromGetAddress: + eepromAddress <<= 1; + eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; + --eepromBitsToRx; + + // Done getting address + if (eepromBitsToRx == 0) { + + if (eepromAddress >= EEPROM_SIZE) + panic("EEPROM read access out of range!"); + + switch (eepromAddress) { + + case EEPROM_PMATCH2_ADDR: + eepromData = rom.perfectMatch[5]; + eepromData <<= 8; + eepromData += rom.perfectMatch[4]; + break; + + case EEPROM_PMATCH1_ADDR: + eepromData = rom.perfectMatch[3]; + eepromData <<= 8; + eepromData += rom.perfectMatch[2]; + break; + + case EEPROM_PMATCH0_ADDR: + eepromData = rom.perfectMatch[1]; + eepromData <<= 8; + eepromData += rom.perfectMatch[0]; + break; + + default: + panic("FreeBSD driver only uses EEPROM to read PMATCH!"); + } + // Set up to read data + eepromState = eepromRead; + eepromBitsToRx = 16; + + // Clear data in bit + regs.mear &= ~MEAR_EEDI; + } + break; + + case eepromRead: + // Clear Data Out bit + regs.mear &= ~MEAR_EEDO; + // Set bit to value of current EEPROM bit + regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; + + eepromData <<= 1; + --eepromBitsToRx; + + // All done + if (eepromBitsToRx == 0) { + eepromState = eepromStart; + } + break; + + default: + panic("invalid EEPROM state"); + } + +} + void NSGigE::transferDone() { @@ -2294,6 +2512,9 @@ NSGigE::rxFilter(const PacketPtr &packet) if (acceptMulticast) drop = false; + // Multicast hashing faked - all packets accepted + if (multicastHashEnable) + drop = false; } if (drop) { @@ -2315,13 +2536,17 @@ NSGigE::recvPacket(PacketPtr packet) if (!rxEnable) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); - interface->recvDone(); return true; } - if (rxFilterEnable && rxFilter(packet)) { + if (!rxFilterEnable) { + DPRINTF(Ethernet, + "receive packet filtering disabled . . . packet dropped\n"); + return true; + } + + if (rxFilter(packet)) { DPRINTF(Ethernet, "packet filtered...dropped\n"); - interface->recvDone(); return true; } @@ -2344,7 +2569,6 @@ NSGigE::recvPacket(PacketPtr packet) } rxFifo.push(packet); - interface->recvDone(); rxKick(); return true; @@ -2394,6 +2618,8 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(regs.pcr); SERIALIZE_SCALAR(regs.rfcr); SERIALIZE_SCALAR(regs.rfdr); + SERIALIZE_SCALAR(regs.brar); + SERIALIZE_SCALAR(regs.brdr); SERIALIZE_SCALAR(regs.srr); SERIALIZE_SCALAR(regs.mibc); SERIALIZE_SCALAR(regs.vrcr); @@ -2408,6 +2634,7 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(regs.tesr); SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); + SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); SERIALIZE_SCALAR(ioEnable); @@ -2441,16 +2668,24 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(rxXferLen); /* - * Serialize DescCaches + * Serialize Cached Descriptors */ - SERIALIZE_SCALAR(txDescCache.link); - SERIALIZE_SCALAR(txDescCache.bufptr); - SERIALIZE_SCALAR(txDescCache.cmdsts); - SERIALIZE_SCALAR(txDescCache.extsts); - SERIALIZE_SCALAR(rxDescCache.link); - SERIALIZE_SCALAR(rxDescCache.bufptr); - SERIALIZE_SCALAR(rxDescCache.cmdsts); - SERIALIZE_SCALAR(rxDescCache.extsts); + SERIALIZE_SCALAR(rxDesc64.link); + SERIALIZE_SCALAR(rxDesc64.bufptr); + SERIALIZE_SCALAR(rxDesc64.cmdsts); + SERIALIZE_SCALAR(rxDesc64.extsts); + SERIALIZE_SCALAR(txDesc64.link); + SERIALIZE_SCALAR(txDesc64.bufptr); + SERIALIZE_SCALAR(txDesc64.cmdsts); + SERIALIZE_SCALAR(txDesc64.extsts); + SERIALIZE_SCALAR(rxDesc32.link); + SERIALIZE_SCALAR(rxDesc32.bufptr); + SERIALIZE_SCALAR(rxDesc32.cmdsts); + SERIALIZE_SCALAR(rxDesc32.extsts); + SERIALIZE_SCALAR(txDesc32.link); + SERIALIZE_SCALAR(txDesc32.bufptr); + SERIALIZE_SCALAR(txDesc32.cmdsts); + SERIALIZE_SCALAR(txDesc32.extsts); SERIALIZE_SCALAR(extstsEnable); /* @@ -2480,6 +2715,17 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(rxDmaState); SERIALIZE_SCALAR(rxKickTick); + /* + * Serialize EEPROM state machine + */ + int eepromState = this->eepromState; + SERIALIZE_SCALAR(eepromState); + SERIALIZE_SCALAR(eepromClk); + SERIALIZE_SCALAR(eepromBitsToRx); + SERIALIZE_SCALAR(eepromOpcode); + SERIALIZE_SCALAR(eepromAddress); + SERIALIZE_SCALAR(eepromData); + /* * If there's a pending transmit, store the time so we can * reschedule it later @@ -2496,6 +2742,7 @@ NSGigE::serialize(ostream &os) SERIALIZE_SCALAR(acceptUnicast); SERIALIZE_SCALAR(acceptPerfect); SERIALIZE_SCALAR(acceptArp); + SERIALIZE_SCALAR(multicastHashEnable); /* * Keep track of pending interrupt status. @@ -2535,6 +2782,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(regs.pcr); UNSERIALIZE_SCALAR(regs.rfcr); UNSERIALIZE_SCALAR(regs.rfdr); + UNSERIALIZE_SCALAR(regs.brar); + UNSERIALIZE_SCALAR(regs.brdr); UNSERIALIZE_SCALAR(regs.srr); UNSERIALIZE_SCALAR(regs.mibc); UNSERIALIZE_SCALAR(regs.vrcr); @@ -2549,6 +2798,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(regs.tesr); UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); + UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); UNSERIALIZE_SCALAR(ioEnable); @@ -2588,16 +2838,24 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxXferLen); /* - * Unserialize DescCaches + * Unserialize Cached Descriptors */ - UNSERIALIZE_SCALAR(txDescCache.link); - UNSERIALIZE_SCALAR(txDescCache.bufptr); - UNSERIALIZE_SCALAR(txDescCache.cmdsts); - UNSERIALIZE_SCALAR(txDescCache.extsts); - UNSERIALIZE_SCALAR(rxDescCache.link); - UNSERIALIZE_SCALAR(rxDescCache.bufptr); - UNSERIALIZE_SCALAR(rxDescCache.cmdsts); - UNSERIALIZE_SCALAR(rxDescCache.extsts); + UNSERIALIZE_SCALAR(rxDesc64.link); + UNSERIALIZE_SCALAR(rxDesc64.bufptr); + UNSERIALIZE_SCALAR(rxDesc64.cmdsts); + UNSERIALIZE_SCALAR(rxDesc64.extsts); + UNSERIALIZE_SCALAR(txDesc64.link); + UNSERIALIZE_SCALAR(txDesc64.bufptr); + UNSERIALIZE_SCALAR(txDesc64.cmdsts); + UNSERIALIZE_SCALAR(txDesc64.extsts); + UNSERIALIZE_SCALAR(rxDesc32.link); + UNSERIALIZE_SCALAR(rxDesc32.bufptr); + UNSERIALIZE_SCALAR(rxDesc32.cmdsts); + UNSERIALIZE_SCALAR(rxDesc32.extsts); + UNSERIALIZE_SCALAR(txDesc32.link); + UNSERIALIZE_SCALAR(txDesc32.bufptr); + UNSERIALIZE_SCALAR(txDesc32.cmdsts); + UNSERIALIZE_SCALAR(txDesc32.extsts); UNSERIALIZE_SCALAR(extstsEnable); /* @@ -2635,7 +2893,19 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) if (rxKickTick) rxKickEvent.schedule(rxKickTick); - /* + /* + * Unserialize EEPROM state machine + */ + int eepromState; + UNSERIALIZE_SCALAR(eepromState); + this->eepromState = (EEPROMState) eepromState; + UNSERIALIZE_SCALAR(eepromClk); + UNSERIALIZE_SCALAR(eepromBitsToRx); + UNSERIALIZE_SCALAR(eepromOpcode); + UNSERIALIZE_SCALAR(eepromAddress); + UNSERIALIZE_SCALAR(eepromData); + + /* * If there's a pending transmit, reschedule it now */ Tick transmitTick; @@ -2652,6 +2922,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(acceptUnicast); UNSERIALIZE_SCALAR(acceptPerfect); UNSERIALIZE_SCALAR(acceptArp); + UNSERIALIZE_SCALAR(multicastHashEnable); /* * Keep track of pending interrupt status. @@ -2677,8 +2948,38 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) Tick NSGigE::cacheAccess(MemReqPtr &req) { + Addr daddr = req->paddr & 0xfff; DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", - req->paddr, req->paddr - addr); + req->paddr, daddr); + + if (!pioDelayWrite || !req->cmd.isWrite()) + return curTick + pioLatency; + + int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; + std::list &wq = writeQueue[cpu]; + if (wq.empty()) + panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr); + + const RegWriteData &data = wq.front(); + if (data.daddr != daddr) + panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x", + cpu, data.daddr, daddr); + + if (daddr == CR) { + if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) { + txEnable = true; + if (txState == txIdle) + txKick(); + } + + if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) { + rxEnable = true; + if (rxState == rxIdle) + rxKick(); + } + } + + wq.pop_front(); return curTick + pioLatency; } @@ -2714,70 +3015,83 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) - Param addr; Param clock; - Param tx_delay; - Param rx_delay; - Param intr_delay; + + Param addr; SimObjectParam mmu; SimObjectParam physmem; - Param rx_filter; - Param hardware_address; - SimObjectParam io_bus; - SimObjectParam payload_bus; + SimObjectParam configspace; + SimObjectParam configdata; + SimObjectParam platform; + Param pci_bus; + Param pci_dev; + Param pci_func; + SimObjectParam hier; - Param pio_latency; + SimObjectParam pio_bus; + SimObjectParam dma_bus; + SimObjectParam payload_bus; Param dma_desc_free; Param dma_data_free; Param dma_read_delay; Param dma_write_delay; Param dma_read_factor; Param dma_write_factor; - SimObjectParam configspace; - SimObjectParam configdata; - SimObjectParam platform; - Param pci_bus; - Param pci_dev; - Param pci_func; - Param tx_fifo_size; - Param rx_fifo_size; - Param m5reg; Param dma_no_allocate; + Param pio_latency; + Param pio_delay_write; + Param intr_delay; + + Param rx_delay; + Param tx_delay; + Param rx_fifo_size; + Param tx_fifo_size; + + Param rx_filter; + Param hardware_address; + Param rx_thread; + Param tx_thread; END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) - INIT_PARAM(addr, "Device Address"), INIT_PARAM(clock, "State machine processor frequency"), - INIT_PARAM(tx_delay, "Transmit Delay"), - INIT_PARAM(rx_delay, "Receive Delay"), - INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), + + INIT_PARAM(addr, "Device Address"), INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), - INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", - "00:99:00:00:00:01"), - INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), - INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), - INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), - INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), - INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), - INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), - INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(platform, "Platform"), INIT_PARAM(pci_bus, "PCI bus"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), - INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072), - INIT_PARAM(m5reg, "m5 register"), - INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true) + + INIT_PARAM(hier, "Hierarchy global variables"), + INIT_PARAM(pio_bus, ""), + INIT_PARAM(dma_bus, ""), + INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), + INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), + INIT_PARAM(dma_data_free, "DMA of Data is free"), + INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), + INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), + INIT_PARAM(dma_read_factor, "multiplier for dma reads"), + INIT_PARAM(dma_write_factor, "multiplier for dma writes"), + INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), + INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), + INIT_PARAM(pio_delay_write, ""), + INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), + + INIT_PARAM(rx_delay, "Receive Delay"), + INIT_PARAM(tx_delay, "Transmit Delay"), + INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), + INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), + + INIT_PARAM(rx_filter, "Enable Receive Filter"), + INIT_PARAM(hardware_address, "Ethernet Hardware Address"), + INIT_PARAM(rx_thread, ""), + INIT_PARAM(tx_thread, "") END_INIT_SIM_OBJECT_PARAMS(NSGigE) @@ -2787,7 +3101,11 @@ CREATE_SIM_OBJECT(NSGigE) NSGigE::Params *params = new NSGigE::Params; params->name = getInstanceName(); + + params->clock = clock; + params->mmu = mmu; + params->pmem = physmem; params->configSpace = configspace; params->configData = configdata; params->plat = platform; @@ -2795,27 +3113,31 @@ CREATE_SIM_OBJECT(NSGigE) params->deviceNum = pci_dev; params->functionNum = pci_func; - params->clock = clock; - params->intr_delay = intr_delay; - params->pmem = physmem; - params->tx_delay = tx_delay; - params->rx_delay = rx_delay; params->hier = hier; - params->header_bus = io_bus; + params->pio_bus = pio_bus; + params->header_bus = dma_bus; params->payload_bus = payload_bus; - params->pio_latency = pio_latency; params->dma_desc_free = dma_desc_free; params->dma_data_free = dma_data_free; params->dma_read_delay = dma_read_delay; params->dma_write_delay = dma_write_delay; params->dma_read_factor = dma_read_factor; params->dma_write_factor = dma_write_factor; + params->dma_no_allocate = dma_no_allocate; + params->pio_latency = pio_latency; + params->pio_delay_write = pio_delay_write; + params->intr_delay = intr_delay; + + params->rx_delay = rx_delay; + params->tx_delay = tx_delay; + params->rx_fifo_size = rx_fifo_size; + params->tx_fifo_size = tx_fifo_size; + params->rx_filter = rx_filter; params->eaddr = hardware_address; - params->tx_fifo_size = tx_fifo_size; - params->rx_fifo_size = rx_fifo_size; - params->m5reg = m5reg; - params->dma_no_allocate = dma_no_allocate; + params->rx_thread = rx_thread; + params->tx_thread = tx_thread; + return new NSGigE(params); }