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

📄 rtl8019.c.svn-base

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/*
+------------------------------------------------------------------------------
| File        : rtl8019.c
+------------------------------------------------------------------------------
| Description :	RealTek 8019 ethernet interface
+------------------------------------------------------------------------------
| History     : 2006-10-10, Qiu Yi,	The init version
+------------------------------------------------------------------------------
*/
#include <net/rtl8019.h>
#include <net/ethernetif.h>
#include <rtthread.h>
#include <rtconfig.h>
#include <rthw.h>

#include <string.h>
#include <net/net_task.h>
//#include <net/netintf.h>
//#include <net/in.h>

typedef unsigned long u_long;
typedef unsigned int u_int;
typedef unsigned short u_short;
typedef unsigned char u_char;

#define RTL8019_DEBUG(...)	do { rt_kprintf("[%s:%d]", __FUNCTION__, __LINE__); rt_kprintf(__VA_ARGS__);rt_kprintf("\n"); } while(0)

extern struct netif rtl8019if;

/* for lwip config */
//#include <config.h>
#ifdef IP_STACK_LWIP
extern int lwip_buffer_copy_to(char *, int, void *);
extern void* lwip_buffer_alloc(int);
extern void lwip_buffer_copy_from(void *, int, void *);
extern void lwip_ethpkt_notify(void *);
#endif

/* commands for CR register */
#define	CMD_STOP	0x01		/* stop */
#define	CMD_RUN		0x02		/* run */
#define	CMD_XMIT	0x04		/* xmit, transmit data to network  */
#define	CMD_READ	0x08		/* read */
#define	CMD_WRITE	0x10		/* write */
#define	CMD_SEND	0x18		/* send */
#define	CMD_NODMA	0x20		/* no DMA */
#define	CMD_PAGE0	0x00		/* select 0 page */
#define	CMD_PAGE1	0x40		/* select 1 page */
#define	CMD_PAGE2	0x80		/* select 2 page */

#define	XMIT_START	0x4000		/* the start address of transmit buffer */
#define	RECV_START	0x4600		/* the start address of receive buffer */
#define	RECV_STOP	0x6000		/* the end address of receive buffer */

/* the status of interrupt status register */
#define	ISR_PRX		0x01		/* ISR of packet receive */
#define	ISR_PTX		0x02		/* ISR of packet transmit */
#define	ISR_RXE		0x04		/* ISR of receive error */
#define	ISR_TXE		0x08		/* ISR of transmit error */
#define	ISR_OVW		0x10		/* ISR of buffer overflow */
#define	ISR_CNT		0x20		/* ISR of count error */
#define	ISR_RDC		0x40		/* ISR of end of DMA */
#define	ISR_RST		0x80		/* ISR of reset */

/* value of Data Control Register */
#define	DCR_WTS		0x01
#define	DCR_BOS		0x02
#define	DCR_LAS		0x04
#define	DCR_LS		0x08
#define	DCR_ARM		0x10
#define	DCR_FIFO2	0x00
#define	DCR_FIFO4	0x20
#define	DCR_FIFO8	0x40
#define	DCR_FIFO12	0x60

/* value of Transmit Control Register */
#define	TCR_CRC			0x01
#define	TCR_LOOP_NONE	0x00
#define	TCR_LOOP_INT	0x02
#define	TCR_LOOP_EXT	0x06
#define	TCR_ATD			0x08
#define	TCR_OFST		0x10

/* value of Receive Control Register */
#define	RCR_SEP		0x01
#define	RCR_AR		0x02
#define	RCR_AB		0x04
#define	RCR_AM		0x08
#define	RCR_PRO		0x10
#define	RCR_MON		0x20

struct net_device_stats
{
	unsigned long rx_packets;	/* total packets received	*/
	unsigned long tx_packets;	/* total packets transmitted	*/
	unsigned long rx_errors;	/* receive bad packets */
	unsigned long tx_errors;	/* transmit bad packets */
};

#define MAX_ADDR_LEN	6			/* Largest hardware address length */
struct rtl8019_device
{
	char devname[8];
	unsigned short flags;

	struct net_device_stats stats;

	/* interface address info. */
	unsigned char dev_addr[MAX_ADDR_LEN];	/* hw address	*/
};
struct rtl8019_device rtl8019_device;

#define ETH_ALEN		6		/* Octets in one ethernet addr	 */
#define ETH_HLEN		14		/* Total octets in header.	 */
#define ETH_ZLEN		60		/* Min. octets in frame sans FCS */
#define ETH_DATA_LEN	1500	/* Max. octets in payload	 */
#define ETH_FRAME_LEN	1514	/* Max. octets in frame sans FCS */

struct ethnet_frame
{
	unsigned char  dst[ETH_ALEN];
	unsigned char  src[ETH_ALEN];
	unsigned short proto;
	unsigned char  data[ETH_DATA_LEN+22];
};

static void ne_copyin(u_short count, u_char *buf);
static void ne_copyout(u_short count, u_char *buf);
static void ne_discard(u_short count);

void rtl8019_cleanup();
int rtl8019_open(const char *pathname, int flags);
int rtl8019_close(int d);
int rtl8019_ioctl(int d, int request, void* p);
int rtl8019_recv(int d, void *buf, size_t count);
int rtl8019_send(int d, const void *buf, size_t count);
int rtl8019_poll_start();
int rtl8019_poll_stop();
int rtl8019_poll_recv(int d, char *buf, size_t count);
int rtl8019_poll_send(int d, const char *buf, size_t count);
void rtl8019_isr(int irqno);
static void rtl8019_rx_job(void *param);

struct ifnet rtl8019_ifnet =
{
	RT_NULL,
	rtl8019_init,
	rtl8019_cleanup,
	rtl8019_open,
	rtl8019_close,
	rtl8019_ioctl,
	rtl8019_recv,
	rtl8019_send,
	rtl8019_poll_recv,
	rtl8019_poll_send
};

struct ethernetif_ops rtl8019_eth_ops =
{
	rtl8019_ioctl,
	rtl8019_poll_send,
	rtl8019_poll_recv,
	rtl8019_send
};

/*
 * Read the specified number of bytes from the device DMA port into
 * the supplied buffer.
 */
static void ne_copyin(u_short count, u_char *buf)
{
	while(count--) *buf++ = NE_DMA;
}

/*
 * Write the specified number of bytes from the device DMA port into
 * the supplied buffer.
 */
static void ne_copyout(u_short count, u_char *buf)
{
	while(count--) NE_DMA = *buf++;
}

/*
 * Pull the specified number of bytes from the device DMA port,
 * and throw them away.
 */
static void ne_discard(u_short count)
{
	u_char value;
	while(count--) value = NE_DMA;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_cleanup
+------------------------------------------------------------------------------
| Description : Cleans up realtek 8019 ethernet interface
+------------------------------------------------------------------------------
*/
void rtl8019_cleanup()
{
	return ;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_open
+------------------------------------------------------------------------------
| Description : Opens realtek 8019 ethernet interface
|
| Parameters  : pathname, the device's name
|               flags,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_open(const char *pathname, int flags)
{
	return 0;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_close
+------------------------------------------------------------------------------
| Description : Closes realtek 8019 ethernet interface
|
| Parameters  : d,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_close(int d)
{
	/* mask all interrupts */
	NE_IMR = 0;

	/* clear ISR */
	NE_ISR = 0xff;

	/* stop nic */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;

	return 0;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_ioctl
+------------------------------------------------------------------------------
| Description : Controls I/O of realtek 8019 ethernet interface
|
| Parameters  : d,
|               request,
|               p,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_ioctl(int d, int request, void* p)
{
	switch(request)
	{
		case NIOCTL_POLLSTART:
			rtl8019_poll_start();
			break;

		case NIOCTL_POLLSTOP:
			rtl8019_poll_stop();
			break;

		case NIOCTL_GADDR:
    		/* get mac address */
    		if(p) memcpy(p, rtl8019_device.dev_addr, 6);
			else  return -1;
			break;

		default :
			break;
	}

	return 0;
}

#define S3C_REG		*(volatile unsigned int *)
#define PCONC		(S3C_REG(0x1d20010))
#define PDATC		(S3C_REG(0x1d20014))
#define PUPC			(S3C_REG(0x1d20018))


static void Delay(unsigned ms)
{
	ms *= 7326;			/* 调整延时到循环周期数(MCLK=66MHz, SDRAM)*/
	while(--ms);		/* 循环延时*/
}

static void ResetNIC(void)
{
	PCONC = PCONC & ~0x30000 | 0x10000;	/* 设定PC8为输出状态(连接NIC的RESET引脚)*/
	PDATC |= 0x100;						/* 输出高电平*/
	Delay(200);								/* 延时至少200毫秒*/
	PDATC &= ~0x100;						/* 输出低电平*/
	Delay(200);								/* 延时,确保NIC复位成功*/
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_init
+------------------------------------------------------------------------------
| Description : Inits realtek 8019 ethernet interface
+------------------------------------------------------------------------------
*/
void rtl8019_init(void)
{
	ResetNIC();						/* 复位NIC*/

	/* set MAC address */
	rtl8019_device.dev_addr[0] = 0x0;
	rtl8019_device.dev_addr[1] = 0x1;
	rtl8019_device.dev_addr[2] = 0x2;
	rtl8019_device.dev_addr[3] = 0x3;
	rtl8019_device.dev_addr[4] = 0x4;
	rtl8019_device.dev_addr[5] = 0x5;
		
	Delay(10);						/* 延时,确保NIC停止*/

	/* config in PAGE0 */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;

	NE_RBCR0 = 0x0;
	NE_RBCR1 = 0x0;
	
	NE_TPSR		= XMIT_START >> 8;
	NE_PSTART	= RECV_START >> 8;
	NE_BNRY		= RECV_START >> 8;
	NE_PSTOP	= RECV_STOP >> 8;
	
	NE_ISR = 0xff;				
	NE_RCR = 0xcc;				/* 准备接受状态*/

	NE_TCR = 0xe0;				/* 准备发送状态*/
#if DMA16
	NE_DCR = 0xc9;				/* 16位DMA操作*/
#else
	NE_DCR = 0xc8;				/* 8位DMA操作*/
#endif

	NE_IMR = ISR_OVW | ISR_TXE | ISR_PTX | ISR_PRX;
	/* clear all interrupts */
	NE_ISR = 0xff;

	/* config in PAGE1 */
	NE_CR	= CMD_PAGE1 | CMD_NODMA | CMD_STOP;
	NE_CURR = RECV_START >> 8;
	
	/* set MAC address */
	NE_PAR0 = rtl8019_device.dev_addr[0];
	NE_PAR1 = rtl8019_device.dev_addr[1];
	NE_PAR2 = rtl8019_device.dev_addr[2];
	NE_PAR3 = rtl8019_device.dev_addr[3];
	NE_PAR4 = rtl8019_device.dev_addr[4];
	NE_PAR5 = rtl8019_device.dev_addr[5];

	/* get mac addr */
	rtl8019_device.dev_addr[0] = NE_PAR0;
	rtl8019_device.dev_addr[1] = NE_PAR1;
	rtl8019_device.dev_addr[2] = NE_PAR2;
	rtl8019_device.dev_addr[3] = NE_PAR3;
	rtl8019_device.dev_addr[4] = NE_PAR4;
	rtl8019_device.dev_addr[5] = NE_PAR5;

	/* clear multicast filters (reject all multicast) */
	NE_MAR0 = 0x0;
	NE_MAR1 = 0x0;
	NE_MAR2 = 0x0;
	NE_MAR3 = 0x0;
	NE_MAR4 = 0x0;
	NE_MAR5 = 0x0;
	NE_MAR6 = 0x0;
	NE_MAR7 = 0x0;
	
	rt_hw_interrupt_install(INT_NE, rtl8019_isr, RT_NULL);
	rt_hw_interrupt_umask(INT_NE);

	NE_CR	= CMD_PAGE1 | CMD_NODMA | CMD_RUN;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_recv
+------------------------------------------------------------------------------
| Description : Receives some data buffer from realtek 8019 ethernet interface
|
| Parameters  : d,
|               buf,
|               count,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_recv(int d, void *buf, size_t count)
{
	return -1;
}

static char temp_tx_buf[1600];
/*
+------------------------------------------------------------------------------
| Function    : rtl8019_send
+------------------------------------------------------------------------------
| Description : Sends some data buffer to realtek 8019 ethernet interface
|
| Parameters  : d,
|               buf,
|               count,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_send(int d, const void *buf, size_t count)
{
	u_char isr;
	register rt_ubase_t temp;
	struct pbuf *p = (struct pbuf *)buf; 

	temp = rt_hw_interrupt_disable();
	
	/* set up to transfer the packet contents to the NIC RAM. */

	#ifdef IP_STACK_LWIP
	count = lwip_buffer_copy_to(temp_tx_buf, sizeof(struct ethnet_frame), (void *)buf);
	#else

⌨️ 快捷键说明

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