⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns_gige.cc

📁 M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作为模拟平台
💻 CC
📖 第 1 页 / 共 5 页
字号:
    if (dmaPending() || getState() != Running)        txDmaState = dmaWriteWaiting;    else        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);    return true;}voidNSGigE::txDmaWriteDone(){    assert(txDmaState == dmaWriting);    txDmaState = dmaIdle;    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",            txDmaAddr, txDmaLen);    DDUMP(EthernetDMA, txDmaData, txDmaLen);    // If the receive state machine  has a pending DMA, let it go first    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)        rxKick();    txKick();}voidNSGigE::txKick(){    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) {        if (txKickTick > curTick) {            DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",                    txKickTick);            goto exit;        }        // Go to the next state machine clock tick.        txKickTick = curTick + ticks(1);    }    switch(txDmaState) {      case dmaReadWaiting:        if (doTxDmaRead())            goto exit;        break;      case dmaWriteWaiting:        if (doTxDmaWrite())            goto exit;        break;      default:        break;    }    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;    switch (txState) {      case txIdle:        if (!txEnable) {            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");            goto exit;        }        if (CTDD) {            txState = txDescRefr;            txDmaAddr = regs.txdp & 0x3fffffff;            txDmaData =                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);            txDmaFree = dmaDescFree;            descDmaReads++;            descDmaRdBytes += txDmaLen;            if (doTxDmaRead())                goto exit;        } else {            txState = txDescRead;            txDmaAddr = regs.txdp & 0x3fffffff;            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);            txDmaFree = dmaDescFree;            descDmaReads++;            descDmaRdBytes += txDmaLen;            if (doTxDmaRead())                goto exit;        }        break;      case txDescRefr:        if (txDmaState != dmaIdle)            goto exit;        txState = txAdvance;        break;      case txDescRead:        if (txDmaState != dmaIdle)            goto exit;        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",                regs.txdp & 0x3fffffff);        DPRINTF(EthernetDesc,                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",                link, bufptr, cmdsts, extsts);        if (cmdsts & CMDSTS_OWN) {            txState = txFifoBlock;            txFragPtr = bufptr;            txDescCnt = cmdsts & CMDSTS_LEN_MASK;        } else {            devIntrPost(ISR_TXIDLE);            txState = txIdle;            goto exit;        }        break;      case txFifoBlock:        if (!txPacket) {            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");            txPacket = new EthPacketData(16384);            txPacketBufPtr = txPacket->data;        }        if (txDescCnt == 0) {            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");            if (cmdsts & CMDSTS_MORE) {                DPRINTF(EthernetSM, "there are more descriptors to come\n");                txState = txDescWrite;                cmdsts &= ~CMDSTS_OWN;                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())                    goto exit;            } else { /* this packet is totally done */                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");                /* deal with the the packet that just finished */                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {                    IpPtr ip(txPacket);                    if (extsts & EXTSTS_UDPPKT) {                        UdpPtr udp(ip);                        udp->sum(0);                        udp->sum(cksum(udp));                        txUdpChecksums++;                    } else if (extsts & EXTSTS_TCPPKT) {                        TcpPtr tcp(ip);                        tcp->sum(0);                        tcp->sum(cksum(tcp));                        txTcpChecksums++;                    }                    if (extsts & EXTSTS_IPPKT) {                        ip->sum(0);                        ip->sum(cksum(ip));                        txIpChecksums++;                    }                }                txPacket->length = txPacketBufPtr - txPacket->data;                // this is just because the receive can't handle a                // packet bigger want to make sure                if (txPacket->length > 1514)                    panic("transmit packet too large, %s > 1514\n",                          txPacket->length);#ifndef NDEBUG                bool success =#endif                    txFifo.push(txPacket);                assert(success);                /*                 * this following section is not tqo spec, but                 * functionally shouldn't be any different.  normally,                 * the chip will wait til the transmit has occurred                 * before writing back the descriptor because it has                 * to wait to see that it was successfully transmitted                 * to decide whether to set CMDSTS_OK or not.                 * however, in the simulator since it is always                 * successfully transmitted, and writing it exactly to                 * spec would complicate the code, we just do it here                 */                cmdsts &= ~CMDSTS_OWN;                cmdsts |= CMDSTS_OK;                DPRINTF(EthernetDesc,                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",                        cmdsts, 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;                transmit();                txPacket = 0;                if (!txEnable) {                    DPRINTF(EthernetSM, "halting TX state machine\n");                    txState = txIdle;                    goto exit;                } else                    txState = txAdvance;                if (doTxDmaWrite())                    goto exit;            }        } else {            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");            if (!txFifo.full()) {                txState = txFragRead;                /*                 * The number of bytes transferred is either whatever                 * is left in the descriptor (txDescCnt), or if there                 * is not enough room in the fifo, just whatever room                 * is left in the fifo                 */                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());                txDmaAddr = txFragPtr & 0x3fffffff;                txDmaData = txPacketBufPtr;                txDmaLen = txXferLen;                txDmaFree = dmaDataFree;                if (doTxDmaRead())                    goto exit;            } else {                txState = txFifoBlock;                transmit();                goto exit;            }        }        break;      case txFragRead:        if (txDmaState != dmaIdle)            goto exit;        txPacketBufPtr += txXferLen;        txFragPtr += txXferLen;        txDescCnt -= txXferLen;        txFifo.reserve(txXferLen);        txState = txFifoBlock;        break;      case txDescWrite:        if (txDmaState != dmaIdle)            goto exit;        if (cmdsts & CMDSTS_INTR)            devIntrPost(ISR_TXDESC);        if (!txEnable) {            DPRINTF(EthernetSM, "halting TX state machine\n");            txState = txIdle;            goto exit;        } else            txState = txAdvance;        break;      case txAdvance:        if (link == 0) {            devIntrPost(ISR_TXIDLE);            txState = txIdle;            goto exit;        } else {            if (txDmaState != dmaIdle)                goto exit;            txState = txDescRead;            regs.txdp = link;            CTDD = false;            txDmaAddr = link & 0x3fffffff;            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);            txDmaFree = dmaDescFree;            if (doTxDmaRead())                goto exit;        }        break;      default:        panic("invalid state");    }    DPRINTF(EthernetSM, "entering next txState=%s\n",            NsTxStateStrings[txState]);    goto next;  exit:    /**     * @todo do we want to schedule a future kick?     */    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",            NsTxStateStrings[txState]);    if (clock && !txKickEvent.scheduled())        txKickEvent.schedule(txKickTick);}/** * Advance the EEPROM state machine * Called on rising edge of EEPROM clock bit in MEAR */voidNSGigE::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");    }}voidNSGigE::transferDone(){    if (txFifo.empty()) {        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");        return;    }    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");    txEvent.reschedule(curTick + ticks(1), true);}boolNSGigE::rxFilter(const EthPacketPtr &packet){    EthPtr eth = packet;    bool drop = true;    string type;    const EthAddr &dst = eth->dst();    if (dst.unicast()) {        // If we're accepting all unicast addresses        if (acce

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -