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

📄 netdrv.c

📁 ARM得编程实例。很经典。在win ce5.0环境下的编程实例
💻 C
字号:
/*******************************************************************
                
*******************************************************************/
#include "..\system.h"

#ifdef INTEL_X86_CPU
    #include <stdlib.h>
    #include <conio.h>
    #include <dos.h>
#endif

#include "..\utility.h"
#include "..\hardware.h"

#include "ne2000.h"
#include "NetDrv.h"

/************************** 8019 port operation ****************************/
/* Wrap 8019 write port operation */
#define rtl8019Write(RTL_ADDRESS, RTL_DATA)     (outp((io_address)  \
               + ((unsigned char)(RTL_ADDRESS)) , (unsigned short)(RTL_DATA)))

/* Wrap 8019 read port operation */
#define rtl8019Read(RTL_ADDRESS)   (inp((io_address) \
                   + ((unsigned char)(RTL_ADDRESS)) ))

/*************************** 调试变量和函数 ********************************/
#if defined(INTEL_X86_CPU) && defined(DEBUG)
INT16U sndok = 0;  /* 发送成功次数 */
#endif

INT16U usrdatalen = 0;   /* user data length */
INT16U rcvErrStatus = 0; /* receiving error status */
#ifdef ARM_XSCALE_CPU 
    unsigned char nextPage = 0;
    unsigned short curAddress = 0;
#endif
/***************************** 局部变量定义 ********************************/
NET_CONFIG_STRUCT  NetConfig[MAX_CARD_NUMBER];  /* 网络配置数组 */

/**************************** 函数声明 *************************************/
static void rtl8019Init(INT16U CardID);                /* 8019as芯片初始化 */
static void rtl8019ReadMAC(INT16U CardID);             /* 读芯片MAC地址    */
static void rtl8019Overrun(INT16U CardID);             /* 芯片溢出处理     */

/**************************** 全局函数定义 *********************************/

/* 初始化网络配置数组 */
void NetCfgInit(void) {
    NetConfig[0].CardID = 0;   
    NetConfig[0].IOAddr = NET0_IOBADDR;

    NetConfig[1].CardID = 1;   
    NetConfig[1].IOAddr = NET1_IOBADDR;

    NetConfig[2].CardID = 2;   
    NetConfig[2].IOAddr = NET2_IOBADDR;

    NetConfig[3].CardID = 3;   
    NetConfig[3].IOAddr = NET3_IOBADDR;
}

/*
    函数名 : netOpen
    功能   : 网卡芯片检测,初始化 
    参数   : CardID 网卡逻辑编号 
    返回值 : 初始化是否正确
             0x00 正确 
             0xFF 网卡不存在 
*/
INT8U netOpen(INT16U CardID) {
    INT16U io_address = 0;
    io_address = NetConfig[CardID].IOAddr;
    
    if (0xFF == ReadPort(io_address)) {
        return(0xFF);
	}

    rtl8019ReadMAC(CardID);          /* Read the Physical Address */
    rtl8019Init(CardID);             /* Initialize */    
    
    return(0x00);
}

void netClose(INT16U CardID) {
    CardID = CardID;
}

/*
    函数名 : rtl8019Receive
    功能   : 8019As接收以太网帧 
    参数   : CardID 网卡逻辑编号 
             buffer 接收缓冲区指针 
    返回值 : 接收是否成功 TRUE 成功   FALSE 失败 
*/
BOOL rtl8019Receive(INT16U CardID, INT8U *buffer)
{
    unsigned short in = 0, out = 0;
    unsigned short i = 0;

    unsigned short rxlen = 0;
    unsigned char header[4] = {0, 0, 0, 0};
#ifdef INTEL_X86_CPU 
    static unsigned char nextPage = 0;
    static unsigned short curAddress = 0;
#endif
    INT16U io_address = 0;
    io_address = NetConfig[CardID].IOAddr;

	/* read CURR from page 1 */
    rtl8019Write(CR, 0x62);
    in = rtl8019Read(CURR);

    rtl8019Write(CR, 0x22);	 /* return to page 0 */
    out = rtl8019Read(BNDRY);	 /* Get the boundary register */

    /* return if there is no packet in the buffer */
    if (in == out) {
        rcvErrStatus = (NET_ERROR|0x03);
        usrdatalen = 0;
	    return(FALSE);
    }

    /* Clear the packet received interrupt flag */
    rtl8019Write(ISR, (1 << ISR_PRX) );

    /* If the boundary pointer is invalid,reset the buffer then exit */
    if ( (out >= RXSTOP_INIT) || (out < RXSTART_INIT) )
    {
        rtl8019Write(BNDRY, RXSTART_INIT);
        rtl8019Write(CR, 0x62);
	    rtl8019Write(CURR, RXSTART_INIT);
        rtl8019Write(CR, 0x22);

        rcvErrStatus = (NET_ERROR|0x04);
        usrdatalen = 0;
        return(FALSE);
    }

    /* Initiate DMA to transfer the packet header: */
    /* statrs(1), nextptr(1), bytecount(2) */
    rtl8019Write(RBCR0, 4);
    rtl8019Write(RBCR1, 0);
    rtl8019Write(RSAR0, 0);
    rtl8019Write(RSAR1, out);
    rtl8019Write(CR, 0x0A);
    for (i = 0; i < 4; i++ ) {
        header[i] = (unsigned char)rtl8019Read(NIC_DATA);
	}

    /* End the DMA operation */
    rtl8019Write(CR, 0x22);
    for (i = 0; i < 50; i++ )    {
		if ( rtl8019Read(ISR) & (1 << 6) ) {
              break;
	    }
    }
    rtl8019Write(ISR, 1 << 6 );

    rxlen = (header[PACKET_LENHIGH] << 8) + header[PACKET_LENLOW];
    nextPage = header[PACKET_NEXTBLK];

    curAddress = (out << 8) + 4;

    /* If the nextPage pointer is invalid,the packet is not ready yet,exit */
    if ( (nextPage >= RXSTOP_INIT) || (nextPage < RXSTART_INIT) ) {
        rcvErrStatus = (NET_ERROR|0x05);
        usrdatalen = 0;
        return(FALSE);
    }

    rxlen -= 4;

    /* Initial DMA to transfer data */
    rtl8019Write(RBCR0, rxlen);
    rtl8019Write(RBCR1, (rxlen >> 8));
    rtl8019Write(RSAR0, curAddress);
    rtl8019Write(RSAR1, (curAddress >> 8));
    rtl8019Write(CR, 0x0A);

    /* Ignore Dest. MAC(6), Src MAC(6), type/len(2) */
    for (i = 0; i < 14; i++ ) {
	    rtl8019Read(NIC_DATA);
	}

    usrdatalen = rxlen - 14;

	for (i = 0; i < rxlen - 14; i++ ) {
	    buffer[i] = (unsigned char)rtl8019Read(NIC_DATA);
    }

    /* End the DMA operation */
    rtl8019Write(CR, 0x22);
    for (i = 0; i < 50; i++ )   {
	    if ( rtl8019Read(ISR) & (1 << ISR_RDC) ) {
              break;
	    }
    }
    rtl8019Write(ISR, 1 << ISR_RDC );

    curAddress += rxlen;

    if ( curAddress >= RXSTOP_ADDRESS ) {
		curAddress = curAddress - (RXSTOP_ADDRESS - RXSTART_ADDRESS);
	}

    /* End the DMA operation */
    rtl8019Write(CR, 0x22);
    for (i = 0; i <= 50; i++) {
	    if (rtl8019Read(ISR) & (1 << ISR_RDC) ) {
	         break;
	    }
	}
    rtl8019Write(ISR, 1 << ISR_RDC);

    /* Set the boundary register to point to the start of the next packet */
    rtl8019Write(BNDRY, nextPage);

    rcvErrStatus = 0;
    return(TRUE);
}

/*
    函数名 : rtl8019Send
    功能   : 8019As发送以太网帧 
    参数   : CardID 网卡逻辑编号 
             destMAC 目标MAC数组指针 
             buffer 发送缓冲区指针 
             len  数据长度 
    返回值 : void 
*/
void rtl8019Send(INT16U CardID, INT8U * destMAC, INT8U * buffer, long int len)
{
    long int i = 0;
    long int length = 0;
    INT16U io_address = 0;
    io_address = NetConfig[CardID].IOAddr;

    length = len;

#ifdef INTEL_X86_CPU 
    _disable();
#endif
    rtl8019Write(CR, 0x22);  /* Abort Remote DMA,start command */

    /* Still transmitting a packet - wait for it to finish */
    while ( rtl8019Read(CR) & 0x04 ) ;

    length += 14;  /* include the length of DA,SA,Type */

    /* Load data byte count for remote DMA */
    rtl8019Write(RBCR0, length);
    rtl8019Write(RBCR1, (length >> 8));

    /* Set start address for remote DMA operation */
    rtl8019Write(RSAR0, 0x00);
    rtl8019Write(RSAR1, 0x40);

    rtl8019Write(CR, 0x12); /* Remote write operation */

    /* write frame */
    for (i = 0 ; i < MACLEN ; i++)  { /* destination mac address */
        rtl8019Write(NIC_DATA, (destMAC[i]));
	}
    for ( i = 0 ; i < MACLEN ; i++)  { /* source mac address */
        rtl8019Write(NIC_DATA, (NetConfig[CardID].LocalMAC[i]));
	}

    rtl8019Write(NIC_DATA, len >> 8);
    rtl8019Write(NIC_DATA, len&0xff);

    for (i = 0 ; i < len ; i++) {
	    rtl8019Write(NIC_DATA, (*(buffer+i))); 
	}

    /* End the DMA operation */
    for (i = 0; i < 400; i++) {
        if (rtl8019Read(ISR) & (1 << ISR_RDC)) {
	        break;
		}
    }
    rtl8019Write(ISR, (1 << ISR_RDC));


    /* Load beginning page for transmit buffer */
    rtl8019Write(TPSR, TXSTART_INIT);

    rtl8019Write(TBCR0, length );
    rtl8019Write(TBCR1, length >> 8);

    /* Send the contents of the transmit buffer onto the network */
    rtl8019Write(CR, 0x26);

#ifdef INTEL_X86_CPU 
    _enable();
#endif
}

/* Process Receive Overflow */
void rtl8019ProcessInterrupt(INT16U CardID)  {
#if defined(INTEL_X86_CPU) && defined(DEBUG)
    static INT16U noverflow = 0;
#endif

    INT16U io_address = 0;
    INT8U byte = 0;
    io_address = NetConfig[CardID].IOAddr;
	byte = (unsigned char)rtl8019Read(ISR);	

	if ( byte & (1 << ISR_OVW) ) {
        rcvErrStatus = (NET_ERROR|0x06);
        usrdatalen = 0;
	    rtl8019Overrun(CardID);
        #if defined(INTEL_X86_CPU) && defined(DEBUG)
	    wprintf(12, 40, "Net%d overflow %u", CardID, noverflow++);
	    #endif
	}
}

/* whether the receive buffer is empty? */
BOOL IsEmpty(INT16U CardID) {
    unsigned short in = 0, out = 0;
    INT16U io_address = 0;

    io_address = NetConfig[CardID].IOAddr;

    rtl8019Write(CR, 0x62);
    in = rtl8019Read(CURR);
    rtl8019Write(CR, 0x22);
    out = rtl8019Read(BNDRY);

    if (in == out) {
	    return(TRUE);
    } else {
	    return(FALSE);
    }
}

/* whether the transmition is completed */
BOOL IsTransEnd(INT16U CardID) {
    INT16U io_address = 0;
    INT8U byte = 0;
    io_address = NetConfig[CardID].IOAddr;

    byte = (unsigned char)rtl8019Read(ISR);

    if (byte & (1 << ISR_TXE)) {
	    rtl8019Write(ISR, (1 << ISR_TXE) );
        #if defined(INTEL_X86_CPU) && defined(DEBUG)
	    wprintf(13, 50, "Net%d TXE error", CardID);
	    #endif
        return(TRUE);
    }

    if (byte & (1 << ISR_PTX)) {
	    rtl8019Write(ISR, (1 << ISR_PTX) );
    #if defined(INTEL_X86_CPU) && defined(DEBUG)
	    sndok++;
    #endif
	    return(TRUE);
    }  else {
	    return(FALSE);
    }
}

/**************************** 局部函数定义 *********************************/
static void rtl8019Init(INT16U CardID)  {
    INT16U io_address = 0;
    io_address = NetConfig[CardID].IOAddr;
    
#ifdef ARM_XSCALE_CPU 
    nextPage = 0;
    curAddress = 0;
#endif

    rtl8019Write(CR, 0x21);
    rtl8019Write(NIC_RESET, 0xFF);
#ifdef INTEL_X86_CPU 
    Delay(100);
#endif

    rtl8019Write(CR, 0x21);    /* Page 0,Abort DMA,Stop Command */
    rtl8019Write(DCR, DCR_INIT);

    rtl8019Write(RBCR0, 0x00); /* Clear remote byte count registers */
    rtl8019Write(RBCR1, 0x00);
    rtl8019Write(RCR, 0x14);

    rtl8019Write(TPSR, TXSTART_INIT);
    rtl8019Write(TCR, 0x02);   /* Internal Loop Back */

    rtl8019Write(BNDRY, RXSTART_INIT);  /* Start of Buffer RAM */
    rtl8019Write(PSTART, RXSTART_INIT); /* Start of Buffer RAM */
    rtl8019Write(PSTOP, RXSTOP_INIT); /* 8-bit mode */

    rtl8019Write(CR, 0x61);
    rtl8019Write(CURR, RXSTART_INIT);

    /* 
      Physical_Address is not initialized on the first pass.  We need to 
      read it from the 93C46 and set it during initialization
     */
    rtl8019Write(PAR0, NetConfig[CardID].LocalMAC[0]); 
    rtl8019Write(PAR1, NetConfig[CardID].LocalMAC[1]); 
    rtl8019Write(PAR2, NetConfig[CardID].LocalMAC[2]); 
    rtl8019Write(PAR3, NetConfig[CardID].LocalMAC[3]);
    rtl8019Write(PAR4, NetConfig[CardID].LocalMAC[4]);
    rtl8019Write(PAR5, NetConfig[CardID].LocalMAC[5]);

    rtl8019Write(CR, 0x22);
    rtl8019Write(ISR, 0xFF);	    /* Clear Interrupt Status Register */
    rtl8019Write(IMR, IMR_INIT);	    /* Setup Interrupt Mask Register   */
    rtl8019Write(TCR, TCR_INIT);     /* Take the NIC out of Loop Back.  */
}

/* Read 8019AS MAC address from Remote DMA Port */
static void rtl8019ReadMAC(INT16U CardID)
{
    int ignore = 0;
    INT16U io_address = 0;
    io_address = NetConfig[CardID].IOAddr;

    rtl8019Write(CR, 0x22);    /* Page0,Abort Remote DMA,Start Command */
    rtl8019Write(RBCR0, 0xFF); /* Set maximum number of bytes to read/write */
    rtl8019Write(RBCR1, 0xFF);
    rtl8019Write(RSAR0, 0);
    rtl8019Write(RSAR1, 0);

    rtl8019Write(CR, 0x0A);    /* Page0,Remote Read,Start Command */

    NetConfig[CardID].LocalMAC[0] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
    NetConfig[CardID].LocalMAC[1] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
    NetConfig[CardID].LocalMAC[2] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
    NetConfig[CardID].LocalMAC[3] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
    NetConfig[CardID].LocalMAC[4] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
    NetConfig[CardID].LocalMAC[5] = (INT8U)rtl8019Read(NIC_DATA);
    ignore = rtl8019Read(NIC_DATA);
}

static void rtl8019Overrun(INT16U CardID)  /* 芯片溢出处理     */
{
	unsigned char data_L = 0, resend = 0;
	INT16U io_address = 0;
	
    io_address = NetConfig[CardID].IOAddr;

	data_L = (unsigned char)rtl8019Read(CR);
	rtl8019Write(CR, 0x21);
	#ifdef INTEL_X86_CPU 
	Delay(10);
	#endif
	rtl8019Write(RBCR0, 0x00);
	rtl8019Write(RBCR1, 0x00);
	if (!(data_L & 0x04)) {
		resend = 0;
	} else if (data_L & 0x04) {
	   data_L = (unsigned char)rtl8019Read(ISR);
	   if ((data_L & 0x02) || (data_L & 0x08)) {
	    	resend = 0;
	   } else {
	    	resend = 1;
	   }
	}

	rtl8019Write(TCR, 0x02);
	rtl8019Write(CR, 0x22);
	rtl8019Write(BNDRY, RXSTART_INIT);
	rtl8019Write(CR, 0x62);
	rtl8019Write(CURR, RXSTART_INIT);
	rtl8019Write(CR, 0x22);
	rtl8019Write(ISR, 0x10);
	rtl8019Write(TCR, TCR_INIT);

    if (resend) {
	   rtl8019Write(CR, 0x26);
	}

    rtl8019Write(ISR, 0xFF);
}

⌨️ 快捷键说明

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