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

📄 dp8390.c

📁 minix3的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * dp8390.c * * This file contains a ethernet device driver for NS dp8390 based ethernet * cards. * * The valid messages and their parameters are: * *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR * |------------+----------+---------+----------+---------+---------| * | HARDINT	|          |         |          |         |         | * |------------|----------|---------|----------|---------|---------| * | DL_WRITE	| port nr  | proc nr | count    | mode    | address | * |------------|----------|---------|----------|---------|---------| * | DL_WRITEV	| port nr  | proc nr | count    | mode    | address | * |------------|----------|---------|----------|---------|---------| * | DL_READ	| port nr  | proc nr | count    |         | address | * |------------|----------|---------|----------|---------|---------| * | DL_READV	| port nr  | proc nr | count    |         | address | * |------------|----------|---------|----------|---------|---------| * | DL_INIT	| port nr  | proc nr | mode     |         | address | * |------------|----------|---------|----------|---------|---------| * | DL_GETSTAT	| port nr  | proc nr |          |         | address | * |------------|----------|---------|----------|---------|---------| * | DL_STOP	| port_nr  |         |          |         |	    | * |------------|----------|---------|----------|---------|---------| * * The messages sent are: * *   m-type	   DL_PORT    DL_PROC   DL_COUNT   DL_STAT   DL_CLCK * |-------------+----------+---------+----------+---------+---------| * |DL_TASK_REPLY| port nr  | proc nr | rd-count | err|stat| clock   | * |-------------+----------+---------+----------+---------+---------| * *   m_type	   m3_i1     m3_i2       m3_ca1 * |-------------+---------+-----------+---------------| * |DL_INIT_REPLY| port nr | last port | ethernet addr | * |-------------+---------+-----------+---------------| * * Created:	before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com> * * Modified Mar 10 1994 by Philip Homburg *	Become a generic dp8390 driver. * * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de> *	Added support for 3c503 boards. */#include "../drivers.h"#include <stdlib.h>#include <minix/com.h>#include <net/hton.h>#include <net/gen/ether.h>#include <net/gen/eth_io.h>#include "assert.h"#include "local.h"#include "dp8390.h"#define DE_PORT_NR	3static dpeth_t de_table[DE_PORT_NR];static u16_t eth_ign_proto;static char *progname;/* Configuration */typedef struct dp_conf{	port_t dpc_port;	int dpc_irq;	phys_bytes dpc_mem;	char *dpc_envvar;} dp_conf_t;dp_conf_t dp_conf[]=	/* Card addresses */{	/* I/O port, IRQ,  Buffer address,  Env. var. */	{  0x280,     3,    0xD0000,        "DPETH0"	},	{  0x300,     5,    0xC8000,        "DPETH1"	},	{  0x380,    10,    0xD8000,        "DPETH2"	},};/* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see * the error: "array size is negative". */extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];/* Card inits configured out? */#if !ENABLE_WDETH#define wdeth_probe(dep)	(0)#endif#if !ENABLE_NE2000#define ne_probe(dep)		(0)#endif#if !ENABLE_3C503#define el2_probe(dep)		(0)#endif/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA * on writes to the CR register. Additional CR_STAs do not appear to hurt * genuine dp8390s */#define CR_EXTRA	CR_STA#if ENABLE_PCI_PROTOTYPE( static void pci_conf, (void)				);#endif_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,							int vectored)	);_PROTOTYPE( static void do_vread, (message *mp, int vectored)		);_PROTOTYPE( static void do_init, (message *mp)				);_PROTOTYPE( static void do_int, (dpeth_t *dep)				);_PROTOTYPE( static void do_getstat, (message *mp)			);_PROTOTYPE( static void do_getname, (message *mp)			);_PROTOTYPE( static void do_stop, (message *mp)				);_PROTOTYPE( static void dp_init, (dpeth_t *dep)				);_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)			);_PROTOTYPE( static void dp_reinit, (dpeth_t *dep)			);_PROTOTYPE( static void dp_reset, (dpeth_t *dep)			);_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)			);_PROTOTYPE( static void dp_recv, (dpeth_t *dep)				);_PROTOTYPE( static void dp_send, (dpeth_t *dep)				);_PROTOTYPE( static void dp8390_stop, (void)				);_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,				size_t offset, size_t size, void *dst)	);_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,				size_t offset, size_t size, void *dst)	);_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,				size_t offset, size_t size, void *dst)	);_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,							int length)	);_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 		vir_bytes offset, int nic_addr, vir_bytes count)	);_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,				iovec_dat_t *iovp, vir_bytes offset,				int nic_addr, vir_bytes count)		);_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,				iovec_dat_t *iovp, vir_bytes offset,				int nic_addr, vir_bytes count)		);_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, 		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)		);_PROTOTYPE( static void conf_hw, (dpeth_t *dep)				);_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)	);_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)		);_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)	);_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);_PROTOTYPE( static void get_userdata, (int user_proc,		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);_PROTOTYPE( static void put_userdata, (int user_proc,		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)				);_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)				);_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,					vir_bytes buf, size_t size)	);_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,					vir_bytes buf, size_t size)	);_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,					vir_bytes buf, size_t size)	);_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,					vir_bytes buf, size_t size)	);/*===========================================================================* *				dpeth_task				     * *===========================================================================*/int main(int argc, char *argv[]){	message m;	int i, irq, r, tasknr;	dpeth_t *dep;	long v;	if (argc < 1)	{		panic("DP8390",			"A head which at this time has no name", NO_NUM);	}	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);	env_setargs(argc, argv);	for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)	{		strcpy(dep->de_name, "dp8390#0");		dep->de_name[7] += i;	}	v= 0;	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);	eth_ign_proto= htons((u16_t) v);	/* Try to notify inet that we are present (again) */	r = findproc("inet", &tasknr);	if (r == OK)		notify(tasknr);	while (TRUE)	{		if ((r= receive(ANY, &m)) != OK)			panic("", "dp8390: receive failed", r);		switch (m.m_type)		{		case DEV_PING:  notify(m.m_source);		continue;		case DL_WRITE:	do_vwrite(&m, FALSE, FALSE);	break;		case DL_WRITEV:	do_vwrite(&m, FALSE, TRUE);	break;		case DL_READ:	do_vread(&m, FALSE);		break;		case DL_READV:	do_vread(&m, TRUE);		break;		case DL_INIT:	do_init(&m);			break;		case DL_GETSTAT: do_getstat(&m);		break;		case DL_GETNAME: do_getname(&m); 		break;		case DL_STOP:	do_stop(&m);			break;		case HARD_INT:			for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)			{				if (dep->de_mode != DEM_ENABLED)					continue;				assert(dep->de_flags & DEF_ENABLED);				irq= dep->de_irq;				assert(irq >= 0 && irq < NR_IRQ_VECTORS);				if (dep->de_int_pending || 1)				{					dep->de_int_pending= 0;					dp_check_ints(dep);					do_int(dep);					r= sys_irqenable(&dep->de_hook);					if (r != OK)					{						panic("DP8390", 						"unable enable interrupts", r);					}				}			}			break;		case SYS_SIG:	{			sigset_t sigset = m.NOTIFY_ARG;			if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();			break;		}		case SYN_ALARM:			printf("dp8390: strange, got SYN_ALARM\n");			break;		default:			panic("", "dp8390: illegal message", m.m_type);		}	}}#if 0/*===========================================================================* *				dp8390_dump				     * *===========================================================================*/void dp8390_dump(){	dpeth_t *dep;	int i, isr;	printf("\n");	for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)	{#if XXX		if (dep->de_mode == DEM_DISABLED)			printf("dp8390 port %d is disabled\n", i);		else if (dep->de_mode == DEM_SINK)			printf("dp8390 port %d is in sink mode\n", i);#endif		if (dep->de_mode != DEM_ENABLED)			continue;		printf("dp8390 statistics of port %d:\n", i);		printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);		printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);		printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);		printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);		printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);		printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);		printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);		printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);		printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);		printf("collision  :%8ld\t", dep->de_stat.ets_collision);		printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);		printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);		printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);		printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);		printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);		printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);		isr= inb_reg0(dep, DP_ISR);		printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,					inb_reg0(dep, DP_ISR), dep->de_flags);	}}#endif/*===========================================================================* *				dp8390_stop				     * *===========================================================================*/static void dp8390_stop(){	message mess;	int i;	for (i= 0; i<DE_PORT_NR; i++)	{		if (de_table[i].de_mode != DEM_ENABLED)			continue;		mess.m_type= DL_STOP;		mess.DL_PORT= i;		do_stop(&mess);	}}#if ENABLE_PCI/*===========================================================================* *				pci_conf				     * *===========================================================================*/static void pci_conf(){	int i, h;	char *envvar;	struct dpeth *dep;	static char envfmt[] = "*:d.d.d";	long v;	static int first_time= 1;	if (!first_time)		return;	first_time= 0;	for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)	{		envvar= dp_conf[i].dpc_envvar;		if (!(dep->de_pci= env_prefix(envvar, "pci")))			continue;	/* no PCI config */		v= 0;		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);		dep->de_pcibus= v;		v= 0;		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);		dep->de_pcidev= v;		v= 0;		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);		dep->de_pcifunc= v;	}	for (h= 1; h >= 0; h--) {		for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)		{			if (!dep->de_pci)				continue;			if (((dep->de_pcibus | dep->de_pcidev |				dep->de_pcifunc) != 0) != h)			{				continue;			}			if (!rtl_probe(dep))				dep->de_pci= -1;		}	}}#endif /* ENABLE_PCI *//*===========================================================================* *				do_vwrite				     * *===========================================================================*/static void do_vwrite(mp, from_int, vectored)message *mp;int from_int;int vectored;{	int port, count, size;	int sendq_head;	dpeth_t *dep;	port = mp->DL_PORT;	count = mp->DL_COUNT;	if (port < 0 || port >= DE_PORT_NR)		panic("", "dp8390: illegal port", port);	dep= &de_table[port];	dep->de_client= mp->DL_PROC;	if (dep->de_mode == DEM_SINK)	{		assert(!from_int);		dep->de_flags |= DEF_PACK_SEND;		reply(dep, OK, FALSE);		return;	}	assert(dep->de_mode == DEM_ENABLED);	assert(dep->de_flags & DEF_ENABLED);	if (dep->de_flags & DEF_SEND_AVAIL)		panic("", "dp8390: send already in progress", NO_NUM);	sendq_head= dep->de_sendq_head;	if (dep->de_sendq[sendq_head].sq_filled)	{		if (from_int)			panic("", "dp8390: should not be sending\n", NO_NUM);		dep->de_sendmsg= *mp;		dep->de_flags |= DEF_SEND_AVAIL;		reply(dep, OK, FALSE);		return;	}	assert(!(dep->de_flags & DEF_PACK_SEND));	if (vectored)	{		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,			(count > IOVEC_NR ? IOVEC_NR : count) *			sizeof(iovec_t), dep->de_write_iovec.iod_iovec);		dep->de_write_iovec.iod_iovec_s = count;		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;		dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;		dep->de_tmp_iovec = dep->de_write_iovec;		size = calc_iovec_size(&dep->de_tmp_iovec);	}	else	{  		dep->de_write_iovec.iod_iovec[0].iov_addr =			(vir_bytes) mp->DL_ADDR;		dep->de_write_iovec.iod_iovec[0].iov_size =			mp->DL_COUNT;		dep->de_write_iovec.iod_iovec_s = 1;		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;		dep->de_write_iovec.iod_iovec_addr = 0;		size= mp->DL_COUNT;	}	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)	{		panic("", "dp8390: invalid packet size", size);	}	(dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,		dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,		size);	dep->de_sendq[sendq_head].sq_filled= TRUE;	if (dep->de_sendq_tail == sendq_head)	{		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);		outb_reg0(dep, DP_TBCR1, size >> 8);		outb_reg0(dep, DP_TBCR0, size & 0xff);		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */	}	else		dep->de_sendq[sendq_head].sq_size= size;		if (++sendq_head == dep->de_sendq_nr)		sendq_head= 0;	assert(sendq_head < SENDQ_NR);	dep->de_sendq_head= sendq_head;	dep->de_flags |= DEF_PACK_SEND;	/* If the interrupt handler called, don't send a reply. The reply	 * will be sent after all interrupts are handled. 	 */	if (from_int)		return;	reply(dep, OK, FALSE);	assert(dep->de_mode == DEM_ENABLED);	assert(dep->de_flags & DEF_ENABLED);}/*===========================================================================* *				do_vread				     * *===========================================================================*/static void do_vread(mp, vectored)message *mp;int vectored;{	int port, count;	int size;	dpeth_t *dep;	port = mp->DL_PORT;	count = mp->DL_COUNT;	if (port < 0 || port >= DE_PORT_NR)		panic("", "dp8390: illegal port", port);	dep= &de_table[port];	dep->de_client= mp->DL_PROC;	if (dep->de_mode == DEM_SINK)	{		reply(dep, OK, FALSE);

⌨️ 快捷键说明

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