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

📄 rtl8139.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 5 页
字号:
	*(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;	mess_reply(mp, &reply_mess);}/*===========================================================================* *				rl_pci_conf				     * *===========================================================================*/static void rl_pci_conf(){	int i, h;	re_t *rep;	static char envvar[] = RL_ENVVAR "#";	static char envfmt[] = "*:d.d.d";	static char val[128];	long v;	for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)	{		strcpy(rep->re_name, "rtl8139#0");		rep->re_name[8] += i;		rep->re_seen= FALSE;		envvar[sizeof(RL_ENVVAR)-1]= '0'+i;		if (0 == env_get_param(envvar, val, sizeof(val)) && 				! env_prefix(envvar, "pci")) {			env_panic(envvar);		}		v= 0;		(void) env_parse(envvar, envfmt, 1, &v, 0, 255);		rep->re_pcibus= v;		v= 0;		(void) env_parse(envvar, envfmt, 2, &v, 0, 255);		rep->re_pcidev= v;		v= 0;		(void) env_parse(envvar, envfmt, 3, &v, 0, 255);		rep->re_pcifunc= v;	}	pci_init();	for (h= 1; h >= 0; h--) {		for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)		{			if (((rep->re_pcibus | rep->re_pcidev |				rep->re_pcifunc) != 0) != h)			{				continue;			}			if (rl_probe(rep))				rep->re_seen= TRUE;		}	}}/*===========================================================================* *				rl_probe				     * *===========================================================================*/static int rl_probe(rep)re_t *rep;{	int i, r, devind, just_one;	u16_t vid, did;	u32_t bar;	u8_t ilr;	char *dname;	if ((rep->re_pcibus | rep->re_pcidev | rep->re_pcifunc) != 0)	{		/* Look for specific PCI device */		r= pci_find_dev(rep->re_pcibus, rep->re_pcidev,			rep->re_pcifunc, &devind);		if (r == 0)		{			printf("%s: no PCI found at %d.%d.%d\n",				rep->re_name, rep->re_pcibus,				rep->re_pcidev, rep->re_pcifunc);			return 0;		}		pci_ids(devind, &vid, &did);		just_one= TRUE;	}	else	{		r= pci_first_dev(&devind, &vid, &did);		if (r == 0)			return 0;		just_one= FALSE;	}	for(;;)	{		for (i= 0; pcitab[i].vid != 0; i++)		{			if (pcitab[i].vid != vid)				continue;			if (pcitab[i].did != did)				continue;			if (pcitab[i].checkclass)			{			  panic("rtl_probe",			    "class check not implemented", NO_NUM);			}			break;		}		if (pcitab[i].vid != 0)			break;		if (just_one)		{			printf(		"%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",				rep->re_name, vid, did,				rep->re_pcibus,				rep->re_pcidev, rep->re_pcifunc);			return 0;		}		r= pci_next_dev(&devind, &vid, &did);		if (!r)			return 0;	}#if VERBOSE	/* stay silent at startup, can always get status later */	dname= pci_dev_name(vid, did);	if (!dname)		dname= "unknown device";	printf("%s: ", rep->re_name);	printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));#endif	pci_reserve(devind);	/* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */	bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;	if ((bar & 0x3ff) >= 0x100-32 || bar < 0x400)	  panic("rtl_probe",	    "base address is not properly configured", NO_NUM);	rep->re_base_port= bar;	ilr= pci_attr_r8(devind, PCI_ILR);	rep->re_irq= ilr;	if (debug)	{		printf("%s: using I/O address 0x%lx, IRQ %d\n",			rep->re_name, (unsigned long)bar, ilr);	}	return TRUE;}/*===========================================================================* *				rl_conf_hw				     * *===========================================================================*/static void rl_conf_hw(rep)re_t *rep;{	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };	rep->re_mode= REM_DISABLED;	/* Superfluous */	if (rep->re_seen)	{		/* PCI device is present */		rep->re_mode= REM_ENABLED;	}	if (rep->re_mode != REM_ENABLED)		return;	rep->re_flags= REF_EMPTY;	rep->re_link_up= -1;	/* Unknown */	rep->re_got_int= 0;	rep->re_send_int= 0;	rep->re_report_link= 0;	rep->re_clear_rx= 0;	rep->re_need_reset= 0;	rep->re_tx_alive= 0;	rep->re_read_s= 0;	rep->re_tx_head= 0;	rep->re_tx_tail= 0;	rep->re_ertxth= RL_TSD_ERTXTH_8;	rep->re_stat= empty_stat;}/*===========================================================================* *				rl_init_buf				     * *===========================================================================*/static void rl_init_buf(rep)re_t *rep;{	size_t rx_bufsize, tx_bufsize, tot_bufsize;	phys_bytes buf;	char *mallocbuf;	static struct memory chunk;	int fd, s, i, off;	/* Allocate receive and transmit buffers */	tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;	if (tx_bufsize % 4)		tx_bufsize += 4-(tx_bufsize % 4);	/* Align */	rx_bufsize= RX_BUFSIZE;	tot_bufsize= N_TX_BUF*tx_bufsize + rx_bufsize;	/* Now try to allocate a kernel memory buffer. */	chunk.size = tot_bufsize;#define BUF_ALIGNMENT (64*1024)	if(!(mallocbuf = malloc(BUF_ALIGNMENT + tot_bufsize))) {	    panic("RTL8139","Couldn't allocate kernel buffer",i);	}	if(OK != (i = sys_umap(SELF, D, (vir_bytes) mallocbuf, tot_bufsize, &buf))) {	    panic("RTL8139","Couldn't re-map malloced buffer",i);	}	/* click-align mallocced buffer. this is what we used to get	 * from kmalloc() too.	 */	if((off = buf % BUF_ALIGNMENT)) {		mallocbuf += BUF_ALIGNMENT - off;		buf += BUF_ALIGNMENT - off;	}	for (i= 0; i<N_TX_BUF; i++)	{		rep->re_tx[i].ret_buf= buf;		rep->re_tx[i].v_ret_buf= mallocbuf;		buf += tx_bufsize;		mallocbuf += tx_bufsize;	}	rep->re_rx_buf= buf;	rep->v_re_rx_buf= mallocbuf;}/*===========================================================================* *				rl_init_hw				     * *===========================================================================*/static void rl_init_hw(rep)re_t *rep;{	int s, i;	rep->re_flags = REF_EMPTY;	rep->re_flags |= REF_ENABLED;	/* Set the interrupt handler. The policy is to only send HARD_INT 	 * notifications. Don't reenable interrupts automatically. The id	 * that is passed back is the interrupt line number.	 */	rep->re_hook_id = rep->re_irq;		if ((s=sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)		printf("RTL8139: error, couldn't set IRQ policy: %d\n", s);	rl_reset_hw(rep);	if ((s=sys_irqenable(&rep->re_hook_id)) != OK)		printf("RTL8139: error, couldn't enable interrupts: %d\n", s);#if VERBOSE	/* stay silent during startup, can always get status later */	if (rep->re_mode) {		printf("%s: model %s\n", rep->re_name, rep->re_model);	} else	{		printf("%s: unknown model 0x%08x\n",			rep->re_name,			rl_inl(rep->re_base_port, RL_TCR) &			(RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));	}#endif	rl_confaddr(rep);	if (debug)	{		printf("%s: Ethernet address ", rep->re_name);		for (i= 0; i < 6; i++)		{			printf("%x%c", rep->re_address.ea_addr[i],				i < 5 ? ':' : '\n');		}	}}/*===========================================================================* *				rl_reset_hw				     * *===========================================================================*/static void rl_reset_hw(rep)re_t *rep;{	port_t port;	u32_t t;	phys_bytes bus_buf;	int i;	clock_t t0,t1;	port= rep->re_base_port;#if 0	/* Reset the PHY */	rl_outb(port, RL_BMCR, MII_CTRL_RST);	getuptime(&t0);	do {		if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))			break;	} while (getuptime(&t1)==OK && (t1-t0) < HZ);	if (rl_inb(port, RL_BMCR) & MII_CTRL_RST)		panic("rtl8139","reset PHY failed to complete", NO_NUM);#endif	/* Reset the device */	rl_outb(port, RL_CR, RL_CR_RST);	getuptime(&t0);	do {		if (!(rl_inb(port, RL_CR) & RL_CR_RST))			break;	} while (getuptime(&t1)==OK && (t1-t0) < HZ);	if (rl_inb(port, RL_CR) & RL_CR_RST)		panic("rtl8139","reset failed to complete", NO_NUM);	t= rl_inl(port, RL_TCR);	switch(t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM))	{	case RL_TCR_HWVER_RTL8139: rep->re_model= "RTL8139"; break;	case RL_TCR_HWVER_RTL8139A: rep->re_model= "RTL8139A"; break;	case RL_TCR_HWVER_RTL8139AG:		rep->re_model= "RTL8139A-G / RTL8139C";		break;	case RL_TCR_HWVER_RTL8139B:		rep->re_model= "RTL8139B / RTL8130";		break;	case RL_TCR_HWVER_RTL8100: rep->re_model= "RTL8100"; break;	case RL_TCR_HWVER_RTL8100B:		rep->re_model= "RTL8100B/RTL8139D";		break;	case RL_TCR_HWVER_RTL8139CP: rep->re_model= "RTL8139C+"; break;	case RL_TCR_HWVER_RTL8101: rep->re_model= "RTL8101"; break;	default:		rep->re_model= NULL;		break;	}#if 0	printf("REVID: 0x%02x\n", rl_inb(port, RL_REVID));#endif	/* Intialize Rx */	/* Should init multicast mask */#if 008-0f	R/W	MAR[0-7]	multicast#endif	bus_buf= vm_1phys2bus(rep->re_rx_buf);	rl_outl(port, RL_RBSTART, bus_buf);	/* Initialize Tx */ 	for (i= 0; i<N_TX_BUF; i++)	{		rep->re_tx[i].ret_busy= FALSE;		bus_buf= vm_1phys2bus(rep->re_tx[i].ret_buf);		rl_outl(port, RL_TSAD0+i*4, bus_buf);		t= rl_inl(port, RL_TSD0+i*4);		assert(t & RL_TSD_OWN);	}#if 0	dump_phy(rep);#endif	t= rl_inw(port, RL_IMR);	rl_outw(port, RL_IMR, t | (RL_IMR_SERR | RL_IMR_TIMEOUT |		RL_IMR_LENCHG));	t= rl_inw(port, RL_IMR);	rl_outw(port, RL_IMR, t | (RL_IMR_FOVW | RL_IMR_PUN |		RL_IMR_RXOVW | RL_IMR_RER | RL_IMR_ROK));	t= rl_inw(port, RL_IMR);	rl_outw(port, RL_IMR, t | (RL_IMR_TER | RL_IMR_TOK));	t= rl_inb(port, RL_CR);	rl_outb(port, RL_CR, t | RL_CR_RE);	t= rl_inb(port, RL_CR);	rl_outb(port, RL_CR, t | RL_CR_TE);	rl_outl(port, RL_RCR, RX_BUFBITS);	t= rl_inl(port, RL_TCR);	rl_outl(port, RL_TCR, t | RL_TCR_IFG_STD);}/*===========================================================================* *				rl_confaddr				     * *===========================================================================*/static void rl_confaddr(rep)re_t *rep;{	static char eakey[]= RL_ENVVAR "#_EA";	static char eafmt[]= "x:x:x:x:x:x";	int i;	port_t port;	u32_t w;	long v;	/* User defined ethernet address? */	eakey[sizeof(RL_ENVVAR)-1]= '0' + (rep-re_table);	port= rep->re_base_port;	for (i= 0; i < 6; i++)	{		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)			break;		rep->re_address.ea_addr[i]= v;	}	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */	/* Should update ethernet address in hardware */	if (i == 6)	{		port= rep->re_base_port;		rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);		w= 0;		for (i= 0; i<4; i++)			w |= (rep->re_address.ea_addr[i] << (i*8));		rl_outl(port, RL_IDR, w);		w= 0;		for (i= 4; i<6; i++)			w |= (rep->re_address.ea_addr[i] << ((i-4)*8));		rl_outl(port, RL_IDR+4, w);		rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);	}	/* Get ethernet address */	for (i= 0; i<6; i++)		rep->re_address.ea_addr[i]= rl_inb(port, RL_IDR+i);}/*===========================================================================* *				rl_rec_mode				     * *===========================================================================*/static void rl_rec_mode(rep)re_t *rep;{	port_t port;	u32_t rcr;	port= rep->re_base_port;	rcr= rl_inl(port, RL_RCR);	rcr &= ~(RL_RCR_AB|RL_RCR_AM|RL_RCR_APM|RL_RCR_AAP);	if (rep->re_flags & REF_PROMISC)		rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;	if (rep->re_flags & REF_BROAD)		rcr |= RL_RCR_AB;	if (rep->re_flags & REF_MULTI)		rcr |= RL_RCR_AM;	rcr |= RL_RCR_APM;	rl_outl(port, RL_RCR, rcr);}/*===========================================================================* *				rl_readv				     * *===========================================================================*/static void rl_readv(mp, from_int, vectored)message *mp;int from_int;int vectored;{	int i, j, n, o, s, s1, dl_port, re_client, count, size;	port_t port;	unsigned amount, totlen, packlen;	phys_bytes src_phys, dst_phys, iov_src;	u16_t d_start, d_end;	u32_t l, rxstat = 0x12345678;	re_t *rep;	iovec_t *iovp;	int cps;	dl_port = mp->DL_PORT;	count = mp->DL_COUNT;	if (dl_port < 0 || dl_port >= RE_PORT_NR)		panic("rtl8139"," illegal port", dl_port);	rep= &re_table[dl_port];	re_client= mp->DL_PROC;	rep->re_client= re_client;	if (rep->re_clear_rx)		goto suspend;	/* Buffer overflow */	assert(rep->re_mode == REM_ENABLED);	assert(rep->re_flags & REF_ENABLED);	port= rep->re_base_port;	/* Assume that the RL_CR_BUFE check was been done by rl_checks_ints	 */	if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))	{		/* Receive buffer is empty, suspend */		goto suspend;	}	d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF;	d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE;	if (d_start >= RX_BUFSIZE)	{		printf("rl_readv: strange value in RL_CAPR: 0x%x\n",			rl_inw(port, RL_CAPR));		d_start %= RX_BUFSIZE;	}	if (d_end > d_start)		amount= d_end-d_start;	else		amount= d_end+RX_BUFSIZE - d_start;	rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);

⌨️ 快捷键说明

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