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

📄 dp8390.c

📁 minix3的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return;	}	assert(dep->de_mode == DEM_ENABLED);	assert(dep->de_flags & DEF_ENABLED);	if(dep->de_flags & DEF_READING)		panic("", "dp8390: read already in progress", NO_NUM);	if (vectored)	{		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,			(count > IOVEC_NR ? IOVEC_NR : count) *			sizeof(iovec_t), dep->de_read_iovec.iod_iovec);		dep->de_read_iovec.iod_iovec_s = count;		dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;		dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;		dep->de_tmp_iovec = dep->de_read_iovec;		size= calc_iovec_size(&dep->de_tmp_iovec);	}	else	{		dep->de_read_iovec.iod_iovec[0].iov_addr =			(vir_bytes) mp->DL_ADDR;		dep->de_read_iovec.iod_iovec[0].iov_size =			mp->DL_COUNT;		dep->de_read_iovec.iod_iovec_s = 1;		dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;		dep->de_read_iovec.iod_iovec_addr = 0;		size= count;	}	if (size < ETH_MAX_PACK_SIZE_TAGGED)		panic("", "dp8390: wrong packet size", size);	dep->de_flags |= DEF_READING;	dp_recv(dep);	if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==		(DEF_READING|DEF_STOPPED))	{		/* The chip is stopped, and all arrived packets are 		 * delivered.		 */		dp_reset(dep);	}	reply(dep, OK, FALSE);}/*===========================================================================* *				do_init					     * *===========================================================================*/static void do_init(mp)message *mp;{	int port;	dpeth_t *dep;	message reply_mess;#if ENABLE_PCI	pci_conf(); /* Configure PCI devices. */#endif	port = mp->DL_PORT;	if (port < 0 || port >= DE_PORT_NR)	{		reply_mess.m_type= DL_INIT_REPLY;		reply_mess.m3_i1= ENXIO;		mess_reply(mp, &reply_mess);		return;	}	dep= &de_table[port];	if (dep->de_mode == DEM_DISABLED)	{		/* This is the default, try to (re)locate the device. */		conf_hw(dep);		if (dep->de_mode == DEM_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 (dep->de_mode == DEM_ENABLED)			dp_init(dep);	}	if (dep->de_mode == DEM_SINK)	{		strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);		dep->de_address.ea_addr[5] = port;		dp_confaddr(dep);		reply_mess.m_type = DL_INIT_REPLY;		reply_mess.m3_i1 = mp->DL_PORT;		reply_mess.m3_i2 = DE_PORT_NR;		*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;		mess_reply(mp, &reply_mess);		return;	}	assert(dep->de_mode == DEM_ENABLED);	assert(dep->de_flags & DEF_ENABLED);	dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);	if (mp->DL_MODE & DL_PROMISC_REQ)		dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;	if (mp->DL_MODE & DL_MULTI_REQ)		dep->de_flags |= DEF_MULTI;	if (mp->DL_MODE & DL_BROAD_REQ)		dep->de_flags |= DEF_BROAD;	dep->de_client = mp->m_source;	dp_reinit(dep);	reply_mess.m_type = DL_INIT_REPLY;	reply_mess.m3_i1 = mp->DL_PORT;	reply_mess.m3_i2 = DE_PORT_NR;	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;	mess_reply(mp, &reply_mess);}/*===========================================================================* *				do_int					     * *===========================================================================*/static void do_int(dep)dpeth_t *dep;{	if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))		reply(dep, OK, TRUE);}/*===========================================================================* *				do_getstat				     * *===========================================================================*/static void do_getstat(mp)message *mp;{	int port;	dpeth_t *dep;	port = mp->DL_PORT;	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)	{		put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,			(vir_bytes) sizeof(dep->de_stat), &dep->de_stat);		reply(dep, OK, FALSE);		return;	}	assert(dep->de_mode == DEM_ENABLED);	assert(dep->de_flags & DEF_ENABLED);	dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);	dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);	dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);	put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,		(vir_bytes) sizeof(dep->de_stat), &dep->de_stat);	reply(dep, OK, FALSE);}/*===========================================================================* *				do_getname				     * *===========================================================================*/static void do_getname(mp)message *mp;{	int r;	strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));	mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';	mp->m_type= DL_NAME_REPLY;	r= send(mp->m_source, mp);	if (r != OK)		panic("dp8390", "do_getname: send failed: %d\n", r);}/*===========================================================================* *				do_stop					     * *===========================================================================*/static void do_stop(mp)message *mp;{	int port;	dpeth_t *dep;	port = mp->DL_PORT;	if (port < 0 || port >= DE_PORT_NR)		panic("", "dp8390: illegal port", port);	dep= &de_table[port];	if (dep->de_mode == DEM_SINK)		return;	assert(dep->de_mode == DEM_ENABLED);	if (!(dep->de_flags & DEF_ENABLED))		return;	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);	(dep->de_stopf)(dep);	dep->de_flags= DEF_EMPTY;}/*===========================================================================* *				dp_init					     * *===========================================================================*/static void dp_init(dep)dpeth_t *dep;{	int dp_rcr_reg;	int i, r;	/* General initialization */	dep->de_flags = DEF_EMPTY;	(*dep->de_initf)(dep);	dp_confaddr(dep);	if (debug)	{		printf("%s: Ethernet address ", dep->de_name);		for (i= 0; i < 6; i++)			printf("%x%c", dep->de_address.ea_addr[i],							i < 5 ? ':' : '\n');	}	/* Initialization of the dp8390 following the mandatory procedure	 * in reference manual ("DP8390D/NS32490D NIC Network Interface	 * Controller", National Semiconductor, July 1995, Page 29).	 */	/* Step 1: */	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);	/* Step 2: */	if (dep->de_16bit)		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);	else		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);	/* Step 3: */	outb_reg0(dep, DP_RBCR0, 0);	outb_reg0(dep, DP_RBCR1, 0);	/* Step 4: */	dp_rcr_reg = 0;	if (dep->de_flags & DEF_PROMISC)		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;	if (dep->de_flags & DEF_BROAD)		dp_rcr_reg |= RCR_AB;	if (dep->de_flags & DEF_MULTI)		dp_rcr_reg |= RCR_AM;	outb_reg0(dep, DP_RCR, dp_rcr_reg);	/* Step 5: */	outb_reg0(dep, DP_TCR, TCR_INTERNAL);	/* Step 6: */	outb_reg0(dep, DP_BNRY, dep->de_startpage);	outb_reg0(dep, DP_PSTART, dep->de_startpage);	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);	/* Step 7: */	outb_reg0(dep, DP_ISR, 0xFF);	/* Step 8: */	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |		IMR_OVWE | IMR_CNTE);	/* Step 9: */	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);	outb_reg1(dep, DP_MAR0, 0xff);	outb_reg1(dep, DP_MAR1, 0xff);	outb_reg1(dep, DP_MAR2, 0xff);	outb_reg1(dep, DP_MAR3, 0xff);	outb_reg1(dep, DP_MAR4, 0xff);	outb_reg1(dep, DP_MAR5, 0xff);	outb_reg1(dep, DP_MAR6, 0xff);	outb_reg1(dep, DP_MAR7, 0xff);	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);	/* Step 10: */	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);	/* Step 11: */	outb_reg0(dep, DP_TCR, TCR_NORMAL);	inb_reg0(dep, DP_CNTR0);		/* reset counters by reading */	inb_reg0(dep, DP_CNTR1);	inb_reg0(dep, DP_CNTR2);	/* Finish the initialization. */	dep->de_flags |= DEF_ENABLED;	for (i= 0; i<dep->de_sendq_nr; i++)		dep->de_sendq[i].sq_filled= 0;	dep->de_sendq_head= 0;	dep->de_sendq_tail= 0;	if (!dep->de_prog_IO)	{		dep->de_user2nicf= dp_user2nic;		dep->de_nic2userf= dp_nic2user;		dep->de_getblockf= dp_getblock;	}	else if (dep->de_16bit)	{		dep->de_user2nicf= dp_pio16_user2nic;		dep->de_nic2userf= dp_pio16_nic2user;		dep->de_getblockf= dp_pio16_getblock;	}	else	{		dep->de_user2nicf= dp_pio8_user2nic;		dep->de_nic2userf= dp_pio8_nic2user;		dep->de_getblockf= dp_pio8_getblock;	}	/* Set the interrupt handler and policy. Do not automatically 	 * reenable interrupts. Return the IRQ line number on interrupts. 	 */ 	dep->de_hook = dep->de_irq;	r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);	if (r != OK)		panic("DP8390", "sys_irqsetpolicy failed", r);	r= sys_irqenable(&dep->de_hook);	if (r != OK)	{		panic("DP8390", "unable enable interrupts", r);	}}/*===========================================================================* *				dp_confaddr				     * *===========================================================================*/static void dp_confaddr(dep)dpeth_t *dep;{	int i;	char eakey[16];	static char eafmt[]= "x:x:x:x:x:x";	long v;	/* User defined ethernet address? */	strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);	strcat(eakey, "_EA");	for (i= 0; i < 6; i++)	{		v= dep->de_address.ea_addr[i];		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)		{			break;		}		dep->de_address.ea_addr[i]= v;	}	if (i != 0 && i != 6) env_panic(eakey);	/* It's all or nothing */}/*===========================================================================* *				dp_reinit				     * *===========================================================================*/static void dp_reinit(dep)dpeth_t *dep;{	int dp_rcr_reg;	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);	dp_rcr_reg = 0;	if (dep->de_flags & DEF_PROMISC)		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;	if (dep->de_flags & DEF_BROAD)		dp_rcr_reg |= RCR_AB;	if (dep->de_flags & DEF_MULTI)		dp_rcr_reg |= RCR_AM;	outb_reg0(dep, DP_RCR, dp_rcr_reg);}/*===========================================================================* *				dp_reset				     * *===========================================================================*/static void dp_reset(dep)dpeth_t *dep;{	int i;	/* Stop chip */	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);	outb_reg0(dep, DP_RBCR0, 0);	outb_reg0(dep, DP_RBCR1, 0);	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)		; /* Do nothing */	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);	outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);	outb_reg0(dep, DP_TCR, TCR_NORMAL);	/* Acknowledge the ISR_RDC (remote dma) interrupt. */	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)		; /* Do nothing */	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);	/* Reset the transmit ring. If we were transmitting a packet, we	 * pretend that the packet is processed. Higher layers will	 * retransmit if the packet wasn't actually sent.	 */	dep->de_sendq_head= dep->de_sendq_tail= 0;	for (i= 0; i<dep->de_sendq_nr; i++)		dep->de_sendq[i].sq_filled= 0;	dp_send(dep);	dep->de_flags &= ~DEF_STOPPED;}/*===========================================================================* *				dp_check_ints				     * *===========================================================================*/static void dp_check_ints(dep)dpeth_t *dep;{	int isr, tsr;	int size, sendq_tail;	if (!(dep->de_flags & DEF_ENABLED))		panic("", "dp8390: got premature interrupt", NO_NUM);	for(;;)	{		isr = inb_reg0(dep, DP_ISR);		if (!isr)			break;		outb_reg0(dep, DP_ISR, isr);		if (isr & (ISR_PTX|ISR_TXE))		{			if (isr & ISR_TXE)			{#if DEBUG { printf("%s: got send Error\n", dep->de_name); }#endif				dep->de_stat.ets_sendErr++;			}			else			{				tsr = inb_reg0(dep, DP_TSR);				if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;#if 0	/* Reserved in later manuals, should be ignored */				if (!(tsr & TSR_DFR))				{					/* In most (all?) implementations of					 * the dp8390, this bit is set					 * when the packet is not deferred					 */					dep->de_stat.ets_transDef++;				}#endif				if (tsr & TSR_COL) dep->de_stat.ets_collision++;				if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;				if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;				if (tsr & TSR_FU					&& ++dep->de_stat.ets_fifoUnder <= 10)				{					printf("%s: fifo underrun\n",						dep->de_name);				}				if (tsr & TSR_CDH					&& ++dep->de_stat.ets_CDheartbeat <= 10)				{					printf("%s: CD heart beat failure\n",						dep->de_name);				}				if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;			}			sendq_tail= dep->de_sendq_tail;			if (!(dep->de_sendq[sendq_tail].sq_filled))			{				/* Software bug? */				assert(!debug);				/* Or hardware bug? */				printf(				"%s: transmit interrupt, but not sending\n",					dep->de_name);				continue;			}			dep->de_sendq[sendq_tail].sq_filled= 0;			if (++sendq_tail == dep->de_sendq_nr)				sendq_tail= 0;			dep->de_sendq_tail= sendq_tail;			if (dep->de_sendq[sendq_tail].sq_filled)			{				size= dep->de_sendq[sendq_tail].sq_size;				outb_reg0(dep, DP_TPSR,

⌨️ 快捷键说明

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