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

📄 rtl8139.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * rtl8139.c * * This file contains a ethernet device driver for Realtek rtl8139 based * ethernet cards. * * The valid messages and their parameters are: * *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR * |------------+----------+---------+----------+---------+---------| * | HARD_INT	|          |         |          |         |         | * |------------|----------|---------|----------|---------|---------| * | SYS_SIG	|          |         |          |         |         | * |------------|----------|---------|----------|---------|---------| * | 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_GETNAME	|          |         |          |         |         | * |------------|----------|---------|----------|---------|---------| * | DL_STOP	| port_nr  |         |          |         |	    | * |------------|----------|---------|----------|---------|---------| * * The messages sent are: * *   m-type	  DL_POR T   DL_PROC   DL_COUNT   DL_STAT   DL_CLCK * |------------|----------|---------|----------|---------|---------| * |DL_TASK_REPL| port nr  | proc nr | rd-count | err|stat| clock   | * |------------|----------|---------|----------|---------|---------| * *   m_type	  m3_i1     m3_i2       m3_ca1 * |------------+---------+-----------+---------------| * |DL_INIT_REPL| port nr | last port | ethernet addr | * |------------|---------|-----------|---------------| * * Created:	Aug 2003 by Philip Homburg <philip@cs.vu.nl> * Changes: *   Aug 15, 2004   sync alarms replace watchdogs timers  (Jorrit N. Herder) *   May 02, 2004   flag alarms replace micro_elapsed()  (Jorrit N. Herder) * */#include "../drivers.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stddef.h>#include <minix/com.h>#include <minix/keymap.h>#include <minix/syslib.h>#include <minix/type.h>#include <minix/sysutil.h>#include <timers.h>#include <ibm/portio.h>#include <net/hton.h>#include <net/gen/ether.h>#include <net/gen/eth_io.h>#include <sys/types.h>#include <fcntl.h>#include <assert.h>#include <unistd.h>#include <sys/ioc_memory.h>#include "../../kernel/const.h"#include "../../kernel/config.h"#include "../../kernel/type.h"#define tmra_ut			timer_t#define tmra_inittimer(tp)	tmr_inittimer(tp)#define Proc_number(p)		proc_number(p)#define debug			0#define printW()		((void)0)#define vm_1phys2bus(p)		(p)#define VERBOSE		0	/* display message during init */#include "../libpci/pci.h"#include "rtl8139.h"#define RX_BUFSIZE	RL_RCR_RBLEN_64K_SIZE#define RX_BUFBITS	RL_RCR_RBLEN_64K#define N_TX_BUF	RL_N_TX#define RE_PORT_NR	1		/* Minix *//* I/O vectors are handled IOVEC_NR entries at a time. */#define IOVEC_NR	16/* Configuration */#define RL_ENVVAR	"RTLETH"PRIVATE struct pcitab{	u16_t vid;	u16_t did;	int checkclass;} pcitab[]={	{ 0x10ec, 0x8139, 0 },		/* Realtek RTL8139 */	{ 0x1186, 0x1300, 0 },		/* D-Link RTL8139 */	{ 0x0000, 0x0000, 0 }};typedef struct re{	port_t re_base_port;	int re_irq;	int re_mode;	int re_flags;	int re_client;	int re_link_up;	int re_got_int;	int re_send_int;	int re_report_link;	int re_clear_rx;	int re_need_reset;	int re_tx_alive;	char *re_model;	/* Rx */	phys_bytes re_rx_buf;	char  *v_re_rx_buf;	vir_bytes re_read_s;	/* Tx */	int re_tx_head;	int re_tx_tail;	struct	{		int ret_busy;		phys_bytes ret_buf;		char * v_ret_buf;	} re_tx[N_TX_BUF];	u32_t re_ertxth;	/* Early Tx Threshold */	/* PCI related */	int re_seen;			/* TRUE iff device available */	u8_t re_pcibus;		u8_t re_pcidev;		u8_t re_pcifunc;		/* 'large' items */	int re_hook_id;			/* IRQ hook id at kernel */	eth_stat_t re_stat;	ether_addr_t re_address;	message re_rx_mess;	message re_tx_mess;	char re_name[sizeof("rtl8139#n")];	iovec_t re_iovec[IOVEC_NR];}re_t;#define REM_DISABLED	0x0#define REM_ENABLED	0x1#define REF_PACK_SENT	0x001#define REF_PACK_RECV	0x002#define REF_SEND_AVAIL	0x004#define REF_READING	0x010#define REF_EMPTY	0x000#define REF_PROMISC	0x040#define REF_MULTI	0x080#define REF_BROAD	0x100#define REF_ENABLED	0x200static re_t re_table[RE_PORT_NR];static u16_t eth_ign_proto;static tmra_ut rl_watchdog;FORWARD _PROTOTYPE( unsigned my_inb, (U16_t port) );FORWARD _PROTOTYPE( unsigned my_inw, (U16_t port) );FORWARD _PROTOTYPE( unsigned my_inl, (U16_t port) );static unsigned my_inb(U16_t port) {	U8_t value;	int s;	if ((s=sys_inb(port, &value)) !=OK)		printf("RTL8139: warning, sys_inb failed: %d\n", s);	return value;}static unsigned my_inw(U16_t port) {	U16_t value;	int s;	if ((s=sys_inw(port, &value)) !=OK)		printf("RTL8139: warning, sys_inw failed: %d\n", s);	return value;}static unsigned my_inl(U16_t port) {	U32_t value;	int s;	if ((s=sys_inl(port, &value)) !=OK)		printf("RTL8139: warning, sys_inl failed: %d\n", s);	return value;}#define rl_inb(port, offset)	(my_inb((port) + (offset)))#define rl_inw(port, offset)	(my_inw((port) + (offset)))#define rl_inl(port, offset)	(my_inl((port) + (offset)))FORWARD _PROTOTYPE( void my_outb, (U16_t port, U8_t value) );FORWARD _PROTOTYPE( void my_outw, (U16_t port, U16_t value) );FORWARD _PROTOTYPE( void my_outl, (U16_t port, U32_t value) );static void my_outb(U16_t port, U8_t value) {	int s;	if ((s=sys_outb(port, value)) !=OK)		printf("RTL8139: warning, sys_outb failed: %d\n", s);}static void my_outw(U16_t port, U16_t value) {	int s;	if ((s=sys_outw(port, value)) !=OK)		printf("RTL8139: warning, sys_outw failed: %d\n", s);}static void my_outl(U16_t port, U32_t value) {	int s;	if ((s=sys_outl(port, value)) !=OK)		printf("RTL8139: warning, sys_outl failed: %d\n", s);}#define rl_outb(port, offset, value)	(my_outb((port) + (offset), (value)))#define rl_outw(port, offset, value)	(my_outw((port) + (offset), (value)))#define rl_outl(port, offset, value)	(my_outl((port) + (offset), (value)))_PROTOTYPE( static void rl_init, (message *mp)				);_PROTOTYPE( static void rl_pci_conf, (void)				);_PROTOTYPE( static int rl_probe, (re_t *rep)				);_PROTOTYPE( static void rl_conf_hw, (re_t *rep)				);_PROTOTYPE( static void rl_init_buf, (re_t *rep)				);_PROTOTYPE( static void rl_init_hw, (re_t *rep)				);_PROTOTYPE( static void rl_reset_hw, (re_t *rep)			);_PROTOTYPE( static void rl_confaddr, (re_t *rep)			);_PROTOTYPE( static void rl_rec_mode, (re_t *rep)			);_PROTOTYPE( static void rl_readv, (message *mp, int from_int, 							int vectored)	);_PROTOTYPE( static void rl_writev, (message *mp, int from_int,							int vectored)	);_PROTOTYPE( static void rl_check_ints, (re_t *rep)			);_PROTOTYPE( static void rl_report_link, (re_t *rep)			);_PROTOTYPE( static void mii_print_techab, (U16_t techab)		);_PROTOTYPE( static void mii_print_stat_speed, (U16_t stat,							U16_t extstat)	);_PROTOTYPE( static void rl_clear_rx, (re_t *rep)			);_PROTOTYPE( static void rl_do_reset, (re_t *rep)			);_PROTOTYPE( static void rl_getstat, (message *mp)			);_PROTOTYPE( static void rl_getname, (message *mp)			);_PROTOTYPE( static void reply, (re_t *rep, 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 void rtl8139_stop, (void)				);_PROTOTYPE( static void check_int_events, (void)				);_PROTOTYPE( static int do_hard_int, (void)				);_PROTOTYPE( static void rtl8139_dump, (message *m)				);#if 0_PROTOTYPE( static void dump_phy, (re_t *rep)				);#endif_PROTOTYPE( static int rl_handler, (re_t *rep)			);_PROTOTYPE( static void rl_watchdog_f, (timer_t *tp)			);/* The message used in the main loop is made global, so that rl_watchdog_f() * can change its message type to fake a HARD_INT message. */PRIVATE message m;PRIVATE int int_event_check;		/* set to TRUE if events arrived */static char *progname;extern int errno;/*===========================================================================* *				main				     * *===========================================================================*/int main(int argc, char *argv[]){	int fkeys, sfkeys;	int inet_proc_nr;	int i, r;	re_t *rep;	long v;	env_setargs(argc, argv);	v= 0;	(void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);	eth_ign_proto= htons((u16_t) v);	/* Observe some function key for debug dumps. */	fkeys = sfkeys = 0; bit_set(sfkeys, 9);	if ((r=fkey_map(&fkeys, &sfkeys)) != OK) 	    printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r);	/* Claim buffer memory now under Minix, before MM takes it all. */	for (rep= &re_table[0]; rep < re_table+RE_PORT_NR; rep++)		rl_init_buf(rep);	/* Try to notify INET that we are present (again). If INET cannot	 * be found, assume this is the first time we started and INET is	 * not yet alive.	 */	(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);	r = findproc("inet", &inet_proc_nr);	if (r == OK) notify(inet_proc_nr);	while (TRUE)	{		if ((r= receive(ANY, &m)) != OK)			panic("rtl8139","receive failed", r);		switch (m.m_type)		{		case DEV_PING: notify(m.m_source);		continue;		case DL_WRITEV:	rl_writev(&m, FALSE, TRUE);	break;		case DL_WRITE:	rl_writev(&m, FALSE, FALSE);	break;#if 0		case DL_READ:	do_vread(&m, FALSE);		break;#endif		case DL_READV:	rl_readv(&m, FALSE, TRUE);	break;		case DL_INIT:	rl_init(&m);			break;		case DL_GETSTAT: rl_getstat(&m);		break;		case DL_GETNAME: rl_getname(&m);		break;#if 0		case DL_STOP:	do_stop(&m);			break;#endif		case SYN_ALARM:			/* Under MINIX, synchronous alarms are used instead of			 * watchdog functions. The approach is very different:			 * MINIX VMD timeouts are handled within the kernel 			 * (the watchdog is executed by CLOCK), and notify()			 * the driver in some cases.			 * MINIX timeouts result in a SYN_ALARM message to the			 * driver and thus are handled where they should be			 * handled. Locally, watchdog functions are used again. 			 */			rl_watchdog_f(NULL);     			break;		 		case HARD_INT:			do_hard_int();			if (int_event_check)				check_int_events();			break ;		case FKEY_PRESSED: rtl8139_dump(&m);		break;		case SYS_SIG: {			sigset_t sigset = m.NOTIFY_ARG;			if (sigismember(&sigset, SIGKSTOP)) rtl8139_stop();					break;		}		default:			panic("rtl8139","illegal message", m.m_type);		}	}}static void check_int_events(void) {  int i;  re_t *rep;			for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)			{				if (rep->re_mode != REM_ENABLED)					continue;				if (!rep->re_got_int)					continue;				rep->re_got_int= 0;				assert(rep->re_flags & REF_ENABLED);				rl_check_ints(rep);			}}/*===========================================================================* *				rtl8139_stop				     * *===========================================================================*/static void rtl8139_stop(){	int i;	re_t *rep;	for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)	{		if (rep->re_mode != REM_ENABLED)			continue;		rl_outb(rep->re_base_port, RL_CR, 0);	}	sys_exit(0);}/*===========================================================================* *				rtl8139_dump				     * *===========================================================================*/static void rtl8139_dump(m)message *m;			/* pointer to request message */{	re_t *rep;	int i;	printf("\n");	for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)	{		if (rep->re_mode == REM_DISABLED)			printf("Realtek RTL 8139 port %d is disabled\n", i);		if (rep->re_mode != REM_ENABLED)			continue;		printf("Realtek RTL 8139 statistics of port %d:\n", i);		printf("recvErr    :%8ld\t", rep->re_stat.ets_recvErr);		printf("sendErr    :%8ld\t", rep->re_stat.ets_sendErr);		printf("OVW        :%8ld\n", rep->re_stat.ets_OVW);		printf("CRCerr     :%8ld\t", rep->re_stat.ets_CRCerr);		printf("frameAll   :%8ld\t", rep->re_stat.ets_frameAll);		printf("missedP    :%8ld\n", rep->re_stat.ets_missedP);		printf("packetR    :%8ld\t", rep->re_stat.ets_packetR);		printf("packetT    :%8ld\t", rep->re_stat.ets_packetT);		printf("transDef   :%8ld\n", rep->re_stat.ets_transDef);		printf("collision  :%8ld\t", rep->re_stat.ets_collision);		printf("transAb    :%8ld\t", rep->re_stat.ets_transAb);		printf("carrSense  :%8ld\n", rep->re_stat.ets_carrSense);		printf("fifoUnder  :%8ld\t", rep->re_stat.ets_fifoUnder);		printf("fifoOver   :%8ld\t", rep->re_stat.ets_fifoOver);		printf("CDheartbeat:%8ld\n", rep->re_stat.ets_CDheartbeat);		printf("OWC        :%8ld\t", rep->re_stat.ets_OWC);		printf("re_flags = 0x%x\n", rep->re_flags);		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);	}}/*===========================================================================* *				do_init					     * *===========================================================================*/static void rl_init(mp)message *mp;{	static int first_time= 1;	int port;	re_t *rep;	message reply_mess;	if (first_time)	{		first_time= 0;		rl_pci_conf(); /* Configure PCI devices. */		tmra_inittimer(&rl_watchdog);		/* Use a synchronous alarm instead of a watchdog timer. */		sys_setalarm(HZ, 0);	}	port = mp->DL_PORT;	if (port < 0 || port >= RE_PORT_NR)	{		reply_mess.m_type= DL_INIT_REPLY;		reply_mess.m3_i1= ENXIO;		mess_reply(mp, &reply_mess);		return;	}	rep= &re_table[port];	if (rep->re_mode == REM_DISABLED)	{		/* This is the default, try to (re)locate the device. */		rl_conf_hw(rep);		if (rep->re_mode == REM_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 (rep->re_mode == REM_ENABLED)			rl_init_hw(rep);#if VERBOSE	/* load silently ... can always check status later */		rl_report_link(rep);#endif	}	assert(rep->re_mode == REM_ENABLED);	assert(rep->re_flags & REF_ENABLED);	rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);	if (mp->DL_MODE & DL_PROMISC_REQ)		rep->re_flags |= REF_PROMISC;	if (mp->DL_MODE & DL_MULTI_REQ)		rep->re_flags |= REF_MULTI;	if (mp->DL_MODE & DL_BROAD_REQ)		rep->re_flags |= REF_BROAD;	rep->re_client = mp->m_source;	rl_rec_mode(rep);	reply_mess.m_type = DL_INIT_REPLY;	reply_mess.m3_i1 = mp->DL_PORT;	reply_mess.m3_i2 = RE_PORT_NR;

⌨️ 快捷键说明

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