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

📄 ne2000.c

📁 最近在國外網站抓到的作業系統 以Arm為基礎去開發的
💻 C
📖 第 1 页 / 共 5 页
字号:
            }
            
            /* signal IP layer or driver that send is done   */
            //ks_invoke_output(/*pi*/);
            NU_Activate_HISR(&Ether_Xmit);
        }       /* pkt xmit or xmit error */

        /* ******                         */
        /* Handle receiver interrupts.    */
        if (isr & (NE2000_ISR_PRX | NE2000_ISR_RXE | NE2000_ISR_OVW)) 
        {
            /*
            * Overwrite warning.  In order to make sure that a
            * lockup of the local DMA hasn't occurred, we reset
            * and re-init the NIC.  The NSC manual suggests only a
            * partial reset/re-init is necessary - but some chips
            * seem to want more.  The DMA lockup has been seen
            * only with early rev chips - Methinks this bug was
            * fixed in later revs.  -DG
            */
            if (isr & NE2000_ISR_OVW) 
            {
                sc->stats.rx_overwrite_errors++;
                sc->stats.rx_other_errors++;
                sc->stats.errors_in++;

                /* Recover from ring buffer overflow.                    */
                /* disable sends and receives while recovery in progress */
                sc->do_recovery = NU_Retrieve_Clock();//ks_get_ticks();
        
                /* disable all interrupts   */
                OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), 0);

                /* save whether xmit is in progress   */
                sc->tpx = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR)) & NE2000_CR_TXP;

                /* STOP command to NIC; also set to page 0   */
                OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_STP | NE2000_CR_PAGE_0);
                /* Timer task will do the rest   */
            } 
            else 
            {
                /* Process Receiver Error.  One or more of:    */
                /*    CRC error,                               */
                /*    frame alignment error                    */
                /*    FIFO overrun, or                         */
                /*    missed packet.                           */
                /*                                             */
                if (isr & NE2000_ISR_RXE) 
                {
                    sc->stats.errors_in++;
                    sc->stats.rx_other_errors++;
                }

                /* Go get the packet(s).                        */
                /* - Doing this on an error is dubious          */
                /*   because there shouldn't be any data to get */
                /*   (we've configured the interface to not     */
                /*   accept packets with errors).               */
                /*                                              */
                /* process the receiver interrupt               */
                if (!sc->do_recovery)
                {
                    ne2000_read_ring_pkt(sc, TRUE);
                }
            }
        }           /* end receive interrupts */

        /*
         * Return NIC CR to standard state: page 0, remote DMA
         * complete, start (toggling the TXP bit off, even if was just
         * set in the transmit routine, is *okay* - it is 'edge'
         * triggered from low to high).
         */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);

        /*
         * If the Network Talley Counters overflow, read them to reset
         * them.  It appears that old 8390's won't clear the ISR flag
         * otherwise - resulting in an infinite loop.
         */
        if (isr & NE2000_ISR_CNT) 
        {
            (void) INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CNTR0));
            (void) INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CNTR1));
            (void) INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CNTR2));
        }

        /* get isr for next loop   */
        isr = INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR));
    }       /* end of while(isr) */
}

/* ********************************************************************   */
/*
 * Retreive packet from shared memory and send to the next level up via
 * the input list. 
 */
 
UINT8    TEMP_BUF_R[2000];

void ne2000_get_packet(PNE2000_SOFTC sc, UINT16 nic_buf, int len, BOOLEAN rint)
{
PFBYTE msgdata;
int tmp_amount;
DV_DEVICE_ENTRY   *device;
int blen = len;

	msgdata = TEMP_BUF_R;		

    /* Allocate a packet to write the ethernet packet in.   */
    //msg = os_alloc_packet_input(len, DRIVER_ALLOC);
    //if (!msg)    
    //{
        //DEBUG_ERROR("ne2000_get_packet() - out of DCUs", NOVAR, 0, 0);
        //if (rint)
        //    sc->stats.packets_lost++;
        //return;
    //}

    /* write ethernet header to packet   */
    //msgdata = DCUTODATA(msg);
    ne2000_pio_readmem(sc, nic_buf, msgdata, sizeof(struct _ether));
    nic_buf = (UINT16)(nic_buf + sizeof(struct _ether));
    msgdata += sizeof(struct _ether);
    //DCUTOPACKET(msg)->length = len; 

    /* Pull packet off interface and put into packet.   */
    len -= sizeof(struct _ether);

    /* Handle wrap here   */
    if (nic_buf + len > sc->mem_end) 
    {
        tmp_amount = sc->mem_end - nic_buf;
        /* Copy amount up to end of NIC memory.   */
        ne2000_pio_readmem(sc, nic_buf, msgdata, tmp_amount);
        len -= tmp_amount;
        nic_buf = sc->mem_ring;
        msgdata += tmp_amount;
    }
    ne2000_pio_readmem(sc, nic_buf, msgdata, len);

    if (rint)
    {
        /* Pull packet off interface and put into packet.   */
        sc->stats.packets_in++;
        sc->stats.bytes_in += len;  
		
		et_data_ptr =  (UINT32)TEMP_BUF_R; 
        et_data_len = blen;

#if RTL8019_LOOPBACK_TEST
	device = DEV_Get_Dev_By_Name("loopback");
#else
    	device = DEV_Get_Dev_By_Name("RTL8019");
#endif	
		
        device->dev_receive(device);
    }
    //else
    //    os_free_packet(msg);
}

/* ********************************************************************   */
/* Ethernet interface receiver interrupt.                                 */
/* ********************************************************************   */

void ne2000_read_ring_pkt(PNE2000_SOFTC sc, BOOLEAN rint)
{
UINT16 boundary;
int  len;
struct ne2000_ring packet_hdr; 
UINT16 nic_packet_ptr;

    /* Set NIC to page 1 registers to get 'current' pointer.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_1 | NE2000_CR_STA);

    /*
     * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
     * it points to where new data has been buffered.  The 'CURR' (current)
     * register points to the logical end of the ring-buffer - i.e. it
     * points to where additional new data will be added.  We loop here
     * until the logical beginning equals the logical end (or in other
     * words, until the ring-buffer is empty).
     */
    while (sc->next_packet != INBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_CURR))) 
    {
        /* Get pointer to this buffer's header structure.   */
        nic_packet_ptr = (UINT16)(sc->mem_ring + 
                                (sc->next_packet - sc->rec_page_start) * 
                                NE2000_PAGE_SIZE);

        /*
         * The UINT8 count includes a 4 UINT8 header that was added by
         * the NIC.
         */
        ne2000_pio_readmem(sc, nic_packet_ptr, (PFBYTE) &packet_hdr, 
                           sizeof(packet_hdr));

        len = (int)packet_hdr.count;

        /* Go get packet from shared memory, put it in a DCU and send it to 
           input exchange. */
        /* Adjust the pointer to the data to point past the header and
           Subtract the size of the CRC from the length */
        if (len <= ETHER_MAX_LEN)
        {
            ne2000_get_packet(sc, 
                    (UINT16)(nic_packet_ptr + sizeof(struct ne2000_ring)),
                    len - CRC_LEN, rint);
        } 

        /* Update next packet pointer.   */
        sc->next_packet = packet_hdr.next_packet;

        /*
         * Update NIC boundary pointer - being careful to keep it one
         * buffer behind (as recommended by NS databook).
         */
        boundary = (UINT16) (sc->next_packet - 1);
        if (boundary < sc->rec_page_start)
            boundary = (UINT16) (sc->rec_page_stop - 1);

        /* Set NIC to page 0 registers to update boundary register.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P1_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_BNRY), boundary);

        /*
         * Set NIC to page 1 registers before looping to top (prepare
         * to get 'CURR' current pointer).
         */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_1 | NE2000_CR_STA);
    }
}

/* ********************************************************************   */
/* RING BUFFER OVERFLOW RECOVERY                                          */
/* ********************************************************************   */

/* perform recovery for ring buffer overflow as suggested by             */
/* National Semiconductor DP8390D/NS32490D NIC Network Interface         */
/* Controller (September 1992) Document                                  */
/* NOTE: the rest of the recovery definatly cannot be done during        */
/* the interrupt due to the delay within the recovery code, therefore,   */
/* it is broken off in this routine just in case recovery ever attempted */
/* at the interrupt level                                                */
void ne2000_ring_overflow_recovery2(void)       /*__fn__*/
{
int resend;
PNE2000_SOFTC sc;
int       softc_off;

    //for (softc_off=0; softc_off<CFG_NUM_NE2000; softc_off++)
    {
        sc = (PNE2000_SOFTC) &ne2000softc[softc_off];

        //if (sc->do_recovery)
        //    break;
    }

    /* we have to wait at least 1.6 miliseconds to do ring overflow
       here we assume that 2 ticks is at least 1.6 milliseconds to
       save space on calculating time elapsed 
       */
    //if (!sc->do_recovery || ( (ks_get_ticks() - sc->do_recovery) < 2))
    //    return;

#if (DEBUG_RING)
        DEBUG_ERROR("ring buffer recovery 2 start", NOVAR, 0, 0);
#endif
    
    
#if (DEBUG_RING)
    DEBUG_ERROR("ring buffer recovery 2 start", NOVAR, 0, 0);
#endif

    /* clear the remote UINT8 count registers   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), 0);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), 0);

    /* set resend variable   */
    if (!sc->tpx)
        resend = 0;
    else
    {
        if ( INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & (NE2000_ISR_PTX | NE2000_ISR_TXE) )
            resend = 0;     
        else
            resend = 1;
    }

    /* set to mode 1 loopback   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), NE2000_TCR_LB0);

    /* issue start command   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_STA);

    /* remove one or more packets from the receive buffer   */
    //ne2000_read_ring_pkt(sc->iface, sc, FALSE);

    /* set to page 0 in case ne2000_read_ring_pkt changed page   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_PAGE_0);

    /* reset the overwrite warning   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), NE2000_ISR_OVW);

#if RTL8019_LOOPBACK_TEST
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), LOOPBACK_TEST_MODE);
#else
    /* Take interface out of loopback.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), 0);
#endif

    /* if resend is 1, reissue xmit command   */
    if (resend)
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_TXP | NE2000_CR_STA);

    /* enable interrupts again   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), NORMAL_NE2000_INTS);

#if (DEBUG_RING)
    recovery_count++;
    DEBUG_ERROR("ring buffer recovery done", EBS_INT1, recovery_count, 0);
#endif

    /* do not clear flag until recovery done; xmit and receive are disable   */
    /* via this flag until the recovery is done                              */
    sc->do_recovery = 0;
}


/* ********************************************************************   */
/* Supporting routines.                                                   */
/* ********************************************************************   */

/*
 * Given a NIC memory source address and a host memory destination address,
 * copy 'amount' from NIC to host using Programmed I/O.  The 'amount' is
 * rounded up to a UINT16 - okay as long as mbufs are UINT16 sized.
 * This routine is currently Novell-specific.
 */
void ne2000_pio_readmem(PNE2000_SOFTC sc, UINT16 src, PFBYTE dst, int amount)
{

    /* Select page 0 registers.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);

    /* Round up to a word.   */
    if (amount & 1)
        ++amount;

⌨️ 快捷键说明

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