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

📄 etherdev.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 2 页
字号:
         */        outb(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);        rxing_page = inb(e8390_base + EN1_CURPAG);        outb(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);        /*          * Remove one frame from the ring.         * Boundary is always a page behind.         */        this_frame = inb(e8390_base + EN0_BOUNDARY) + 1;        if (this_frame >= NESM_RX_STOP_PG)            this_frame = NESM_RX_START_PG;                /*          * Read all the frames?         * Done for now...         */        if (this_frame == rxing_page)            break;        current_offset = this_frame << 8;                /*         * Get a pick on the ethernet packet header         * to read the size.         */        outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+ NE_CMD);        outb(sizeof(struct e8390_pkt_hdr), e8390_base + EN0_RCNTLO);        outb(0, e8390_base + EN0_RCNTHI);        outb(0, e8390_base + EN0_RSARLO);       /* On page boundary */        outb(this_frame, e8390_base + EN0_RSARHI);        outb(E8390_RREAD+E8390_START, e8390_base + NE_CMD);        memcpy_from_dataport(NE_BASE + NE_DATAPORT, (void *)&rx_frame_hdr, sizeof(struct e8390_pkt_hdr));        outb(ENISR_RDC, e8390_base + EN0_ISR);  /* Ack intr. */        pkt_len = rx_frame_hdr.count - sizeof(struct e8390_pkt_hdr);        pkt_stat = rx_frame_hdr.status;        if (pkt_len < 60  ||  pkt_len > 1518) {            printf("etherdev: bogus packet size: %d!\n",pkt_len);        }         else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {            int offset;            offset = current_offset + sizeof(rx_frame_hdr);                        outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+ NE_CMD);            outb(pkt_len & 0xff, e8390_base + EN0_RCNTLO);            outb(pkt_len >> 8, e8390_base + EN0_RCNTHI);            outb(offset & 0xff, e8390_base + EN0_RSARLO);            outb(offset >> 8, e8390_base + EN0_RSARHI);            outb(E8390_RREAD+E8390_START, e8390_base + NE_CMD);            rx_index++;            memcpy_from_dataport(NE_BASE + NE_DATAPORT, rxbuf[rx_index], pkt_len);            if (pkt_len & 0x01) {                rxbuf[rx_index][pkt_len - 1] = inb(NE_BASE + NE_DATAPORT);            }            outb(ENISR_RDC, e8390_base + EN0_ISR);  /* Ack intr. */                    next_frame = rx_frame_hdr.next;                            /*              * This _should_ never happen....             */            if (next_frame >= NESM_RX_STOP_PG) {                printf("etherdev: next frame inconsistency, %#2x\n", next_frame);                next_frame = NESM_RX_START_PG;            }                outb(next_frame-1, e8390_base+EN0_BOUNDARY);                        processPACKET((struct ether_header *)rxbuf[rx_index], pkt_len);            rx_index--;        }        else {            printf("etherdev: bogus packet: status=0x%02x nxpg=0x%02x size=%d\n", \                rx_frame_hdr.status, rx_frame_hdr.next, rx_frame_hdr.count);        }        rx_pkt_count++;            }    return rx_pkt_count;}/* polletherdev():    Called by pollethernet() to do the device-specific portion of the    ethernet polling.  This code is the first step in processing incoming    ethernet packets.  If a packet is available, the functino geteinbuf()    (get ethernet input buffer) is called to pass the packet to the higher    level processPACKET() function.    IMPORTANT NOTE:    This function MUST be re-entrant.  There is a possibility that the    processPACKET() function will ultimately call polletherdev() again.    This means that once the packet has been detected in the device, it     is important that this code do whatever is necessary to assure that    the same packet will not be seen as available to the nested caller.    In other words...    clear the packet from the device prior to calling processPACKET().*/intpolletherdev(){    register uchar  isr;    /*     * Get the status     */     isr = inb(NE_BASE + EN0_ISR);        if (isr & ENISR_OVER) {        printf("ISR: we have OVERRUN!!\n");        outb(ENISR_OVER , NE_BASE + EN0_ISR);    }    if (isr & ENISR_RX) {        /* Clear the ENISR_RX bit */        outb(ENISR_RX , NE_BASE + EN0_ISR);        return geteinbuf();    }    return 0;}/* getXmitBuffer():    Called by various points in the IP/UDP/ICMP code for a buffer that    will ultimately be the next output packet.*/uchar *getXmitBuffer(){    /*     * I am only using one buffer for the momment.     */    return(txbuf);}/* sendBuffer():*/intsendBuffer(int length){    static int busy = 0;    if (EtherVerbose &  SHOW_OUTGOING)        printPkt((struct ether_header *)txbuf,length,ETHER_OUTGOING);    if (busy) {        /*           * wait until sending the previous packet finishes         * and then ack the interrupt.         */         while ((inb(e8390_base+EN0_ISR) & (ENISR_TX | ENISR_TX_ERR)) == 0);        outb(ENISR_TX | ENISR_TX_ERR, e8390_base + EN0_ISR);        busy = 0;    }        /* Keep stats: */    if (EtherXFRAMECnt) {        /*        if (prevtbptr->status & BD_DEF)            EtherDEFCnt++;        if (prevtbptr->status & BD_LC)            EtherLCCnt++;        if (prevtbptr->status & BD_RL)            EtherRLCnt++;        */    }    EtherXFRAMECnt++;    /*     * Now the normal output.     * First we round up for word writes.     */    if (length & 0x01)        length++;    /*     * Be sure that we are already in page 0.     */    outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); /* 0x22 */                /*     * Do the remote transfer     */    outb(length & 0xff, e8390_base + EN0_RCNTLO);    outb(length >> 8, e8390_base + EN0_RCNTHI);    outb(0x0, e8390_base + EN0_RSARLO);    outb(NESM_TX_START_PG , e8390_base + EN0_RSARHI);    outb(E8390_RWRITE+E8390_START, e8390_base + NE_CMD);    /*     * Transfer the whole buffer to the data port     * in chunks of 16bits.     */    memcpy_to_dataport(NE_BASE + NE_DATAPORT, txbuf, length);    /*      * Then write the length to TCNT, and update TPSR     */    outb(length & 0xff, e8390_base + EN0_TCNTLO);    outb(length >> 8, e8390_base + EN0_TCNTHI);    outb(NESM_TX_START_PG, e8390_base + EN0_TPSR);    /*     * Issue transmit command.     */     outb(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base + NE_CMD);    busy = 1;    return(0);}/* Disable/Enable either broadcast or promiscuous mode... */voidenableBroadcastReception(){    uchar rcr;    outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */    rcr = inb(e8390_base+EN0_RXCR);    rcr |= E8390_RCR_AB;    outb(rcr, e8390_base+EN0_RXCR);    outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); /* 0x22 */}voiddisableBroadcastReception(){    uchar rcr;    outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */    rcr = inb(e8390_base+EN0_RXCR);    rcr &= ~E8390_RCR_AB;    outb(rcr, e8390_base+EN0_RXCR);    outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); /* 0x22 */}voidenablePromiscuousReception(){    uchar rcr;    outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */    rcr = inb(e8390_base+EN0_RXCR);    rcr |= E8390_RCR_PRO;    outb(rcr, e8390_base+EN0_RXCR);    outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); /* 0x22 */}voiddisablePromiscuousReception(){    uchar rcr;    outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */    rcr = inb(e8390_base+EN0_RXCR);    rcr &= ~E8390_RCR_PRO;    outb(rcr, e8390_base+EN0_RXCR);    outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); /* 0x22 */}voidenresetmmu(){}/* extGetIpAdd() & extGetEtherAdd():    These two functions are stubs that allow a user to insert an external    interface into the standard mechanism that MicroMonitor uses to     retrieve its IP and MAC address.  If not used, they simply return NULL.    If used, they should return an ascii string that represents either the    IP or MAC address to be assigned to this target.*/char *extGetIpAdd(){    return((char *)0);}char *extGetEtherAdd(){    return((char *)0);}#endif

⌨️ 快捷键说明

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