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

📄 ne2000.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
       */
    //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);

    /* Take interface out of loopback.    */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), 0);

    /* 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;

    /* Set up DMA byte count.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), amount);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), amount >> 8);

    /* Set up source address in NIC mem.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR0), src);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR1), src >> 8);

    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD0 | NE2000_CR_PAGE_0 | NE2000_CR_STA);

    if (sc->isa16bit)
        insw((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), (unsigned short KS_FAR *) dst, amount / 2);
    else
        insb((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), dst, amount);
}

/*
 * Write a DCU to the destination NIC memory address using programmed I/O
 */
BOOLEAN ne2000_pio_write_pkt(PNE2000_SOFTC sc, PFCBYTE packet, int length, UINT16 dst)
{
int     maxwait; /* about 120us */
UINT8    savebyte[2];
BOOLEAN ret_val=TRUE;

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

    /* Reset remote DMA complete flag.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), NE2000_ISR_RDC);

    /* Set up DMA UINT8 count.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), length);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), length >> 8);

    /* Set up destination address in NIC mem.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR0), dst);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR1), dst >> 8);

    /* Set remote DMA write.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD1 | NE2000_CR_PAGE_0 | NE2000_CR_STA);

    /*
     * Transfer DCU to the NIC memory.
     * 16-bit cards require that data be transferred as words, and only
     * words, so that case requires some extra code to patch over
     * odd-length DCUs.
     */
    if (!sc->isa16bit) 
    {
        /* NE1000s are easy.   */
        outsb((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), packet, length);
    } 
    else 
    {
        /* NE2000s are a bit trickier.   */
        /* Output contiguous words.      */
        if (length > 1) 
        {
            outsw((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), (unsigned short KS_FAR *) packet, length >> 1);
            packet += length;
            length &= 1;
            if (length)
                packet--;
        }
        /* If odd number of bytes, output last UINT8 as a UINT16 with a 0 appended   */
        if (length == 1) 
        {
            savebyte[0] = *packet;
            savebyte[1] = 0;
            OUTWORD(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), *(UINT16 *)savebyte);
        }
    }
        
    /*
     * Wait for remote DMA complete.  This is necessary because on the
     * transmit side, data is handled internally by the NIC in bursts and
     * we can't start another remote DMA until this one completes.  Not
     * waiting causes really bad things to happen - like the NIC
     * irrecoverably jamming the ISA bus.
     */
#if (NEW_WAIT)
    maxwait = 300;      /* about 360usec */
#else
    maxwait = 1000;
#endif
    while (maxwait--)
    {
        if ( ((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RDC) == NE2000_ISR_RDC))
            break;
    }

    /* If pi is zero we are probing so don't reset   */
    if (!maxwait) 
    {
#if (NEW_WAIT)
		#define ks_msec_p_tick() (1000/NU_PLUS_Ticks_Per_Second)
		#define ks_sleep(x)	NU_Sleep(x)
		//DEBUG_ERROR("NE2000: sleep in xmit", NOVAR, 0, 0);
        /* the while() above was not enough.  Cannot afford to tie up the   */
        /* CPU longer than .5 msec, so sleep 20 msecs longer now.           */
        if (ks_msec_p_tick() >= 20)
            ks_sleep(1);
        else
            ks_sleep((UINT16)((20+ks_msec_p_tick()-1)/ks_msec_p_tick()));

        ++sc->stats.tx_delayed;
#endif
#if (NEW_WAIT)
        if ((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RDC) != NE2000_ISR_RDC)
#endif
        {
            //DEBUG_ERROR("remote transmit DMA failed to complete", NOVAR, 0, 0);
            sc->stats.errors_out++;
            sc->stats.tx_other_errors++;
            ne2000_reset(sc);
            ret_val = FALSE;
        }
    }
    
    
    return(ret_val);
}


/*********************************************************************/
/*                                                                   */
/*     					NUCLEUS NET FUNCTION                         */
/*                                                                   */
/*********************************************************************/

VOID MAC_TxHisr(DV_DEVICE_ENTRY* device)
{
    STATUS  previous_int_value;

    if (device == NU_NULL)
        return;
    
    /*  Lock out interrupts.  */
    previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);

    DEV_Recover_TX_Buffers (device);

    /* If there is another item on the list, transmit it. */
    if(device -> dev_transq.head)
    {
        /*  Re-enable interrupts. */
        NU_Control_Interrupts(previous_int_value);

        /* Transmit the next packet. */
        Rtl8019_Transmit(device, device->dev_transq.head);
    }

    /*  Re-enable interrupts. */
    NU_Control_Interrupts(previous_int_value);

}  /* MAC_TxHisr */

VOID Rtl8019_TxHisr()
{
    DV_DEVICE_ENTRY     *device;

    /* Get a pointer to the device. */
    device = DEV_Get_Dev_By_Name("RTL8019");
    
	MAC_TxHisr(device);
}

void Rtl8019_RxHisr ()
{
    /* Let the upper layer know a good packet is here. */
    NU_Set_Events(&Buffers_Available, (UNSIGNED)2, NU_OR);

    Hisr_Activated = 0;
}  /* END */

/************************************************************************
* FUNCTION                                                             
*                                                                      
*        Rtl8019_Initialize                                        
*                                                                      
* DESCRIPTION                                                          
*                                                                      
*        This function intializes the media layer of the protocol stack. 
*                                                                      
* AUTHOR                                                               
*                                                                      
*        MeterChen                                      
*                                                                      
* INPUTS                                                               
*                                                                      
*        DV_DEVICE_ENTRY       *dev_ptr      Pointer to the device 
*                                            structure for this device.
*                                                                      
* OUTPUTS                                                              
*                                                                      
*        STATUS                              Returns NU_SUCCESS if
*                                            initialization is successful,
*                                            else a value less than 0 is
*                                            returned.
*                                                                      
************************************************************************/

STATUS Rtl8019_Initialize(DV_DEVICE_ENTRY *dev_ptr)
{
STATUS  status;
VOID    *pointer;

    /* Fill in the device table */
    dev_ptr->dev_output     = NET_Ether_Send;   /* net.c */
    dev_ptr->dev_input      = NET_Ether_Input;  /* net.c */
    dev_ptr->dev_start      = Rtl8019_Transmit;
    dev_ptr->dev_receive    = Rtl8019_Receive;
    dev_ptr->dev_addrlen    = HW_Address_Size;
    dev_ptr->dev_hdrlen     = ETH_HeaderSize;
    dev_ptr->dev_mtu        = MTU_Size;         /* 1500 */
    dev_ptr->dev_ioctl      = Rtl8019_Ioctl;

    /* Get the hardware address from the device structure and */
    /* set it into the CAM filter.                            */
    //Rtl8019_SetMacAddr(dev_ptr);

    /* Initialize the MAC. */
    if (ne2000_open() != TRUE)
    {
    	return (-1);
    }
	
	/* Allow reception of broadcast and multicast packets. */
    dev_ptr->dev_flags |= (DV_BROADCAST | DV_MULTICAST);

	/* CAM filter setting is done in api_MacHWInit routine */
	memcpy(dev_ptr->dev_mac_addr, (UINT8*)dev_ptr->dev_driver_options, 6);

    /* Init the basic interface information. */
    SNMP_ifDescr(device->dev_unit + 1, "Realtek 8019as Ethernet: Software revision 1.2");
    SNMP_ifType(device->dev_unit + 1, 6);
    SNMP_ifMtu(device->dev_unit + 1, device->dev_mtu);

    /* Create the HISR for receiving packets from the MAC */
    status = NU_Allocate_Memory (&System_Memory,
                                 &pointer,
                                 2000,
                                 NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        return (-2);
    }

    status = NU_Create_HISR (&Ether_Rcv, "ETH_RX_HISR",
                             Rtl8019_RxHisr,
                             0, pointer, 2000);
   
    if (status != NU_SUCCESS)
    {
        return (-3);
    }

    /* Create the HISR for transmitting packets */
    status = NU_Allocate_Memory (&System_Memory,
                                 &pointer,
                                 2000,
                                 NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        return (-4);
    }

    status = NU_Create_HISR (&Ether_Xmit, "ETH_TX_HISR",
                              Rtl8019_TxHisr,
                              0, pointer, 2000);
    if (status != NU_SUCCESS)
    {
        return (-5);
    }

    /* Set the current status to operational. */
    SNMP_ifAdminStatus(device->dev_unit + 1, 1);
    SNMP_ifOperStatus(device->dev_unit + 1, 1);

    return (NU_SUCCESS);
} 

/************************************************************************
* FUNCTION                                                             
*                                                                      
*        Rtl8019_Transmit                                        
*                                                                      
* DESCRIPTION                                                          
*                                                                      
*        Accepts a packet from the upper layers and generates an
*        ethernet frame for transmission.
*                                                                      
* AUTHOR                                                               
*                                                                      
*        Meterchen                                      
*                                                                      
* INPUTS                                                               
*                                                                      
*        DV_DEVICE_ENTRY    *dev        Pointer to the device structure.
*        NET_BUFFER         *buf_ptr    Pointer to the data we want to
*                                         send.

⌨️ 快捷键说明

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