/************************************************
* www.21control.com
************************************************/
#ifdef LWIP
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <altera_avalon_pio_regs.h>
#include "alt_types.h"
#include "ctrl_rtl8019_regs.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include "netif/etharp.h"
#include "system.h"
#include "arch/perf.h"
#include "sys/alt_irq.h"
#include "ctrl_rtl8019.h"
/* Unique descricption of the network interface. */
#define IFNAME0 'n'
#define IFNAME1 '9'
extern sys_mbox_t rx_mbox;
static err_t
ctrl_rtl8019_output(struct netif *netif, struct pbuf *p,struct ip_addr *ipaddr);
static struct pbuf* low_level_input(ctrl_rtl8019_if *dev);
static err_t low_level_output(struct netif *netif, struct pbuf *p);
static err_t low_level_init(ctrl_rtl8019_if* dev);
void ctrl_rtl8019_irq(void* context, alt_u32 interrupt);
/*************************************************/
static inline void Delay16Cycles(void)
{
unsigned int i;
for(i=0;i<100;i++);
}
u_char reg_read(unsigned int base,u_char reg)
{
unsigned char uc;
uc=IORD_8DIRECT(base, reg); /* DYNAMIC MEMORY */
//uc=IORD(base, reg); /* NATIVE MEMORY SIZE */
return uc;
}
u_char reg_write(base,reg, data)
{
IOWR_8DIRECT(base, reg, data);/* DYNAMIC MEMORY */
//IOWR(base, reg, data); /* NATIVE MEMORY SIZE */
return data;
}
void getState(unsigned char *RTL_BASE_ADDR)
{
unsigned char old_cr,uc;
unsigned char tsr,isr,rsr;
unsigned char rcr,tcr,dcr,imr;
unsigned char pstart,pstop;
int iRet;
old_cr=IORD_CTRL_RTL8019_CR(0x00800000);
//change to page0
IOWR_CTRL_RTL8019_CR(0x00800000,CTRL_RTL8019_CR_STA_MSK | CTRL_RTL8019_CR_RD2_MSK );
tsr=IORD_CTRL_RTL8019_TSR(0x00800000);
isr=IORD_CTRL_RTL8019_ISR(0x00800000);
rsr=IORD_CTRL_RTL8019_RSR(0x00800000);
// change to page2
IOWR_CTRL_RTL8019_CR(0x00800000, CTRL_RTL8019_CR_STA_MSK | CTRL_RTL8019_CR_RD2_MSK | CTRL_RTL8019_CR_PS1_MSK);
pstop=IORD_CTRL_RTL8019_PSTOP(0x00800000);
pstart=IORD_CTRL_RTL8019_PSTART(0x00800000);
rcr=IORD_CTRL_RTL8019_RCR(0x00800000);
tcr=IORD_CTRL_RTL8019_TCR(0x00800000);
dcr=IORD_CTRL_RTL8019_DCR(0x00800000);
imr=IORD_CTRL_RTL8019_IMR(0x00800000);
IOWR_CTRL_RTL8019_CR(0x00800000,CTRL_RTL8019_CR_STP_MSK | CTRL_RTL8019_CR_RD2_MSK | CTRL_RTL8019_CR_PS0_MSK);
uc=IORD_CTRL_RTL8019_PAR0(0x00800000);
uc=IORD_CTRL_RTL8019_PAR1(0x00800000);
uc=IORD_CTRL_RTL8019_PAR2(0x00800000);
uc=IORD_CTRL_RTL8019_PAR3(0x00800000);
uc=IORD_CTRL_RTL8019_PAR4(0x00800000);
uc=IORD_CTRL_RTL8019_PAR5(0x00800000);
IOWR_CTRL_RTL8019_CR(0x00800000,old_cr);
}
/*!
* Reset the Ethernet controller.
* use hardware line e_rst
*/
int rtl8019_Reset(ctrl_rtl8019_if* dev)
{
unsigned char i;
unsigned char j;
/*
* Do the software reset by reading from the reset register followed
* by writing to the reset register. Wait until the controller enters
* the reset state.
*/
for (j = 0; j < 20; j++) {
IOWR_ALTERA_AVALON_PIO_DATA(E_RST_BASE,0x01); /* hardware reset*/
//IORD_CTRL_RTL8019_RESET(dev->base_addr);
OSTimeDlyHMSM(0,0,1,0);
//IOWR_CTRL_RTL8019_RESET(dev->base_addr,0xff);
IOWR_ALTERA_AVALON_PIO_DATA(E_RST_BASE,0x00); /* hardware reset*/
for (i = 0; i < 20; i++) {
OSTimeDlyHMSM(0,0,1,0);
/*
* We got the reset bit. However, Ethernut 1.1 may
* still fail because the NIC hasn't got it's hardware
* reset and the data lines remain in tristate. So we
* read noise instead of the register. To solve this
* problem, we will verify the NIC's id.
*/
i=IORD_CTRL_RTL8019_ISR(dev->base_addr);
if ((i & CTRL_RTL8019_ISR_RST_MSK ) != 0 )
return 0;
i=IORD_CTRL_RTL8019_8019ID0(dev->base_addr);
if ( i == 0x50 )
return 0;
i= IORD_CTRL_RTL8019_8019ID1(dev->base_addr);
if( i == 0x70)
return 0;
}
}
return -1;
}
/*-----------------------------------------------------------------------------------*
*
* ctrl_rtl8019_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*
*-----------------------------------------------------------------------------------*/
static void ctrl_rtl8019_input(ctrl_rtl8019_if *dev)
{
struct eth_hdr *ethhdr;
struct pbuf *p;
struct netif* netif = dev->lwip_dev_list.dev.netif;
/* move received packet into a new pbuf */
p = low_level_input(dev);
/* no packet could be read, silently ignore this */
if (p == NULL) return;
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
/* IP packet? */
case ETHTYPE_IP:
/*
* update ARP table
*
* The code which updates the ARP tables does not appear to be thread safe
* so I've added a MUTEX around all calls to the arp code
*
*/
sys_sem_wait(dev->arp_semaphore);
etharp_ip_input(netif, p);
sys_sem_signal(dev->arp_semaphore);
/* skip Ethernet header */
pbuf_header(p, -(s16_t)sizeof(struct eth_hdr));
/* pass to network layer */
netif->input(p, netif);
break;
case ETHTYPE_ARP:
/*
* pass p to ARP module
*
* The code which updates the ARP tables does not appear to be thread safe
* so I've added a MUTEX around all calls to the arp code
*
*/
sys_sem_wait(dev->arp_semaphore);
etharp_arp_input(netif, (struct eth_addr *)&netif->hwaddr, p);
sys_sem_signal(dev->arp_semaphore);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
/*-----------------------------------------------------------------------------------*
*
* ctrl_rtl8019_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*
*-----------------------------------------------------------------------------------*/
err_t ctrl_rtl8019_init(struct netif *netif)
{
err_t ret_code;
ctrl_rtl8019_if* dev = (ctrl_rtl8019_if*)netif->state;
dev->lwip_dev_list.dev.netif = netif;
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("ctrl_rtl8019_init()\n"));
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = ctrl_rtl8019_output;
netif->linkoutput = low_level_output;
if (netif->state == NULL )
{
ret_code = ERR_IF;
goto exit;
}
if (dev->bus_width != 8)
{
printf("This driver doesn't support the Ethernet add on card at present\n");
ret_code = ERR_IF;
goto exit;
}
ret_code = low_level_init(dev);
if (ret_code == ERR_OK)
{
etharp_init();
}
else
{
free(netif->state);
}
exit:
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("ctrl_rtl8019_init() exit = %d\n",ret_code));
return ret_code;
}
/*
* Fires up the network interface. NIC interrupts
* should have been disabled when calling this
* function.
*/
static err_t low_level_init(ctrl_rtl8019_if* dev)
{
unsigned char i,uc;
/*
* Need to have a pointer to a generice lwip_dev
* This is so that the get_mac_addr function interface
* is device agnostic
*/
alt_lwip_dev* lwip_dev = &dev->lwip_dev_list.dev;
err_t ret_code = ERR_OK;
LWIP_DEBUGF(NETIF_DEBUG |