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

📄 ns_gige.cc

📁 M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作为模拟平台
💻 CC
📖 第 1 页 / 共 5 页
字号:
    assert(rxDmaState == dmaReading);    rxDmaState = dmaIdle;    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",            rxDmaAddr, rxDmaLen);    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);    // If the transmit state machine has a pending DMA, let it go first    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)        txKick();    rxKick();}boolNSGigE::doRxDmaWrite(){    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);    rxDmaState = dmaWriting;    if (dmaPending() || getState() != Running)        rxDmaState = dmaWriteWaiting;    else        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);    return true;}voidNSGigE::rxDmaWriteDone(){    assert(rxDmaState == dmaWriting);    rxDmaState = dmaIdle;    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",            rxDmaAddr, rxDmaLen);    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);    // If the transmit state machine has a pending DMA, let it go first    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)        txKick();    rxKick();}voidNSGigE::rxKick(){    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) {        if (rxKickTick > curTick) {            DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",                    rxKickTick);            goto exit;        }        // Go to the next state machine clock tick.        rxKickTick = curTick + ticks(1);    }    switch(rxDmaState) {      case dmaReadWaiting:        if (doRxDmaRead())            goto exit;        break;      case dmaWriteWaiting:        if (doRxDmaWrite())            goto exit;        break;      default:        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    // label "next".  however, if you have intermediate work, like DMA    // so that you can't go to the next state yet, you go to exit and    // exit the loop.  however, when the DMA is done it will trigger    // an event and come back to this loop.    switch (rxState) {      case rxIdle:        if (!rxEnable) {            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");            goto exit;        }        if (CRDD) {            rxState = rxDescRefr;            rxDmaAddr = regs.rxdp & 0x3fffffff;            rxDmaData =                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);            rxDmaFree = dmaDescFree;            descDmaReads++;            descDmaRdBytes += rxDmaLen;            if (doRxDmaRead())                goto exit;        } else {            rxState = rxDescRead;            rxDmaAddr = regs.rxdp & 0x3fffffff;            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);            rxDmaFree = dmaDescFree;            descDmaReads++;            descDmaRdBytes += rxDmaLen;            if (doRxDmaRead())                goto exit;        }        break;      case rxDescRefr:        if (rxDmaState != dmaIdle)            goto exit;        rxState = rxAdvance;        break;     case rxDescRead:        if (rxDmaState != dmaIdle)            goto exit;        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",                regs.rxdp & 0x3fffffff);        DPRINTF(EthernetDesc,                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",                link, bufptr, cmdsts, extsts);        if (cmdsts & CMDSTS_OWN) {            devIntrPost(ISR_RXIDLE);            rxState = rxIdle;            goto exit;        } else {            rxState = rxFifoBlock;            rxFragPtr = bufptr;            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;        }        break;      case rxFifoBlock:        if (!rxPacket) {            /**             * @todo in reality, we should be able to start processing             * the packet as it arrives, and not have to wait for the             * full packet ot be in the receive fifo.             */            if (rxFifo.empty())                goto exit;            DPRINTF(EthernetSM, "****processing receive of new packet****\n");            // If we don't have a packet, grab a new one from the fifo.            rxPacket = rxFifo.front();            rxPktBytes = rxPacket->length;            rxPacketBufPtr = rxPacket->data;#if TRACING_ON            if (DTRACE(Ethernet)) {                IpPtr ip(rxPacket);                if (ip) {                    DPRINTF(Ethernet, "ID is %d\n", ip->id());                    TcpPtr tcp(ip);                    if (tcp) {                        DPRINTF(Ethernet,                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",                                tcp->sport(), tcp->dport(), tcp->seq(),                                tcp->ack());                    }                }            }#endif            // sanity check - i think the driver behaves like this            assert(rxDescCnt >= rxPktBytes);            rxFifo.pop();        }        // dont' need the && rxDescCnt > 0 if driver sanity check        // above holds        if (rxPktBytes > 0) {            rxState = rxFragWrite;            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity            // check holds            rxXferLen = rxPktBytes;            rxDmaAddr = rxFragPtr & 0x3fffffff;            rxDmaData = rxPacketBufPtr;            rxDmaLen = rxXferLen;            rxDmaFree = dmaDataFree;            if (doRxDmaWrite())                goto exit;        } else {            rxState = rxDescWrite;            //if (rxPktBytes == 0) {  /* packet is done */            assert(rxPktBytes == 0);            DPRINTF(EthernetSM, "done with receiving packet\n");            cmdsts |= CMDSTS_OWN;            cmdsts &= ~CMDSTS_MORE;            cmdsts |= CMDSTS_OK;            cmdsts &= 0xffff0000;            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE#if 0            /*             * all the driver uses these are for its own stats keeping             * which we don't care about, aren't necessary for             * functionality and doing this would just slow us down.             * if they end up using this in a later version for             * functional purposes, just undef             */            if (rxFilterEnable) {                cmdsts &= ~CMDSTS_DEST_MASK;                const EthAddr &dst = rxFifoFront()->dst();                if (dst->unicast())                    cmdsts |= CMDSTS_DEST_SELF;                if (dst->multicast())                    cmdsts |= CMDSTS_DEST_MULTI;                if (dst->broadcast())                    cmdsts |= CMDSTS_DEST_MASK;            }#endif            IpPtr ip(rxPacket);            if (extstsEnable && ip) {                extsts |= EXTSTS_IPPKT;                rxIpChecksums++;                if (cksum(ip) != 0) {                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");                    extsts |= EXTSTS_IPERR;                }                TcpPtr tcp(ip);                UdpPtr udp(ip);                if (tcp) {                    extsts |= EXTSTS_TCPPKT;                    rxTcpChecksums++;                    if (cksum(tcp) != 0) {                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");                        extsts |= EXTSTS_TCPERR;                    }                } else if (udp) {                    extsts |= EXTSTS_UDPPKT;                    rxUdpChecksums++;                    if (cksum(udp) != 0) {                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");                        extsts |= EXTSTS_UDPERR;                    }                }            }            rxPacket = 0;            /*             * the driver seems to always receive into desc buffers             * of size 1514, so you never have a pkt that is split             * into multiple descriptors on the receive side, so             * i don't implement that case, hence the assert above.             */            DPRINTF(EthernetDesc,                    "rxDesc: addr=%08x writeback cmdsts extsts\n",                    regs.rxdp & 0x3fffffff);            DPRINTF(EthernetDesc,                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",                    link, bufptr, cmdsts, 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++;            descDmaWrBytes += rxDmaLen;            if (doRxDmaWrite())                goto exit;        }        break;      case rxFragWrite:        if (rxDmaState != dmaIdle)            goto exit;        rxPacketBufPtr += rxXferLen;        rxFragPtr += rxXferLen;        rxPktBytes -= rxXferLen;        rxState = rxFifoBlock;        break;      case rxDescWrite:        if (rxDmaState != dmaIdle)            goto exit;        assert(cmdsts & CMDSTS_OWN);        assert(rxPacket == 0);        devIntrPost(ISR_RXOK);        if (cmdsts & CMDSTS_INTR)            devIntrPost(ISR_RXDESC);        if (!rxEnable) {            DPRINTF(EthernetSM, "Halting the RX state machine\n");            rxState = rxIdle;            goto exit;        } else            rxState = rxAdvance;        break;      case rxAdvance:        if (link == 0) {            devIntrPost(ISR_RXIDLE);            rxState = rxIdle;            CRDD = true;            goto exit;        } else {            if (rxDmaState != dmaIdle)                goto exit;            rxState = rxDescRead;            regs.rxdp = link;            CRDD = false;            rxDmaAddr = regs.rxdp & 0x3fffffff;            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);            rxDmaFree = dmaDescFree;            if (doRxDmaRead())                goto exit;        }        break;      default:        panic("Invalid rxState!");    }    DPRINTF(EthernetSM, "entering next rxState=%s\n",            NsRxStateStrings[rxState]);    goto next;  exit:    /**     * @todo do we want to schedule a future kick?     */    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",            NsRxStateStrings[rxState]);    if (clock && !rxKickEvent.scheduled())        rxKickEvent.schedule(rxKickTick);}voidNSGigE::transmit(){    if (txFifo.empty()) {        DPRINTF(Ethernet, "nothing to transmit\n");        return;    }    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",            txFifo.size());    if (interface->sendPacket(txFifo.front())) {#if TRACING_ON        if (DTRACE(Ethernet)) {            IpPtr ip(txFifo.front());            if (ip) {                DPRINTF(Ethernet, "ID is %d\n", ip->id());                TcpPtr tcp(ip);                if (tcp) {                    DPRINTF(Ethernet,                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",                            tcp->sport(), tcp->dport(), tcp->seq(),                            tcp->ack());                }            }        }#endif        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);        txBytes += txFifo.front()->length;        txPackets++;        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",                txFifo.avail());        txFifo.pop();        /*         * normally do a writeback of the descriptor here, and ONLY         * after that is done, send this interrupt.  but since our         * stuff never actually fails, just do this interrupt here,         * otherwise the code has to stray from this nice format.         * besides, it's functionally the same.         */        devIntrPost(ISR_TXOK);    }   if (!txFifo.empty() && !txEvent.scheduled()) {       DPRINTF(Ethernet, "reschedule transmit\n");       txEvent.schedule(curTick + retryTime);   }}boolNSGigE::doTxDmaRead(){    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);    txDmaState = dmaReading;    if (dmaPending() || getState() != Running)        txDmaState = dmaReadWaiting;    else        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);    return true;}voidNSGigE::txDmaReadDone(){    assert(txDmaState == dmaReading);    txDmaState = dmaIdle;    DPRINTF(EthernetDMA, "tx dma read  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();}boolNSGigE::doTxDmaWrite(){    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);    txDmaState = dmaWriting;

⌨️ 快捷键说明

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