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

📄 rtl8139.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 5 页
字号:
	t= rl_inw(port, RL_NWAYTR);	printf("NWAYTR: 0x%04lx\n", t);	t= rl_inw(port, RL_CSCR);	printf("CSCR: 0x%04lx\n", t);	t= rl_inb(port, RL_CONFIG5);	printf("CONFIG5: 0x%02lx\n", t);}#endifstatic int do_hard_int(void){	int i,s;	for (i=0; i < RE_PORT_NR; i ++) {		/* Run interrupt handler at driver level. */		rl_handler( &re_table[i]);		/* Reenable interrupts for this hook. */	if ((s=sys_irqenable(&re_table[i].re_hook_id)) != OK)		printf("RTL8139: error, couldn't enable interrupts: %d\n", s);	}}/*===========================================================================* *				rl_handler				     * *===========================================================================*/static int rl_handler(rep)re_t *rep;{	int i, port, tx_head, tx_tail, link_up;	u16_t isr, tsad;	u32_t tsd, tcr, ertxth;#if 0	u8_t cr;#endif	clock_t t0,t1;	int_event_check = FALSE;	/* disable check by default */	port= rep->re_base_port;	/* Ack interrupt */	isr= rl_inw(port, RL_ISR);	rl_outw(port, RL_ISR, isr);	if (isr & RL_IMR_FOVW)	{		isr &= ~RL_IMR_FOVW;		/* Should do anything? */		rep->re_stat.ets_fifoOver++;	}	if (isr & RL_IMR_PUN)	{		isr &= ~RL_IMR_PUN;		/* Either the link status changed or there was a TX fifo		 * underrun.		 */		link_up= !(rl_inb(port, RL_MSR) & RL_MSR_LINKB);		if (link_up != rep->re_link_up)		{			rep->re_report_link= TRUE;			rep->re_got_int= TRUE;			int_event_check = TRUE;		}	}	if (isr & RL_IMR_RXOVW)	{		isr &= ~RL_IMR_RXOVW;		/* Clear the receive buffer */		rep->re_clear_rx= TRUE;		rep->re_got_int= TRUE;		int_event_check = TRUE;	}	if (isr & (RL_ISR_RER | RL_ISR_ROK))	{		isr &= ~(RL_ISR_RER | RL_ISR_ROK);		if (!rep->re_got_int && (rep->re_flags & REF_READING))		{			rep->re_got_int= TRUE;			int_event_check = TRUE;		}	}#if 0	if ((isr & (RL_ISR_TER | RL_ISR_TOK)) &&		(rep->re_flags & REF_SEND_AVAIL) &&		(rep->re_tx[0].ret_busy || rep->re_tx[1].ret_busy ||		rep->re_tx[2].ret_busy || rep->re_tx[3].ret_busy))			{		printf(	"rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",			rep->re_tx_head, rep->re_tx_tail,			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);		printf(	"rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",			rl_inw(port, RL_TSAD),			rl_inl(port, RL_TSD0+0*4),			rl_inl(port, RL_TSD0+1*4),			rl_inl(port, RL_TSD0+2*4),			rl_inl(port, RL_TSD0+3*4));	}#endif	if ((isr & (RL_ISR_TER | RL_ISR_TOK)) || 1)	{		isr &= ~(RL_ISR_TER | RL_ISR_TOK);		tsad= rl_inw(port, RL_TSAD);		if (tsad & (RL_TSAD_TABT0|RL_TSAD_TABT1|			RL_TSAD_TABT2|RL_TSAD_TABT3))		{#if 0			/* Do we need a watch dog? */			/* Just reset the whole chip */			rep->re_need_reset= TRUE;			rep->re_got_int= TRUE;			int_event_check = TRUE;#elif 0			/* Reset transmitter */			rep->re_stat.ets_transAb++;			cr= rl_inb(port, RL_CR);			cr &= ~RL_CR_TE;			rl_outb(port, RL_CR, cr);			getuptime(&t0);			do {				if (!(rl_inb(port, RL_CR) & RL_CR_TE))					break;			} while (getuptime(&t1)==OK && (t1-t0) < HZ);			if (rl_inb(port, RL_CR) & RL_CR_TE)			{			  panic("rtl8139","cannot disable transmitter",					NO_NUM);			}			rl_outb(port, RL_CR, cr | RL_CR_TE);			tcr= rl_inl(port, RL_TCR);			rl_outl(port, RL_TCR, tcr | RL_TCR_IFG_STD);			printf("rl_handler: reset after abort\n");			if (rep->re_flags & REF_SEND_AVAIL)			{				printf("rl_handler: REF_SEND_AVAIL\n");				rep->re_send_int= TRUE;				rep->re_got_int= TRUE;				int_event_check = TRUE;			}			for (i= 0; i< N_TX_BUF; i++)				rep->re_tx[i].ret_busy= FALSE;			rep->re_tx_head= 0;#else			printf("rl_handler, TABT, tasd = 0x%04x\n",				tsad);			/* Find the aborted transmit request */			for (i= 0; i< N_TX_BUF; i++)			{				tsd= rl_inl(port, RL_TSD0+i*4);				if (tsd & RL_TSD_TABT)					break;			}			if (i >= N_TX_BUF)			{				printf(				"rl_handler: can't find aborted TX req.\n");			}			else			{				printf("TSD%d = 0x%04lx\n", i, tsd);				/* Set head and tail to this buffer */				rep->re_tx_head= rep->re_tx_tail= i;			}			/* Aborted transmission, just kick the device			 * and be done with it.			 */			rep->re_stat.ets_transAb++;			tcr= rl_inl(port, RL_TCR);			rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);#endif		}		/* Transmit completed */		tx_head= rep->re_tx_head;		tx_tail= rep->re_tx_tail;		for (i= 0; i< 2*N_TX_BUF; i++)		{			if (!rep->re_tx[tx_tail].ret_busy)			{				/* Strange, this buffer is not in-use.				 * Increment tx_tail until tx_head is				 * reached (or until we find a buffer that				 * is in-use.				 */				if (tx_tail == tx_head)					break;				if (++tx_tail >= N_TX_BUF)					tx_tail= 0;				assert(tx_tail < RL_N_TX);				rep->re_tx_tail= tx_tail;				continue;			}			tsd= rl_inl(port, RL_TSD0+tx_tail*4);			if (!(tsd & RL_TSD_OWN))			{				/* Buffer is not yet ready */				break;			}			/* Should collect statistics */			if (tsd & RL_TSD_CRS)				rep->re_stat.ets_carrSense++;			if (tsd & RL_TSD_TABT)			{				printf("rl_handler, TABT, TSD%d = 0x%04lx\n",					tx_tail, tsd);				assert(0);	/* CLRABT is not all that						 * effective, why not?						 */				rep->re_stat.ets_transAb++;				tcr= rl_inl(port, RL_TCR);				rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);			}			if (tsd & RL_TSD_OWC)				rep->re_stat.ets_OWC++;			if (tsd & RL_TSD_CDH)				rep->re_stat.ets_CDheartbeat++;			/* What about collisions? */			if (tsd & RL_TSD_TOK)				rep->re_stat.ets_packetT++;			else				rep->re_stat.ets_sendErr++;			if (tsd & RL_TSD_TUN)			{				rep->re_stat.ets_fifoUnder++;				/* Increase ERTXTH */				ertxth= tsd + (1 << RL_TSD_ERTXTH_S);				ertxth &= RL_TSD_ERTXTH_M;				if (debug && ertxth > rep->re_ertxth)				{					printf("%s: new ertxth: %ld bytes\n",						rep->re_name,						(ertxth >> RL_TSD_ERTXTH_S) *						32);					rep->re_ertxth= ertxth;				}			}			rep->re_tx[tx_tail].ret_busy= FALSE;#if 0			if (rep->re_flags & REF_SEND_AVAIL)			{			printf("TSD%d: %08lx\n", tx_tail, tsd);			printf(			"rl_handler: head %d, tail %d, busy: %d %d %d %d\n", 				tx_head, tx_tail,				rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy, 				rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);			}#endif			if (++tx_tail >= N_TX_BUF)				tx_tail= 0;			assert(tx_tail < RL_N_TX);			rep->re_tx_tail= tx_tail;			if (rep->re_flags & REF_SEND_AVAIL)			{#if 0				printf("rl_handler: REF_SEND_AVAIL\n");#endif				rep->re_send_int= TRUE;				if (!rep->re_got_int)				{					rep->re_got_int= TRUE;					int_event_check = TRUE;				}			}		}		assert(i < 2*N_TX_BUF);	}	if (isr)	{		printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",			isr);	}	return 1;}/*===========================================================================* *				rl_watchdog_f				     * *===========================================================================*/static void rl_watchdog_f(tp)timer_t *tp;{	int i;	re_t *rep;	/* Use a synchronous alarm instead of a watchdog timer. */	sys_setalarm(HZ, 0);	for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)	{		if (rep->re_mode != REM_ENABLED)			continue;		if (!(rep->re_flags & REF_SEND_AVAIL))		{			/* Assume that an idle system is alive */			rep->re_tx_alive= TRUE;			continue;		}		if (rep->re_tx_alive)		{			rep->re_tx_alive= FALSE;			continue;		}		printf("rl_watchdog_f: resetting port %d\n", i);		printf(	"TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",			rl_inw(rep->re_base_port, RL_TSAD),			rl_inl(rep->re_base_port, RL_TSD0+0*4),			rl_inl(rep->re_base_port, RL_TSD0+1*4),			rl_inl(rep->re_base_port, RL_TSD0+2*4),			rl_inl(rep->re_base_port, RL_TSD0+3*4));		printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",			rep->re_tx_head, rep->re_tx_tail,			rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,			rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);		rep->re_need_reset= TRUE;		rep->re_got_int= TRUE;					check_int_events();	}}#if 0_PROTOTYPE( static void rtl_init, (struct dpeth *dep)			);_PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a)		);_PROTOTYPE( static void ee_wen, (dpeth_t *dep)				);_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w)	);_PROTOTYPE( static void ee_wds, (dpeth_t *dep)				);static void rtl_init(dep)dpeth_t *dep;{	u8_t reg_a, reg_b, cr, config0, config2, config3;	int i;	char val[128];	printf("rtl_init called\n");	ne_init(dep);	/* ID */	outb_reg0(dep, DP_CR, CR_PS_P0);	reg_a = inb_reg0(dep, DP_DUM1);	reg_b = inb_reg0(dep, DP_DUM2);	printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);	outb_reg0(dep, DP_CR, CR_PS_P3);	config0 = inb_reg3(dep, 3);	config2 = inb_reg3(dep, 5);	config3 = inb_reg3(dep, 6);	outb_reg0(dep, DP_CR, CR_PS_P0);	printf("rtl_init: config 0/2/3 = %x/%x/%x\n",		config0, config2, config3);	if (0 == sys_getkenv("RTL8029FD",9+1, val, sizeof(val)))	{		printf("rtl_init: setting full-duplex mode\n");		outb_reg0(dep, DP_CR, CR_PS_P3);		cr= inb_reg3(dep, 1);		outb_reg3(dep, 1, cr | 0xc0);		outb_reg3(dep, 6, config3 | 0x40);		config3 = inb_reg3(dep, 6);		config2= inb_reg3(dep, 5);		outb_reg3(dep, 5, config2 | 0x20);		config2= inb_reg3(dep, 5);		outb_reg3(dep, 1, cr);		outb_reg0(dep, DP_CR, CR_PS_P0);		printf("rtl_init: config 2 = %x\n", config2);		printf("rtl_init: config 3 = %x\n", config3);	}	for (i= 0; i<64; i++)		printf("%x ", get_ee_word(dep, i));	printf("\n");	if (0 == sys_getkenv("RTL8029MN",9+1, val, sizeof(val)))	{		ee_wen(dep);		set_ee_word(dep, 0x78/2, 0x10ec);		set_ee_word(dep, 0x7A/2, 0x8029);		set_ee_word(dep, 0x7C/2, 0x10ec);		set_ee_word(dep, 0x7E/2, 0x8029);		ee_wds(dep);		assert(get_ee_word(dep, 0x78/2) == 0x10ec);		assert(get_ee_word(dep, 0x7A/2) == 0x8029);		assert(get_ee_word(dep, 0x7C/2) == 0x10ec);		assert(get_ee_word(dep, 0x7E/2) == 0x8029);	}	if (0 == sys_getkenv("RTL8029XXX",10+1, val, sizeof(val)))	{		ee_wen(dep);		set_ee_word(dep, 0x76/2, 0x8029);		ee_wds(dep);		assert(get_ee_word(dep, 0x76/2) == 0x8029);	}}static u16_t get_ee_word(dep, a)dpeth_t *dep;int a;{	int b, i, cmd;	u16_t w;	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */	/* Switch to 9346 mode and enable CS */	outb_reg3(dep, 1, 0x80 | 0x8);	cmd= 0x180 | (a & 0x3f);	/* 1 1 0 a5 a4 a3 a2 a1 a0 */	for (i= 8; i >= 0; i--)	{		b= (cmd & (1 << i));		b= (b ? 2 : 0);		/* Cmd goes out on the rising edge of the clock */		outb_reg3(dep, 1, 0x80 | 0x8 | b);		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);	}	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */	w= 0;	for (i= 0; i<16; i++)	{		w <<= 1;		/* Data is shifted out on the rising edge. Read at the		 * falling edge.		 */		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);		outb_reg3(dep, 1, 0x80 | 0x8 | b);		b= inb_reg3(dep, 1);		w |= (b & 1);	}	outb_reg3(dep, 1, 0x80);		/* drop CS */	outb_reg3(dep, 1, 0x00);		/* back to normal */	outb_reg0(dep, DP_CR, CR_PS_P0);	/* back to bank 0 */	return w;}static void ee_wen(dep)dpeth_t *dep;{	int b, i, cmd;	u16_t w;	outb_reg0(dep, DP_CR, CR_PS_P3);	/* Bank 3 */	/* Switch to 9346 mode and enable CS */	outb_reg3(dep, 1, 0x80 | 0x8);	cmd= 0x130;		/* 1 0 0 1 1 x x x x */	for (i= 8; i >= 0; i--)	{		b= (cmd & (1 << i));		b= (b ? 2 : 0);		/* Cmd goes out on the rising edge of the clock */		outb_reg3(dep, 1, 0x80 | 0x8 | b);		outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);	}	outb_reg3(dep, 1, 0x80 | 0x8);	/* End of cmd */	outb_reg3(dep, 1, 0x80);	/* Drop CS */	/* micro_delay(1); */			/* Is this required? */}static void set_ee_word(dep, a, w)dpeth_t *dep;int a;u16_t w;{	int b, i, cmd;	clock_t t0, t1;	outb_reg3(dep, 1, 0x80 | 0x8);		/* Set CS */	cmd= 0x140 | (a & 0x3f);		/* 1

⌨️ 快捷键说明

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