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

📄 dp8390.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 4 页
字号:
message *mp;
{
	int port;
	dpeth_t *dep;
	message reply_mess;

	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)
	{
		dep->de_address.ea_addr[0] = 
			dep->de_address.ea_addr[1] = 
			dep->de_address.ea_addr[2] = 
			dep->de_address.ea_addr[3] = 
			dep->de_address.ea_addr[4] = 
			dep->de_address.ea_addr[5] = 0;
		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_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;

	/* General initialization */
	dep->de_flags = DEF_EMPTY;
	(*dep->de_initf)(dep);

	dp_confaddr(dep);

	/* Initialization of the dp8390 */
	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
	outb_reg0(dep, DP_IMR, 0);
	outb_reg0(dep, DP_PSTART, dep->de_startpage);
	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
	outb_reg0(dep, DP_BNRY, dep->de_startpage);
	outb_reg0(dep, DP_RCR, RCR_MON);
	outb_reg0(dep, DP_TCR, TCR_NORMAL);
	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);
	outb_reg0(dep, DP_RBCR0, 0);
	outb_reg0(dep, DP_RBCR1, 0);
	outb_reg0(dep, DP_ISR, 0xFF);
	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT);

	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);
	outb_reg1(dep, DP_CR, CR_PS_P0 | CR_DM_ABORT);

	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);
	inb_reg0(dep, DP_CNTR0);		/* reset counters by reading */
	inb_reg0(dep, DP_CNTR1);
	inb_reg0(dep, DP_CNTR2);

	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
		IMR_OVWE | IMR_CNTE);
	outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);

	/* 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 */
	put_irq_handler(dep->de_irq, dp_handler);
	enable_irq(dep->de_irq);
}


/*===========================================================================*
 *				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)
	{
		/* It's all or nothing; force a panic. */
		(void) env_parse(eakey, "?", 0, &v, 0L, 0L);
	}
}


/*===========================================================================*
 *				dp_reinit				     *
 *===========================================================================*/
static void dp_reinit(dep)
dpeth_t *dep;
{
	int dp_rcr_reg;

	outb_reg0(dep, DP_CR, CR_PS_P0);

	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|TCR_OFST);

	/* 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("dp8390: got send Error\n"); }
#endif
				dep->de_stat.ets_sendErr++;
			}
			else
			{
				tsr = inb_reg0(dep, DP_TSR);

				if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
				if (tsr & TSR_DFR) dep->de_stat.ets_transDef++;
				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("dp8390: fifo underrun\n");
				}
				if (tsr & TSR_CDH
					&& ++dep->de_stat.ets_CDheartbeat <= 10)
				{
					printf(
					"dp8390: CD heart beat failure\n");
				}
				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(
			"dp8390: transmit interrupt, but not sending\n");
				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,
					dep->de_sendq[sendq_tail].sq_sendpage);
				outb_reg0(dep, DP_TBCR1, size >> 8);
				outb_reg0(dep, DP_TBCR0, size & 0xff);
				outb_reg0(dep, DP_CR, CR_TXP);	/* there is goes.. */
			}
			if (dep->de_flags & DEF_SEND_AVAIL)
				dp_send(dep);
		}

		if (isr & ISR_PRX)
			dp_recv(dep);
		
		if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
		if (isr & ISR_CNT)
		{
			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);
		}
		if (isr & ISR_OVW)
		{
#if DEBUG
 { printW(); printf("dp8390: got overwrite warning\n"); }
#endif
		}
		if (isr & ISR_RDC)
		{
			/* Nothing to do */
		}
		if (isr & ISR_RST)
		{
			/* this means we got an interrupt but the ethernet 
			 * chip is shutdown. We set the flag DEF_STOPPED,
			 * and continue processing arrived packets. When the
			 * receive buffer is empty, we reset the dp8390.
			 */
#if DEBUG
 { printW(); printf("dp8390: NIC stopped\n"); }
#endif
			dep->de_flags |= DEF_STOPPED;
			break;
		}
	}

⌨️ 快捷键说明

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