📄 dev_net_s3c4510b.c
字号:
//zzc: 2005-2-6 currently not support network simulation on Cygwin#ifndef __CYGWIN__/* dev_net_s3c4510b.c - skyeye S3C4510B 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 *//* * 06/17/2005 initial verion for s3c4510b * walimis <wlm@student.dlut.edu.cn> */#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_s3c4510b.h"static struct device_default_value s3c4510b_net_def[] = { /* name base size interrupt array */ {"s3c4510b", 0x3FF9000, 0x2000, {16, 17, 18, 19}}, {NULL},};#define MAX_DEVICE_NUM 10static struct device_desc *s3c4510b_devs[MAX_DEVICE_NUM];#if 0voidnet_s3c4510b_set_update_intr (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct machine_config *mc = (struct machine_config *) dev->mach; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; mc->mach_set_intr (intr->interrupts[INT_S3C4510B]); mc->mach_update_intr (mc);}inline voidset_time (int packets){ 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);}static voidsend_interrupt (){ int i; struct device_desc *dev; for (i = 0; i < MAX_DEVICE_NUM; i++) { if ((dev = s3c4510b_devs[i]) != NULL) { struct net_device *net_dev = (struct net_device *) dev->dev; struct machine_config *mc = (struct machine_config *) dev->mach; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; if ((io->need_update)) { /* only update once. */ net_s3c4510b_set_update_intr (dev); io->need_update = 0; set_time (0); return; } } }}static voidinit_sigaction (void){ struct sigaction act; act.sa_handler = send_interrupt; act.sa_flags = 0; sigemptyset (&act.sa_mask); sigaction (SIGALRM, &act, NULL);}#endifstatic voidmac_write (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; struct machine_config *mc = (struct machine_config *) dev->mach; ARMul_State *state = (ARMul_State *) mc->state; fault_t fault; u32 ptr, status, len; int i; fault = mmu_read_word (state, io->bdmatxptr, &ptr); /* if( fault ) { *addr = io->bdmatxptr; return fault; } */ if (!(ptr & BDMA_owner)) return 0; ptr &= ~BDMA_owner; fault = mmu_read_word (state, io->bdmatxptr + 8, &len); /* if( fault ) { *addr = io->bdmatxptr + 8; return fault; } */ len &= 0xffff; if (len > sizeof (io->mac_buf)) return; for (i = 0; i < len; i++) { fault = mmu_read_byte (state, ptr + i, io->mac_buf + i); /* if( fault ) { *addr = ptr + i; return fault; } */ } //Update TXstatus status = len | (Comp << 16); fault = mmu_write_word (state, io->bdmatxptr + 8, status); //print_packet(io->mac_buf, len); /* if( fault ) { *addr = io->bdmatxptr + 8; return fault; } */ //set owner bit of desc to CPU fault = mmu_write_word (state, io->bdmatxptr, ptr); /* if( fault ) { *addr = io->bdmatxptr; return fault; } */ //get next desc fault = mmu_read_word (state, io->bdmatxptr + 12, &io->bdmatxptr); /* if( fault ) { *addr = io->bdmatxptr + 12; */ net_dev->net_write (net_dev, io->mac_buf, len); //write( skyeye_config.net[0].fd, io->mac_buf, len ); //trigger interrupt if (io->mactxcon & EnComp) { mc->mach_set_intr (intr->interrupts[INT_S3C4510B_MACTX]); mc->mach_update_intr (mc); //s3c4510b_set_interrupt(INT_MACTX); //s3c4510b_update_int(state); } return 0;}static voidmac_read (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; struct machine_config *mc = (struct machine_config *) dev->mach; ARMul_State *state = (ARMul_State *) mc->state; int packet_len, s3c4510b_len; fault_t fault; u32 ptr, status_len; int n, i; //*addr = 0; packet_len = net_dev->net_read (net_dev, io->mac_buf, sizeof (io->mac_buf)); //n = read(skyeye_config.net[0].fd, mac_buf, sizeof(mac_buf)); if (packet_len <= 0) return 0; fault = mmu_read_word (state, io->bdmarxptr, &ptr); //print_packet(io->mac_buf, packet_len); /* if( fault ) { *addr = io->bdmarxptr; return fault; } */ if (!(ptr & BDMA_owner)) return 0; ptr &= ~BDMA_owner; //if( len + 2 > sizeof(mac_buf) ) return 0; /* FIXME:for s3c4510b frame, ptr offset is 2 */ for (i = 0; i < packet_len; i++) { fault = mmu_write_byte (state, ptr + 2 + i, *(io->mac_buf + i)); /* if(fault) { *addr = ptr + 2 + i; return fault; } */ } //in desc, set Good bit for RX status , and set len status_len = (Good << 16) | (packet_len + 4); //printf("status_len:%x\n",status_len); fault = mmu_write_word (state, io->bdmarxptr + 8, status_len); /* if(fault) { *addr = io->bdmarxptr+8; return fault; } */ //set owner bit of desc to CPU fault = mmu_write_word (state, io->bdmarxptr, ptr); /* if(fault) { *addr = io->bdmarxptr; return fault; } */ //get next desc fault = mmu_read_word (state, io->bdmarxptr + 12, &io->bdmarxptr); /* if(fault) { *addr = io->bdmarxptr + 12; return fault; } */ /* update bdmastat register */ io->bdmastat |= S_BRxRDF; mc->mach_set_intr (intr->interrupts[INT_S3C4510B_BDMARX]); mc->mach_update_intr (mc); return 0;}static voidnet_s3c4510b_fini (struct device_desc *dev){ struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; free (dev->dev); free (io);}static voidnet_s3c4510b_reset (struct device_desc *dev){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; int i; io->bdmatxptr = 0xFFFFFFFF; io->bdmarxptr = 0xFFFFFFFF;}static voidnet_s3c4510b_update (struct device_desc *dev){ struct device_interrupt *intr = &dev->intr; struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; struct machine_config *mc = (struct machine_config *) dev->mach; if ((io->bdmarxcon & RxEn)) {//koodailar modify it for mingw 2005.12.18--------------------------------------#ifdef __MINGW32__ //whenever possible, update it mac_read (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)) { mac_read (dev); } }#endif//end koodailar ---------------------------------------------------------------- }}intnet_s3c4510b_read_word (struct device_desc *dev, u32 addr, u32 * data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; int offset = (u16) (addr - dev->base + 0x9000); int ret = ADDR_HIT; //printf("%s:addr %x, %x\n", __FUNCTION__, addr, MACON); *data = 0; switch (offset) { case MACON: *data = io->macon; break; case CAMCON: *data = io->camcon; break; case MACTXCON: *data = io->mactxcon; break; case MACTXSTAT: *data = io->mactxstat; break; case MACRXCON: *data = io->macrxcon; break; case MACRXSTAT: *data = io->macrxstat; break; case STADATA: *data = io->stadata; break; case STACON: *data = io->stacon; break; case CAMEN: *data = io->camen; break; case BDMATXPTR: *data = io->bdmatxptr; break; case BDMARXPTR: *data = io->bdmarxptr; break; case BDMASTAT: *data = io->bdmastat; break; case BDMARXCON: *data = io->bdmarxcon; break; case BDMATXCON: *data = io->bdmatxcon; break; case BDMARXLSZ: *data = io->bdmarxlsz; break; default: break; } return ret;}intnet_s3c4510b_write_word (struct device_desc *dev, u32 addr, u32 data){ struct net_device *net_dev = (struct net_device *) dev->dev; struct net_s3c4510b_io *io = (struct net_s3c4510b_io *) dev->data; int offset = (u16) (addr - dev->base + 0x9000); int ret = ADDR_HIT; //printf("%s\n", __FUNCTION__); switch (offset) { case MACTXCON: if (data & TxEn == TxEn) { /* u32 addr; fault_t fault; fault = mac_write(dev); if( fault ) { mmu_data_abort(state, fault, addr); return; } */ mac_write (dev); } io->mactxcon = data; break; case BDMATXPTR: io->bdmatxptr = data; break; case BDMARXPTR: io->bdmarxptr = data; break; case BDMASTAT: io->bdmastat &= (~data); break; case MACON: io->macon = data; break; case MACRXCON: io->macrxcon = data; break; case BDMARXCON: io->bdmarxcon = data; break; case BDMATXCON: io->bdmatxcon = data; break; case BDMARXLSZ: io->bdmarxlsz = data; break; case CAMEN: io->camen = data; break; default: break; } return ret;}static intnet_s3c4510b_setup (struct device_desc *dev){ int i; int enough = 0; struct net_s3c4510b_io *io; struct device_interrupt *intr = &dev->intr; dev->fini = net_s3c4510b_fini; dev->reset = net_s3c4510b_reset; dev->update = net_s3c4510b_update; dev->read_word = net_s3c4510b_read_word; dev->write_word = net_s3c4510b_write_word; io = (struct net_s3c4510b_io *) malloc (sizeof (struct net_s3c4510b_io)); memset (io, 0, sizeof (struct net_s3c4510b_io)); if (io == NULL) return 1; dev->data = (void *) io; net_s3c4510b_reset (dev); //init_sigaction(); /* see if we need to set default values. * */ set_device_default (dev, s3c4510b_net_def); for (i = 0; i < MAX_DEVICE_NUM; i++) { if (s3c4510b_devs[i] == NULL) { s3c4510b_devs[i] = dev; enough = 1; break; } } if (enough == 0) return 1; return 0;}voidnet_s3c4510b_init (struct device_module_set *mod_set){ int i; register_device_module ("s3c4510b", mod_set, &net_s3c4510b_setup); for (i = 0; i < MAX_DEVICE_NUM; i++) s3c4510b_devs[i] = NULL;}//zzc:#endif __CYGWIN__#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -