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

📄 fxp.c

📁 minix3.1.1源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * fxp.c * * This file contains an ethernet device driver for Intel 82557, 82558,  * 82559, 82550, and 82562 fast ethernet controllers. * * 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:	Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com> */#include "../drivers.h"#include <stdlib.h>#include <net/hton.h>#include <net/gen/ether.h>#include <net/gen/eth_io.h>#include <timers.h>#define tmra_ut			timer_t#define tmra_inittimer(tp)	tmr_inittimer(tp)#define Proc_number(p)		proc_number(p)#define debug			0#define RAND_UPDATE		/**/#define printW()		((void)0)#define vm_1phys2bus(p)		(p)#include "assert.h"#include "../libpci/pci.h"#include "fxp.h"#include "mii.h"/* Number of receive buffers */#define N_RX_BUF	40/* Number of transmit buffers */#define N_TX_BUF	4/* I/O vectors are handled IOVEC_NR entries at a time. */#define IOVEC_NR	16/* Configuration */#define FXP_ENVVAR	"FXPETH"struct pcitab{	u16_t vid;	u16_t did;	int checkclass;};PRIVATE struct pcitab pcitab_fxp[]={	{ 0x8086, 0x1229, 0 },		/* Intel 82557, etc. */	{ 0x8086, 0x2449, 0 },		/* Intel 82801BA/BAM/CA/CAM */	{ 0x0000, 0x0000, 0 }};#define FXP_PORT_NR	1		/* Minix */typedef int irq_hook_t;/* Translate a pointer to a field in a structure to a pointer to the structure * itself.  So it translates '&struct_ptr->field' back to 'struct_ptr'. */#define structof(type, field, ptr) \	((type *) (((char *) (ptr)) - offsetof(type, field)))#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)static timer_t *fxp_timers= NULL;static clock_t fxp_next_timeout= 0;static void micro_delay(unsigned long usecs);/* ignore interrupt for the moment */#define interrupt(x)	0char buffer[70*1024];typedef struct fxp{	port_t fxp_base_port;	int fxp_mode;	int fxp_got_int;	int fxp_send_int;	int fxp_flags;	int fxp_client;	int fxp_features;		/* Needed? */	int fxp_irq;	int fxp_type;			/* What kind of hardware */	int fxp_ee_addrlen;		/* #EEPROM address bits */	int fxp_tx_alive;	int fxp_need_reset;	/* Rx */	vir_bytes fxp_read_s;	int fxp_rx_nbuf;	int fxp_rx_bufsize;	struct rfd *fxp_rx_buf;	phys_bytes fxp_rx_busaddr;	int fxp_rx_head;	int fxp_rx_need_restart;	int fxp_need_conf;		/* Re-configure after draining send					 * queue					 */	/* Tx */	int fxp_tx_nbuf;	int fxp_tx_bufsize;	struct tx *fxp_tx_buf;	phys_bytes fxp_tx_busaddr;	int fxp_tx_idle;	int fxp_tx_head;	int fxp_tx_tail;	int fxp_tx_threshold;	/* Link status */	int fxp_report_link;	int fxp_link_up;	int fxp_mii_busy;	u16_t fxp_mii_scr;	/* PCI related */	int fxp_seen;			/* TRUE iff device available */	u8_t fxp_pcibus;		u8_t fxp_pcidev;		u8_t fxp_pcifunc;		/* 'large' items */	irq_hook_t fxp_hook;	ether_addr_t fxp_address;	message fxp_rx_mess;	message fxp_tx_mess;	struct sc fxp_stat;	u8_t fxp_conf_bytes[CC_BYTES_NR];	char fxp_name[sizeof("fxp#n")];	iovec_t fxp_iovec[IOVEC_NR];}fxp_t;/* fxp_mode */#define FM_DISABLED	0x0#define FM_ENABLED	0x1/* fxp_flags */#define FF_EMPTY	0x000#define FF_PACK_SENT	0x001#define FF_PACK_RECV	0x002#define FF_SEND_AVAIL	0x004#define FF_READING	0x010#define FF_PROMISC	0x040#define FF_MULTI	0x080#define FF_BROAD	0x100#define FF_ENABLED	0x200/* fxp_features */#define FFE_NONE	0x0/* fxp_type */#define FT_UNKNOWN	0x0#define FT_82557	0x1#define FT_82558A	0x2#define FT_82559	0x4static fxp_t fxp_table[FXP_PORT_NR];static int fxp_tasknr= ANY;static u16_t eth_ign_proto;static tmra_ut fxp_watchdog;static char *progname;extern int errno;#define fxp_inb(port, offset)	(do_inb((port) + (offset)))#define fxp_inw(port, offset)	(do_inw((port) + (offset)))#define fxp_inl(port, offset)	(do_inl((port) + (offset)))#define fxp_outb(port, offset, value)	(do_outb((port) + (offset), (value)))#define fxp_outw(port, offset, value)	(do_outw((port) + (offset), (value)))#define fxp_outl(port, offset, value)	(do_outl((port) + (offset), (value)))_PROTOTYPE( static void fxp_init, (message *mp)				);_PROTOTYPE( static void fxp_pci_conf, (void)				);_PROTOTYPE( static int fxp_probe, (fxp_t *fp)				);_PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp)			);_PROTOTYPE( static void fxp_init_hw, (fxp_t *fp)			);_PROTOTYPE( static void fxp_init_buf, (fxp_t *fp)			);_PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp)			);_PROTOTYPE( static void fxp_confaddr, (fxp_t *fp)			);_PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp)			);_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,							int vectored)	);_PROTOTYPE( static void fxp_readv, (message *mp, int from_int, 							int vectored)	);_PROTOTYPE( static void fxp_do_conf, (fxp_t *fp)			);_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,				phys_bytes bus_addr, int check_idle)	);_PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,				phys_bytes bus_addr, int check_idle)	);_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp)			);_PROTOTYPE( static void fxp_getstat, (message *mp)			);_PROTOTYPE( static void fxp_getname, (message *mp)			);_PROTOTYPE( static int fxp_handler, (fxp_t *fp)				);_PROTOTYPE( static void fxp_check_ints, (fxp_t *fp)			);_PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp)			);_PROTOTYPE( static int fxp_link_changed, (fxp_t *fp)			);_PROTOTYPE( static void fxp_report_link, (fxp_t *fp)			);_PROTOTYPE( static void fxp_stop, (void));_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block)	);_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);_PROTOTYPE( static void put_userdata, (int user_proc,		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);_PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg)		);_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp)			);_PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg)			);_PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,						tmr_func_t watchdog)	);_PROTOTYPE( static void fxp_expire_timers,(void)			);_PROTOTYPE( static u8_t do_inb, (port_t port)				);_PROTOTYPE( static u32_t do_inl, (port_t port)				);_PROTOTYPE( static void do_outb, (port_t port, u8_t v)			);_PROTOTYPE( static void do_outl, (port_t port, u32_t v)			);/*===========================================================================* *				main					     * *===========================================================================*/int main(int argc, char *argv[]){	message m;	int i, r, tasknr;	fxp_t *fp;	long v;	if ((fxp_tasknr= getprocnr())<0)		panic("FXP", "couldn't get proc nr", errno);	if (argc < 1)		panic("FXP", "A head which at this time has no name", NO_NUM);	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);	v= 0;#if 0	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);#endif	eth_ign_proto= htons((u16_t) v);#if 0	/* What about memory allocation? */	/* Claim buffer memory now under Minix, before MM takes it all. */	for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)		fxp_init_buf(fp);#endif	/* 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("FXP","receive failed", r);		switch (m.m_type)		{		case DEV_PING:  notify(m.m_source);		continue;		case DL_WRITEV:	fxp_writev(&m, FALSE, TRUE);	break;		case DL_WRITE:	fxp_writev(&m, FALSE, FALSE);	break;#if 0		case DL_READ:	fxp_vread(&m, FALSE);		break;#endif		case DL_READV:	fxp_readv(&m, FALSE, TRUE);	break;		case DL_INIT:	fxp_init(&m);			break;		case DL_GETSTAT: fxp_getstat(&m);		break;		case DL_GETNAME: fxp_getname(&m); 		break;		case HARD_INT:			for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)			{				if (fp->fxp_mode != FM_ENABLED)					continue;				fxp_handler(fp);				r= sys_irqenable(&fp->fxp_hook);				if (r != OK)					panic("FXP","unable enable interrupts", r);				if (!fp->fxp_got_int)					continue;				fp->fxp_got_int= 0;				assert(fp->fxp_flags & FF_ENABLED);				fxp_check_ints(fp);			}			break;		case SYS_SIG:	{			sigset_t sigset = m.NOTIFY_ARG;			if (sigismember(&sigset, SIGKSTOP)) fxp_stop();			break;		}		case SYN_ALARM:	fxp_expire_timers();		break;		default:			panic("FXP"," illegal message", m.m_type);		}	}}/*===========================================================================* *				fxp_init				     * *===========================================================================*/static void fxp_init(mp)message *mp;{	static int first_time= 1;	int port;	fxp_t *fp;	message reply_mess;	if (first_time)	{		first_time= 0;		fxp_pci_conf(); /* Configure PCI devices. */		tmra_inittimer(&fxp_watchdog);		tmr_arg(&fxp_watchdog)->ta_int= 0;		fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);	}	port = mp->DL_PORT;	if (port < 0 || port >= FXP_PORT_NR)	{		reply_mess.m_type= DL_INIT_REPLY;		reply_mess.m3_i1= ENXIO;		mess_reply(mp, &reply_mess);		return;	}	fp= &fxp_table[port];	if (fp->fxp_mode == FM_DISABLED)	{		/* This is the default, try to (re)locate the device. */		fxp_conf_hw(fp);		if (fp->fxp_mode == FM_DISABLED)		{			/* Probe failed, or the device is configured off. */			reply_mess.m_type= DL_INIT_REPLY;			reply_mess.m3_i1= ENXIO;			mess_reply(mp, &reply_mess);			return;		}		if (fp->fxp_mode == FM_ENABLED)			fxp_init_hw(fp);		fxp_report_link(fp);	}	assert(fp->fxp_mode == FM_ENABLED);	assert(fp->fxp_flags & FF_ENABLED);	fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);	if (mp->DL_MODE & DL_PROMISC_REQ)		fp->fxp_flags |= FF_PROMISC;	if (mp->DL_MODE & DL_MULTI_REQ)		fp->fxp_flags |= FF_MULTI;	if (mp->DL_MODE & DL_BROAD_REQ)		fp->fxp_flags |= FF_BROAD;	fp->fxp_client = mp->m_source;	fxp_rec_mode(fp);	reply_mess.m_type = DL_INIT_REPLY;	reply_mess.m3_i1 = mp->DL_PORT;	reply_mess.m3_i2 = FXP_PORT_NR;	*(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;	mess_reply(mp, &reply_mess);}/*===========================================================================* *				fxp_pci_conf				     * *===========================================================================*/static void fxp_pci_conf(){	static char envvar[] = FXP_ENVVAR "#";	static char envfmt[] = "*:d.d.d";	int i, h;	fxp_t *fp;	long v;	for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)	{		strcpy(fp->fxp_name, "fxp#0");		fp->fxp_name[4] += i;		fp->fxp_seen= FALSE;		fp->fxp_features= FFE_NONE;		envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;#if 0		if (getenv(envvar) != NULL)		{			if (strcmp(getenv(envvar), "off") == 0)			{				fp->fxp_pcibus= 255;				continue;			}			if (!env_prefix(envvar, "pci"))				env_panic(envvar);		}#endif		v= 0;#if 0		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);#endif		fp->fxp_pcibus= v;		v= 0;#if 0		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);#endif		fp->fxp_pcidev= v;		v= 0;#if 0		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);#endif		fp->fxp_pcifunc= v;	}	pci_init();	for (h= 1; h >= 0; h--) {		for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)		{			if (fp->fxp_pcibus == 255)				continue;			if (((fp->fxp_pcibus | fp->fxp_pcidev |				fp->fxp_pcifunc) != 0) != h)			{				continue;			}			if (fxp_probe(fp))				fp->fxp_seen= TRUE;		}	}}/*===========================================================================* *				fxp_probe				     * *===========================================================================*/static int fxp_probe(fp)fxp_t *fp;{	int i, r, devind, just_one;	u16_t vid, did;	u32_t bar;	u8_t ilr, rev;	char *dname, *str;	if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)	{		/* Look for specific PCI device */		r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,			fp->fxp_pcifunc, &devind);		if (r == 0)		{			printf("%s: no PCI device found at %d.%d.%d\n",				fp->fxp_name, fp->fxp_pcibus,				fp->fxp_pcidev, fp->fxp_pcifunc);			return FALSE;		}		pci_ids(devind, &vid, &did);		just_one= TRUE;	}	else	{		r= pci_first_dev(&devind, &vid, &did);		if (r == 0)			return FALSE;		just_one= FALSE;	}	for(;;)	{		for (i= 0; pcitab_fxp[i].vid != 0; i++)		{			if (pcitab_fxp[i].vid != vid)				continue;			if (pcitab_fxp[i].did != did)				continue;			if (pcitab_fxp[i].checkclass)			{				panic("FXP","fxp_probe: class check not implemented",					NO_NUM);			}			break;		}		if (pcitab_fxp[i].vid != 0)			break;		if (just_one)		{			printf(		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",				fp->fxp_name, vid, did,				fp->fxp_pcibus,				fp->fxp_pcidev, fp->fxp_pcifunc);			return FALSE;		}		r= pci_next_dev(&devind, &vid, &did);		if (!r)			return FALSE;	}	dname= pci_dev_name(vid, did);#if VERBOSE	if (!dname)		dname= "unknown device";	printf("%s: %s (%04x/%04x) at %s\n",		fp->fxp_name, dname, vid, did, pci_slot_name(devind));#endif	pci_reserve(devind);	bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;	if ((bar & 0x3ff) >= 0x100-32 || bar < 0x400)	{		panic("FXP","fxp_probe: base address is not properly configured",			NO_NUM);	}	fp->fxp_base_port= bar;	ilr= pci_attr_r8(devind, PCI_ILR);	fp->fxp_irq= ilr;	if (debug)	{		printf("%s: using I/O address 0x%lx, IRQ %d\n",			fp->fxp_name, (unsigned long)bar, ilr);	}	rev= pci_attr_r8(devind, PCI_REV);	str= NULL;	fp->fxp_type= FT_UNKNOWN;	switch(rev)	{	case FXP_REV_82557A:	str= "82557A";			/* 0x01 */				fp->fxp_type= FT_82557;				break;	case FXP_REV_82557B:	str= "82557B"; break;		/* 0x02 */	case FXP_REV_82557C:	str= "82557C"; break;		/* 0x03 */	case FXP_REV_82558A:	str= "82558A"; 			/* 0x04 */				fp->fxp_type= FT_82558A;				break;	case FXP_REV_82558B:	str= "82558B"; break;		/* 0x05 */	case FXP_REV_82559A:	str= "82559A"; break;		/* 0x06 */	case FXP_REV_82559B:	str= "82559B"; break;		/* 0x07 */	case FXP_REV_82559C:	str= "82559C";			/* 0x08 */				fp->fxp_type= FT_82559;				break;	case FXP_REV_82559ERA:	str= "82559ER-A"; break;	/* 0x09 */	case FXP_REV_82550_1:	str= "82550(1)"; break;		/* 0x0C */	case FXP_REV_82550_2:	str= "82550(2)"; break;		/* 0x0D */	case FXP_REV_82550_3:	str= "82550(3)"; break;		/* 0x0E */	case FXP_REV_82551_1:	str= "82551(1)"; break;		/* 0x0F */	case FXP_REV_82551_2:	str= "82551(2)"; break;		/* 0x10 */	}#if VERBOSE	if (str)		printf("%s: device revision: %s\n", fp->fxp_name, str);	else		printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);#endif	if (fp->fxp_type == FT_UNKNOWN)	{		printf("fxp_probe: device is not supported by this driver\n");		return FALSE;	}	return TRUE;}/*===========================================================================* *				fxp_conf_hw				     * *===========================================================================*/static void fxp_conf_hw(fp)fxp_t *fp;{	int i;	int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;	fp->fxp_mode= FM_DISABLED;	/* Superfluous */	if (!fp->fxp_seen)

⌨️ 快捷键说明

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