📄 rtl8019.c
字号:
/*
+------------------------------------------------------------------------------
| 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 + -