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

📄 ne2000.c

📁 基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7的BSP,操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*********************************************************************** 
 * $Workfile:   net2000.c  $ 
 * $Revision: 1.1.1.1 $ 
 * $Author: meterchen $ 
 * $Date: 2003/11/10 17:00:55 $ 
 * 
 * Project:     Shenzhen-Nucleus-Net
 * 
 * Description: 
 *     ne2000 driver   
 *
 * Revision History: 
 * 
 *********************************************************************** 
 * 
 *  Copyright (c) 2003 CHENMENG
 * 
 *  All rights reserved 
 * 
 **********************************************************************/

#define CFG_NE2000_IOBASE 0x06000000
#define CFG_NE2000_IRQ    0x18

#include "nucleus.h"
#include "44b.h"
#include "externs.h"
#include "ethernet.h"

#include "ostype.h"
#include "ne2000.h"

#define IP_ALEN  4              /* number of bytes in an IP address */
#define ETH_ALEN 6              /* number of bytes in an ETHERNET address */
#define TOK_ALEN 6              /* number of bytes in a Token Ring address */
#define LL_ALEN  6              /* number of bytes in a Link Layer address */
                                /* (token ring or ethernet)   */
#define ETHERSIZE  1514   /* maximum number of bytes in ETHERNET packet */
                          /* (used by ethernet drivers)   */
                          
struct _ether 
{
    UINT8 eth_dest[ETH_ALEN];    /* where the packet is going  */
    UINT8 eth_source[ETH_ALEN];  /* who it came from           */
    UINT16 eth_type;              /* Ethernet packet type for 802.3 */
                                /* or length of (IP layer + LLC,SNAP) if 802.2   */
};

#define HW_Address_Size     6     /* Length of Ethernet Addresses           */
#define TYPE_LENGTH         2     /* Length of Header Type/Length Field     */  
#define MTU_Size            1500  /* MAX Transmission Unit, excluding media */
                                  /*  header length for ethernet            */

/* Ethernet header size:  dest addr, source addr, Type/Length               */
#define ETH_HeaderSize      ((HW_Address_Size * 2) + TYPE_LENGTH)


NU_HISR  Ether_Xmit;
NU_HISR  Ether_Rcv;

volatile UINT32 et_data_ptr;
volatile UINT32 et_data_len;

int      Hisr_Activated = 0;

STATUS Rtl8019_Transmit(DV_DEVICE_ENTRY *dev, NET_BUFFER *buf_ptr);
STATUS Rtl8019_Receive(DV_DEVICE_ENTRY *device);
STATUS  Rtl8019_Ioctl(DV_DEVICE_ENTRY *dev, INT option, DV_REQ *d_req);


/* ********************************************************************   */
/* ********************************************************************   */
/* I/O ROUTINES                                                           */
/* ********************************************************************   */
/* ********************************************************************   */

/* tbd: rep move simulated in 'C'   */
void insw(IOADDRESS ioaddr, PFWORD dst, int n)
{
    while (n--)
        *dst++ = (word)INWORD(ioaddr);
}

void insb(IOADDRESS ioaddr, PFBYTE dst, int n)
{
    while (n--)
        *dst++ = INBYTE(ioaddr);
}

void outsw(IOADDRESS ioaddr, PFWORD src, int n)
{
    while (n--)
        OUTWORD(ioaddr, *src++);
}

void outsb(IOADDRESS ioaddr, PFCBYTE src, int n)
{
    while (n--)
        OUTBYTE(ioaddr, *src++);
}


#define NEW_WAIT 1

#define DISPLAY_ERROR   0   /* display error during interrupt */
#define DEBUG_RING      0
#define DEBUG_NIC       1

#if (DEBUG_RING)
int recovery_count = 0;     /* count of ring buffer overflows */
#endif

/* ********************************************************************   */
#define ETHER_MIN_LEN   64                  /* includes header */
#define ETHER_MAX_LEN   (ETHERSIZE+4)       /* includes header */
#define CRC_LEN         4

#define EROUND  ((sizeof(struct _ether) + 3) & ~3)
#define EOFF    (EROUND - sizeof(struct _ether))

NE2000_SOFTC KS_FAR ne2000softc[1];
extern KS_CONSTANT UINT8 KS_FAR test_pattern[32];

/* ********************************************************************   */
void ne2000_getmcaf(PFBYTE mclist, int bytesmclist, PFBYTE af);
void ne2000_reset(/*PIFACE pi, */PNE2000_SOFTC sc);
void ne2000_interrupt(int minor_no);

int  ne2000_probe_Novell(/*PIFACE pi, */PNE2000_SOFTC sc);
void ne2000_stop(PNE2000_SOFTC sc);

void    ne2000_init(/*PIFACE pi, */PNE2000_SOFTC sc);
void    ne2000_pio_readmem(PNE2000_SOFTC sc, UINT16 src, PFBYTE dst, int amount);
BOOLEAN ne2000_pio_write_pkt(/*PIFACE pi, */PNE2000_SOFTC sc, PFCBYTE packet, int length, UINT16 dst);
UINT16    ne2000_ring_copy(PNE2000_SOFTC sc, UINT16 src, PFBYTE dst, UINT16 amount);
void    ne2000_ring_overflow_recovery2(void);
void    ne2000_get_packet(/*PIFACE pi, */PNE2000_SOFTC sc, UINT16 nic_buf, int len, BOOLEAN rint);
void    ne2000_read_ring_pkt(/*PIFACE pi, */PNE2000_SOFTC sc, BOOLEAN rint);

/* ********************************************************************   */
/* MEMORY MANAGMENT                                                       */
/* ********************************************************************   */ 
#define iface_to_softc() (PNE2000_SOFTC) &ne2000softc[0]
#define off_to_softc()   (PNE2000_SOFTC) &ne2000softc[0]

/*
 * Probe and vendor-specific initialization routine for NE1000/2000 boards.
 */
int ne2000_probe_Novell(PNE2000_SOFTC sc)
{
UINT8 tmp;
IOADDRESS nic_addr;
IOADDRESS asic_addr;

    /* meaningless, the asic addr i think maybe used on PC's netcard */
    sc->asic_addr = (IOADDRESS) (sc->ia_iobase + (UINT16) NE2000_NOVELL_ASIC_OFFSET);
    asic_addr = sc->asic_addr; /* used in the macro to calculate register pointers */
    ASSIGN_ASIC_ADDR(NE2000_NOVELL_DATA,  asic_addr_NE2000_NOVELL_DATA)
    ASSIGN_ASIC_ADDR(NE2000_NOVELL_RESET, asic_addr_NE2000_NOVELL_RESET)

    sc->nic_addr = (IOADDRESS)(sc->ia_iobase + NE2000_NOVELL_NIC_OFFSET);
    nic_addr = sc->nic_addr; /* used in the macro to calculate register pointers */
    ASSIGN_REG_ADDR(NE2000_P0_BNRY,nic_addr_NE2000_P0_BNRY)
    ASSIGN_REG_ADDR(NE2000_P0_CNTR0,nic_addr_NE2000_P0_CNTR0)
    ASSIGN_REG_ADDR(NE2000_P0_CNTR1,nic_addr_NE2000_P0_CNTR1)
    ASSIGN_REG_ADDR(NE2000_P0_DCR,nic_addr_NE2000_P0_DCR)
    ASSIGN_REG_ADDR(NE2000_P0_CNTR2,nic_addr_NE2000_P0_CNTR2)
    ASSIGN_REG_ADDR(NE2000_P0_CR,nic_addr_NE2000_P0_CR)
    ASSIGN_REG_ADDR(NE2000_P0_IMR,nic_addr_NE2000_P0_IMR)
    ASSIGN_REG_ADDR(NE2000_P0_ISR,nic_addr_NE2000_P0_ISR)
    ASSIGN_REG_ADDR(NE2000_P0_NCR,nic_addr_NE2000_P0_NCR)
    ASSIGN_REG_ADDR(NE2000_P0_PSTART,nic_addr_NE2000_P0_PSTART)
    ASSIGN_REG_ADDR(NE2000_P0_PSTOP,nic_addr_NE2000_P0_PSTOP)
    ASSIGN_REG_ADDR(NE2000_P0_RBCR0,nic_addr_NE2000_P0_RBCR0)
    ASSIGN_REG_ADDR(NE2000_P0_RBCR1,nic_addr_NE2000_P0_RBCR1)
    ASSIGN_REG_ADDR(NE2000_P0_RCR,nic_addr_NE2000_P0_RCR)
    ASSIGN_REG_ADDR(NE2000_P0_RSAR0,nic_addr_NE2000_P0_RSAR0)
    ASSIGN_REG_ADDR(NE2000_P0_RSAR1,nic_addr_NE2000_P0_RSAR1)
    ASSIGN_REG_ADDR(NE2000_P0_RSR,nic_addr_NE2000_P0_RSR)
    ASSIGN_REG_ADDR(NE2000_P0_TBCR0,nic_addr_NE2000_P0_TBCR0)
    ASSIGN_REG_ADDR(NE2000_P0_TBCR1,nic_addr_NE2000_P0_TBCR1)
    ASSIGN_REG_ADDR(NE2000_P0_TCR,nic_addr_NE2000_P0_TCR)
    ASSIGN_REG_ADDR(NE2000_P0_TPSR,nic_addr_NE2000_P0_TPSR)
    ASSIGN_REG_ADDR(NE2000_P0_TSR,nic_addr_NE2000_P0_TSR)
    ASSIGN_REG_ADDR(NE2000_P1_CR,nic_addr_NE2000_P1_CR)
    ASSIGN_REG_ADDR(NE2000_P1_CURR,nic_addr_NE2000_P1_CURR)
    ASSIGN_REG_ADDR(NE2000_P1_MAR0,nic_addr_NE2000_P1_MAR0)
    ASSIGN_REG_ADDR(NE2000_P1_MAR1,nic_addr_NE2000_P1_MAR1)
    ASSIGN_REG_ADDR(NE2000_P1_MAR2,nic_addr_NE2000_P1_MAR2)
    ASSIGN_REG_ADDR(NE2000_P1_MAR3,nic_addr_NE2000_P1_MAR3)
    ASSIGN_REG_ADDR(NE2000_P1_MAR4,nic_addr_NE2000_P1_MAR4)
    ASSIGN_REG_ADDR(NE2000_P1_MAR5,nic_addr_NE2000_P1_MAR5)
    ASSIGN_REG_ADDR(NE2000_P1_MAR6,nic_addr_NE2000_P1_MAR6)
    ASSIGN_REG_ADDR(NE2000_P1_MAR7,nic_addr_NE2000_P1_MAR7)
    ASSIGN_REG_ADDR(NE2000_P1_PAR0,nic_addr_NE2000_P1_PAR0)

    /* Reset the board.   */
    tmp = INBYTE(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_RESET));
    OUTBYTE(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_RESET), tmp);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
    
    NU_Sleep(2);    /* 5000 usec */

    /* initialize DCR for byte operations.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTART),8192 / NE2000_PAGE_SIZE);	//this value is overridden in ne2000_init
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTOP), 16384 / NE2000_PAGE_SIZE);
    sc->isa16bit = 0;
    
#define MEMSIZE  16384
#define MEMSTART 16384

    sc->mem_start = MEMSTART;
    sc->mem_size = MEMSIZE;
    sc->mem_end = (UINT16)((long)MEMSTART + (long)MEMSIZE);

    /* XMIT Page offset is the begining of ram to the NE
       RCV Page offset is xmit offset + size of xmite ring 
       RCV End is Begining of ram + size of rem */
    sc->tx_page_start = (UINT16) (MEMSTART / NE2000_PAGE_SIZE);
    sc->rec_page_start = (UINT16)((MEMSTART / NE2000_PAGE_SIZE) + NE2000_TXBUF_SIZE);
    sc->rec_page_stop =  (UINT16) ((MEMSTART / NE2000_PAGE_SIZE) + MEMSIZE / NE2000_PAGE_SIZE);
    sc->mem_ring = MEMSTART + NE2000_PAGE_SIZE * NE2000_TXBUF_SIZE;
    //ne2000_pio_readmem(sc, 0, romdata, 16);
    //for (n = 0; n < ETH_ALEN; n++)
    //    pi->addr.my_hw_addr[n] = romdata[n*(sc->isa16bit+1)];

    /* Clear any pending interrupts that might have occurred above.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), 0xff);

    return (1);
}

/* ********************************************************************   */
/* OPEN and CLOSE routines.                                               */
/* ********************************************************************   */

void ne2000_close(/*PIFACE pi*/)                     /*__fn__*/
{
PNE2000_SOFTC sc;

    sc = iface_to_softc();
    if (!sc)
        return;
    ne2000_stop(sc);
}

/* ********************************************************************   */
/* Install interface into kernel networking data structures.              */
BOOLEAN ne2000_open(VOID)
{
PNE2000_SOFTC sc;
VOID (*oldfptr)(INT);

    sc = iface_to_softc();
    if (!sc)
    {
        //set_errno(ENUMDEVICE);
        return(FALSE);
    }

    tc_memset((PFBYTE) sc, 0, sizeof(*sc));

    /* determine which device and initialize    */
    sc->ia_iobase = (IOADDRESS) CFG_NE2000_IOBASE; 
    sc->ia_irq    = CFG_NE2000_IRQ; 

    if (!(ne2000_probe_Novell(sc)))
    {
        //DEBUG_ERROR("ne2000probe failed", NOVAR, 0, 0);
        //set_errno(EPROBEFAIL);
        return(FALSE);
    }
    
    /* Set interface to stopped condition (reset).   */
    ne2000_stop(sc);

    /* Register interrupt lisr   */
    NU_Register_LISR(sc->ia_irq/*22*/, ne2000_interrupt, &oldfptr);
    rI_ISPR |= BIT_EINT1;		//clear pending bit
    rINTMSK &= ~BIT_EINT1;		//enable interrupt bit
    
    ne2000_reset(sc);
    
    return(TRUE);
}

/* Reset interface.   */
void ne2000_reset(/*PIFACE pi, */PNE2000_SOFTC sc)
{
STATUS previous_int_value;

    /*  Lock out interrupts.  */
    previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
   
    ne2000_stop(sc);
    ne2000_init(sc);
   
    NU_Control_Interrupts(previous_int_value);
}
 
/* Take interface offline.   */
void ne2000_stop(PNE2000_SOFTC sc)
{
int n = 5000;

    /* Stop everything on the interface, and select page 0 registers.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);

    /*
     * Wait for interface to enter stopped state, but limit # of checks to
     * 'n' (about 5ms).  It shouldn't even take 5us on modern DS8390's, but
     * just in case it's an old one.
     */
    while (((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RST) == 0) && --n);
}

/* Initialize device.    */
void ne2000_init(PNE2000_SOFTC sc)
{
int i;
STATUS previous_int_value;
UINT8  mcaf[8];   /* multicast address filter */
UINT8  my_hw_addr[6];

	tc_memset(my_hw_addr, 2, 6);	//set the macaddress is all 2
	tc_memset(mcaf, 1, 8);			//accept all multicast packet
    
    /*
     * Initialize the NIC in the exact order outlined in the NS manual.
     * This init procedure is "mandatory"...don't change what or when
     * things happen.
     */

	/*  Lock out interrupts.  */
    previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
    
    /* This variable is used below - don't move this assignment.   */
    sc->next_packet = (UINT16) (sc->rec_page_start + 1);

    /* Set interface for page 0, remote DMA complete, stopped.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);

    if (sc->isa16bit) 
    {
        /*
         * Set FIFO threshold to 8, No auto-init Remote DMA, UINT8
         * order=80x86, UINT16-wide DMA xfers,
         */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_WTS | NE2000_DCR_LS);
    } 
    else 
    {
        /* Same as above, but UINT8-wide DMA xfers.   */
        OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS);
    }

    /* Clear remote UINT8 count registers.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), 0);

    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), 0);

    /* Tell RCR to do nothing for now.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RCR), NE2000_RCR_MON);

    /* Place NIC in internal loopback mode.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), NE2000_TCR_LB0);

    /* Initialize transmit/receive (ring-buffer) page start.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TPSR), sc->tx_page_start);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTART), sc->rec_page_start);

    /* Initialize receiver (ring-buffer) page stop and boundary.   */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTOP), sc->rec_page_stop);
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_BNRY), sc->rec_page_start);

    /*
     * Clear all interrupts.  A '1' in each bit position clears the
     * corresponding flag.
     */
    OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), 0xff);

    /*
     * Enable the following interrupts: receive/transmit complete,
     * receive/transmit error, and Receiver OverWrite.
     *

⌨️ 快捷键说明

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