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

📄 ns_gige.cc

📁 M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作为模拟平台
💻 CC
📖 第 1 页 / 共 5 页
字号:
            if (reg & TX_CFG_BRST_DIS) ;#endif#if 0            /* we handle our own DMA, ignore the kernel's exhortations */            if (reg & TX_CFG_MXDMA) ;#endif            // also, we currently don't care about fill/drain            // thresholds though this may change in the future with            // more realistic networks or a driver which changes it            // according to feedback            break;          case GPIOR:            // 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;          case RXDP:            regs.rxdp = reg;            CRDD = false;            break;          case RXDP_HI:            regs.rxdp_hi = reg;            break;          case RX_CFG:            regs.rxcfg = reg;#if 0            if (reg & RX_CFG_AEP) ;            if (reg & RX_CFG_ARP) ;            if (reg & RX_CFG_STRIPCRC) ;            if (reg & RX_CFG_RX_RD) ;            if (reg & RX_CFG_ALP) ;            if (reg & RX_CFG_AIRL) ;            /* we handle our own DMA, ignore what kernel says about it */            if (reg & RX_CFG_MXDMA) ;            //also, we currently don't care about fill/drain thresholds            //though this may change in the future with more realistic            //networks or a driver which changes it according to feedback            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;#endif            break;          case PQCR:            /* there is no priority queueing used in the linux 2.6 driver */            regs.pqcr = reg;            break;          case WCSR:            /* not going to implement wake on LAN */            regs.wcsr = reg;            break;          case PCR:            /* not going to implement pause control */            regs.pcr = reg;            break;          case RFCR:            regs.rfcr = reg;            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;            acceptBroadcast = (reg & RFCR_AAB) ? true : false;            acceptMulticast = (reg & RFCR_AAM) ? true : false;            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_UHEN)                panic("Unicast hash filtering not used by drivers!\n");            if (reg & RFCR_ULM)                panic("RFCR_ULM not implemented!\n");            break;          case RFDR:            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:            regs.brar = reg;            break;          case BRDR:            panic("the driver never uses BRDR, something is wrong!\n");          case SRR:            panic("SRR is read only register!\n");          case MIBC:            panic("the driver never uses MIBC, something is wrong!\n");          case VRCR:            regs.vrcr = reg;            break;          case VTCR:            regs.vtcr = reg;            break;          case VDR:            panic("the driver never uses VDR, something is wrong!\n");          case CCSR:            /* not going to implement clockrun stuff */            regs.ccsr = reg;            break;          case TBICR:            regs.tbicr = reg;            if (reg & TBICR_MR_LOOPBACK)                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");            if (reg & TBICR_MR_AN_ENABLE) {                regs.tanlpar = regs.tanar;                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);            }#if 0            if (reg & TBICR_MR_RESTART_AN) ;#endif            break;          case TBISR:            panic("TBISR is read only register!\n");          case TANAR:            // 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            break;          case TANLPAR:            panic("this should only be written to by the fake phy!\n");          case TANER:            panic("TANER is read only register!\n");          case TESR:            regs.tesr = reg;            break;          default:            panic("invalid register access daddr=%#x", daddr);        }    } else {        panic("Invalid Request Size");    }    pkt->makeAtomicResponse();    return pioDelay;}voidNSGigE::devIntrPost(uint32_t interrupts){    if (interrupts & ISR_RESERVE)        panic("Cannot set a reserved interrupt");    if (interrupts & ISR_NOIMPL)        warn("interrupt not implemented %#x\n", interrupts);    interrupts &= ISR_IMPL;    regs.isr |= interrupts;    if (interrupts & regs.imr) {        if (interrupts & ISR_SWI) {            totalSwi++;        }        if (interrupts & ISR_RXIDLE) {            totalRxIdle++;        }        if (interrupts & ISR_RXOK) {            totalRxOk++;        }        if (interrupts & ISR_RXDESC) {            totalRxDesc++;        }        if (interrupts & ISR_TXOK) {            totalTxOk++;        }        if (interrupts & ISR_TXIDLE) {            totalTxIdle++;        }        if (interrupts & ISR_TXDESC) {            totalTxDesc++;        }        if (interrupts & ISR_RXORN) {            totalRxOrn++;        }    }    DPRINTF(EthernetIntr,            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",            interrupts, regs.isr, regs.imr);    if ((regs.isr & regs.imr)) {        Tick when = curTick;        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)            when += intrDelay;        cpuIntrPost(when);    }}/* writing this interrupt counting stats inside this means that this function   is now limited to being used to clear all interrupts upon the kernel   reading isr and servicing.  just telling you in case you were thinking   of expanding use.*/voidNSGigE::devIntrClear(uint32_t interrupts){    if (interrupts & ISR_RESERVE)        panic("Cannot clear a reserved interrupt");    if (regs.isr & regs.imr & ISR_SWI) {        postedSwi++;    }    if (regs.isr & regs.imr & ISR_RXIDLE) {        postedRxIdle++;    }    if (regs.isr & regs.imr & ISR_RXOK) {        postedRxOk++;    }    if (regs.isr & regs.imr & ISR_RXDESC) {            postedRxDesc++;    }    if (regs.isr & regs.imr & ISR_TXOK) {        postedTxOk++;    }    if (regs.isr & regs.imr & ISR_TXIDLE) {        postedTxIdle++;    }    if (regs.isr & regs.imr & ISR_TXDESC) {        postedTxDesc++;    }    if (regs.isr & regs.imr & ISR_RXORN) {        postedRxOrn++;    }    if (regs.isr & regs.imr & ISR_IMPL)        postedInterrupts++;    interrupts &= ~ISR_NOIMPL;    regs.isr &= ~interrupts;    DPRINTF(EthernetIntr,            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",            interrupts, regs.isr, regs.imr);    if (!(regs.isr & regs.imr))        cpuIntrClear();}voidNSGigE::devIntrChangeMask(){    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",            regs.isr, regs.imr, regs.isr & regs.imr);    if (regs.isr & regs.imr)        cpuIntrPost(curTick);    else        cpuIntrClear();}voidNSGigE::cpuIntrPost(Tick when){    // If the interrupt you want to post is later than an interrupt    // already scheduled, just let it post in the coming one and don't    // schedule another.    // HOWEVER, must be sure that the scheduled intrTick is in the    // future (this was formerly the source of a bug)    /**     * @todo this warning should be removed and the intrTick code should     * be fixed.     */    assert(when >= curTick);    assert(intrTick >= curTick || intrTick == 0);    if (when > intrTick && intrTick != 0) {        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",                intrTick);        return;    }    intrTick = when;    if (intrTick < curTick) {        debug_break();        intrTick = curTick;    }    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",            intrTick);    if (intrEvent)        intrEvent->squash();    intrEvent = new IntrEvent(this, intrTick, true);}voidNSGigE::cpuInterrupt(){    assert(intrTick == curTick);    // Whether or not there's a pending interrupt, we don't care about    // it anymore    intrEvent = 0;    intrTick = 0;    // Don't send an interrupt if there's already one    if (cpuPendingIntr) {        DPRINTF(EthernetIntr,                "would send an interrupt now, but there's already pending\n");    } else {        // Send interrupt        cpuPendingIntr = true;        DPRINTF(EthernetIntr, "posting interrupt\n");        intrPost();    }}voidNSGigE::cpuIntrClear(){    if (!cpuPendingIntr)        return;    if (intrEvent) {        intrEvent->squash();        intrEvent = 0;    }    intrTick = 0;    cpuPendingIntr = false;    DPRINTF(EthernetIntr, "clearing interrupt\n");    intrClear();}boolNSGigE::cpuIntrPending() const{ return cpuPendingIntr; }voidNSGigE::txReset(){    DPRINTF(Ethernet, "transmit reset\n");    CTDD = false;    txEnable = false;;    txFragPtr = 0;    assert(txDescCnt == 0);    txFifo.clear();    txState = txIdle;    assert(txDmaState == dmaIdle);}voidNSGigE::rxReset(){    DPRINTF(Ethernet, "receive reset\n");    CRDD = false;    assert(rxPktBytes == 0);    rxEnable = false;    rxFragPtr = 0;    assert(rxDescCnt == 0);    assert(rxDmaState == dmaIdle);    rxFifo.clear();    rxState = rxIdle;}voidNSGigE::regsReset(){    memset(&regs, 0, sizeof(regs));    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);    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    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103    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;    acceptMulticast = false;    acceptUnicast = false;    acceptPerfect = false;    acceptArp = false;}boolNSGigE::doRxDmaRead(){    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);    rxDmaState = dmaReading;    if (dmaPending() || getState() != Running)        rxDmaState = dmaReadWaiting;    else        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);    return true;}voidNSGigE::rxDmaReadDone(){

⌨️ 快捷键说明

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