📄 dev_net_rtl8019.c
字号:
//zzc: 2005-2-6 currently not support network simulation on Cygwin#ifndef __CYGWIN__/* dev_net_rtl8019.c - skyeye realtek 8019 ethernet controllor simulation Copyright (C) 2003 - 2005 Skyeye Develop Group for help please send mail to <skyeye-developer@lists.gro.clinux.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * 05/25/2005 modified for rtl8019 * walimis <wlm@student.dlut.edu.cn> * 04/27/2003 add net option support * chenyu <chenyu@hpclab.cs.tsinghua.edu.cn> * 02/25/2003 initial version * yangye <yangye@163.net> */#include <signal.h>#include <sys/time.h>//koodailar add for mingw 2005.12.18 ----------------------------------------#ifdef __MINGW32__#include "arch/arm/common/armdefs.h"#include "device/skyeye_device.h"#else#include "armdefs.h"#include "skyeye_device.h"#endif// end ----------------------------------------------------------------------#include "dev_net_rtl8019.h"//if you don't want to the debug info,just commit below two line//#define DEBUG 1#undef DEBUG#if DEBUG#define DBG_PRINT(a...) fprintf(stderr, ##a)#else#define DBG_PRINT(a...)#endifstatic struct device_default_value rtl8019_net_def[] = { /* name base size interrupt array */ {"at91", 0xfffa0000, 0xff, {16, 0, 0, 0}}, {NULL},};#define MAX_DEVICE_NUM 10static struct device_desc *rtl8019_devs[MAX_DEVICE_NUM];static inline voidnet_rtl8019_set_update_intr (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct machine_config *mc = (struct machine_config *) dev->mach; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; mc->mach_set_intr (intr->interrupts[INT_RTL8019]); mc->mach_update_intr (mc);}static inline voidset_time (int packets){//koodailar remove it for mingw 2005.12.18--------------------------------------//it may have timing problem. But i have not found it yet.//if there is anything wrong please report bugs. #ifndef __MINGW32__ struct itimerval value; value.it_value.tv_sec = 0; value.it_value.tv_usec = packets; value.it_interval = value.it_value; setitimer (ITIMER_REAL, &value, NULL);#endif//end -------------------------------------------------------------------------- }static voidsend_interrupt (){ int i; struct device_desc *dev; for (i = 0; i < MAX_DEVICE_NUM; i++) { if ((dev = rtl8019_devs[i]) != NULL) { struct net_device *net_dev = (struct net_device *) dev->dev; struct machine_config *mc = (struct machine_config *) dev->mach; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; if ((io->need_update) && (io->IMR & io->ISR)) { net_rtl8019_set_update_intr (dev); io->need_update = 0; set_time (0); return; } } }}static voidinit_sigaction (void){//koodailar remove it for mingw 2005.12.18--------------------------------------//may have problem . please see the above function:// static inline void set_time (int packets)#ifndef __MINGW32__ struct sigaction act; act.sa_handler = send_interrupt; act.sa_flags = 0; sigemptyset (&act.sa_mask); sigaction (SIGALRM, &act, NULL);#endif//end -------------------------------------------------------------------------- }static voidwrite_cr (struct device_desc *dev, u8 data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; u8 startpage; u16 packet_len; u16 rtl8019_len; DBG_PRINT ("write_cr begin: data %d\n", data); // Validate remote-DMA (RD2,RD1,RD0 not allowed to be 000) if (((data & 0x38) == 0x00)) { //wrong command DBG_PRINT ("write_cr: wrong command\n"); return; } // XMIT command if (data & CMD_XMIT) { DBG_PRINT ("write_cr: xmit command\n"); startpage = (io->TPSR - START_PAGE); //tpsr - 0x40 packet_len = (((u16) io->TBCR1 << 8) | (io->TBCR0)); packet_len &= 0xffff; io->TSR = 0; if (!rtl8019_output (dev, (io->sram + startpage * PAGE_SIZE), packet_len)) { io->TSR |= TSR_PTX; } else { io->TSR |= TSR_COL; } /**** send a interrupt to CPU here! ****/ io->ISR |= ISR_PTX; set_time (packet_len); io->need_update = 1; //net_rtl8019_set_update_intr(dev); } //remote dma write if ((data & CMD_READ) && (data & CMD_RUN)) { rtl8019_len = (((u16) io->RBCR1 << 8) | io->RBCR0); io->remote_read_offset = (u16) (io->RSAR1 << 8 | io->RSAR0) - (u16) (START_PAGE * PAGE_SIZE); io->remote_read_offset &= 0xffff; io->remote_read_count = rtl8019_len; //printf("io->remote_read_count:%d,io->remote_read_offset:%x\n", io->remote_read_count, io->remote_read_offset); } //remote dma write if ((data & CMD_WRITE) && (data & CMD_RUN) && ((data & CMD_NODMA) == 0)) { io->remote_write_offset = (io->RSAR1 << 8 | io->RSAR0) - START_PAGE * PAGE_SIZE; io->remote_write_count = (((u16) io->RBCR1 << 8) | io->RBCR0); io->remote_write_count &= 0xffff; //printf("rtl8019 rw:count:%d,offset:%x\n", io->remote_write_count, io->remote_write_offset); } io->CR = data; DBG_PRINT ("write_cr: end\n");}static voidremote_write_word (struct device_desc *dev, u16 data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; DBG_PRINT ("remote_write begin: data %d\n", data); if (io->CR & CMD_WRITE) { //in remote write mode io->sram[io->remote_write_offset] = data & 0xff; io->sram[io->remote_write_offset + 1] = data >> 8; io->remote_write_offset += 2; io->remote_write_count -= 2; if (io->remote_write_count <= 0) { io->CR &= (~CMD_WRITE); //clear dma command in CR io->CR |= CMD_NODMA; io->ISR |= ISR_RDC; // remote write finished int if ((ISR_RDC & io->IMR)) { net_rtl8019_set_update_intr (dev); } } DBG_PRINT ("remote write end\n"); return; }}static voidremote_write_byte (struct device_desc *dev, u8 data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; DBG_PRINT ("remote_write begin: data %d\n", data); if (io->CR & CMD_WRITE) { //in remote write mode io->sram[io->remote_write_offset] = data; io->remote_write_offset++; io->remote_write_count--; if (io->remote_write_count == 0) { io->CR &= (~CMD_WRITE); //clear dma command in CR io->CR |= CMD_NODMA; io->ISR |= ISR_RDC; // remote write finished int if ((ISR_RDC & io->IMR)) { net_rtl8019_set_update_intr (dev); } } DBG_PRINT ("remote write end\n"); return; }}static u16remote_read_halfword (struct device_desc *dev){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; u16 data; DBG_PRINT ("remote read begin\n"); if (io->CR & CMD_READ) { data = io->sram[io->remote_read_offset]; data |= io->sram[io->remote_read_offset + 1] << 8; io->remote_read_offset += 2; io->remote_read_count -= 2; if (io->remote_read_count <= 0) { io->CR &= (~CMD_READ); io->CR |= CMD_NODMA; io->ISR |= ISR_RDC; if ((ISR_RDC & io->IMR)) { net_rtl8019_set_update_intr (dev); } } DBG_PRINT ("remote read end:data %d\n", data); return data; }}static u8remote_read_byte (struct device_desc *dev){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; u8 data; DBG_PRINT ("remote read begin\n"); if (io->CR & CMD_READ) { data = io->sram[io->remote_read_offset]; io->remote_read_offset++; if (--io->remote_read_count == 0) { io->CR &= (~CMD_READ); io->CR |= CMD_NODMA; io->ISR |= ISR_RDC; if ((ISR_RDC & io->IMR)) { net_rtl8019_set_update_intr (dev); } } DBG_PRINT ("remote read end:data %d\n", data); return data; }}static voidnet_rtl8019_fini (struct device_desc *dev){ struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; free (dev->dev); free (io);}static voidnet_rtl8019_reset (struct device_desc *dev){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; /*init PROM */ io->PROM[0] = (u8) net_dev->macaddr[0]; //MACADDR0; io->PROM[1] = (u8) net_dev->macaddr[0]; //MACADDR0; io->PROM[2] = (u8) net_dev->macaddr[1]; //MACADDR1; io->PROM[3] = (u8) net_dev->macaddr[1]; //MACADDR1; io->PROM[4] = (u8) net_dev->macaddr[2]; //MACADDR2; io->PROM[5] = (u8) net_dev->macaddr[2]; //MACADDR2; io->PROM[6] = (u8) net_dev->macaddr[3]; //MACADDR3; io->PROM[7] = (u8) net_dev->macaddr[3]; //MACADDR3; io->PROM[8] = (u8) net_dev->macaddr[4]; //MACADDR4; io->PROM[9] = (u8) net_dev->macaddr[4]; //MACADDR4; io->PROM[10] = (u8) net_dev->macaddr[5]; //MACADDR5; io->PROM[11] = (u8) net_dev->macaddr[5]; //MACADDR5; io->PAR0 = io->PROM[0]; io->PAR1 = io->PROM[2]; io->PAR2 = io->PROM[4]; io->PAR3 = io->PROM[6]; io->PAR4 = io->PROM[8]; io->PAR5 = io->PROM[10]; //init Registers io->CR = 0x21; //nic Stopped io->PSTART = 0; io->PSTOP = 0; io->BNRY = 0; io->TPSR = 0; io->TBCR0 = 0; io->TBCR1 = 0; io->ISR = 0; io->RSAR0 = 0; io->RSAR1 = 0; io->RBCR0 = 0; io->RBCR1 = 0; io->RCR = 0; io->TCR = 0; io->DCR = 0x84; //set long addr bit io->IMR = 0; io->CURR = 0; /* raise reset interrupt */ io->ISR = io->ISR | ISR_RST; /* init nic RAM */ if (io->sram != NULL) { memset (io->sram, 0, PAGE_NUM * PAGE_SIZE); } else { io->sram = (u8 *) malloc (PAGE_NUM * PAGE_SIZE); } io->remote_read_offset = 0; io->remote_write_offset = 0; io->remote_read_count = 0; io->remote_write_count = 0; io->need_update = 0;}static voidnet_rtl8019_update (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; struct machine_config *mc = (struct machine_config *) dev->mach; if ((!mc->mach_pending_intr (intr->interrupts[INT_RTL8019]))) {//koodailar modify it for mingw 2005.12.18--------------------------------------#ifdef __MINGW32__ //whenever possible, update it rtl8019_input (dev);#else fd_set frds; struct timeval tv; int ret; FD_ZERO (&frds); FD_SET (net_dev->net_fd, &frds); tv.tv_sec = 0; tv.tv_usec = 0; if ((ret = select (net_dev->net_fd + 1, &frds, NULL, NULL, &tv)) > 0) { if (FD_ISSET (net_dev->net_fd, &frds)) { rtl8019_input (dev); } }#endif//end koodailar ---------------------------------------------------------------- }}static intnet_rtl8019_read_halfword (struct device_desc *dev, u32 addr, u16 * data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; int offset = (u8) (addr - dev->base); int ret = ADDR_HIT; //DBG_PRINT("nic read begin: offset %x, io->ISR %x\n",offset,io->ISR); if (offset == 0x10) { //remote read if (io->DCR & 0x1) { *data = remote_read_halfword (dev); } }}static intnet_rtl8019_read_byte (struct device_desc *dev, u32 addr, u8 * data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_rtl8019_io *io = (struct net_rtl8019_io *) dev->data; int offset = (u8) (addr - dev->base); int ret = ADDR_HIT; DBG_PRINT ("nic read begin: offset %x, io->ISR %x\n", offset, io->ISR); *data = 0; if (offset == 0x10) { //remote read /* FIXME: don't use DCR here. */ *data = remote_read_byte (dev); return ret; } if (offset == 0x1f) { //reset net_rtl8019_reset (dev); return ret; } if ((io->CR >> 6) == 0) { //read page0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -