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

📄 dp8390.c

📁 minix3的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
					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 | CR_EXTRA);			}			if (dep->de_flags & DEF_SEND_AVAIL)				dp_send(dep);		}		if (isr & ISR_PRX)		{			/* Only call dp_recv if there is a read request */			if (dep->de_flags & DEF_READING)				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)		{			dep->de_stat.ets_OVW++;#if 0			{ printW(); printf(				"%s: got overwrite warning\n", dep->de_name); }#endif			if (dep->de_flags & DEF_READING)			{				printf("dp_check_ints: strange: overwrite warning and pending read request\n");				dp_recv(dep);			}		}		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 0			 { printW(); printf(				"%s: NIC stopped\n", dep->de_name); }#endif			dep->de_flags |= DEF_STOPPED;			break;		}	}	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);	}}/*===========================================================================* *				dp_recv					     * *===========================================================================*/static void dp_recv(dep)dpeth_t *dep;{	dp_rcvhdr_t header;	unsigned pageno, curr, next;	vir_bytes length;	int packet_processed, r;	u16_t eth_type;	packet_processed = FALSE;	pageno = inb_reg0(dep, DP_BNRY) + 1;	if (pageno == dep->de_stoppage) pageno = dep->de_startpage;	do	{		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);		curr = inb_reg1(dep, DP_CURR);		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);		if (curr == pageno) break;		(dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),			&header);		(dep->de_getblockf)(dep, pageno, sizeof(header) +			2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);		length = (header.dr_rbcl | (header.dr_rbch << 8)) -			sizeof(dp_rcvhdr_t);		next = header.dr_next;		if (length < ETH_MIN_PACK_SIZE ||			length > ETH_MAX_PACK_SIZE_TAGGED)		{			printf("%s: packet with strange length arrived: %d\n",				dep->de_name, (int) length);			next= curr;		}		else if (next < dep->de_startpage || next >= dep->de_stoppage)		{			printf("%s: strange next page\n", dep->de_name);			next= curr;		}		else if (eth_type == eth_ign_proto)		{			/* Hack: ignore packets of a given protocol, useful			 * if you share a net with 80 computers sending			 * Amoeba FLIP broadcasts.  (Protocol 0x8146.)			 */			static int first= 1;			if (first)			{				first= 0;				printf("%s: dropping proto 0x%04x packets\n",					dep->de_name,					ntohs(eth_ign_proto));			}			dep->de_stat.ets_packetR++;		}		else if (header.dr_status & RSR_FO)		{			/* This is very serious, so we issue a warning and			 * reset the buffers */			printf("%s: fifo overrun, resetting receive buffer\n",				dep->de_name);			dep->de_stat.ets_fifoOver++;			next = curr;		}		else if ((header.dr_status & RSR_PRX) &&					   (dep->de_flags & DEF_ENABLED))		{			r = dp_pkt2user(dep, pageno, length);			if (r != OK)				return;			packet_processed = TRUE;			dep->de_stat.ets_packetR++;		}		if (next == dep->de_startpage)			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);		else			outb_reg0(dep, DP_BNRY, next - 1);		pageno = next;	}	while (!packet_processed);}/*===========================================================================* *				dp_send					     * *===========================================================================*/static void dp_send(dep)dpeth_t *dep;{	if (!(dep->de_flags & DEF_SEND_AVAIL))		return;	dep->de_flags &= ~DEF_SEND_AVAIL;	switch(dep->de_sendmsg.m_type)	{	case DL_WRITE:	do_vwrite(&dep->de_sendmsg, TRUE, FALSE);	break;	case DL_WRITEV:	do_vwrite(&dep->de_sendmsg, TRUE, TRUE);	break;	default:		panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);		break;	}}/*===========================================================================* *				dp_getblock				     * *===========================================================================*/static void dp_getblock(dep, page, offset, size, dst)dpeth_t *dep;int page;size_t offset;size_t size;void *dst;{	int r;	offset = page * DP_PAGESIZE + offset;	r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,		SELF, D, (vir_bytes)dst, size);	if (r != OK)		panic("DP8390", "dp_getblock: sys_vircopy failed", r);}/*===========================================================================* *				dp_pio8_getblock			     * *===========================================================================*/static void dp_pio8_getblock(dep, page, offset, size, dst)dpeth_t *dep;int page;size_t offset;size_t size;void *dst;{	offset = page * DP_PAGESIZE + offset;	outb_reg0(dep, DP_RBCR0, size & 0xFF);	outb_reg0(dep, DP_RBCR1, size >> 8);	outb_reg0(dep, DP_RSAR0, offset & 0xFF);	outb_reg0(dep, DP_RSAR1, offset >> 8);	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);	insb(dep->de_data_port, dst, size);}/*===========================================================================* *				dp_pio16_getblock			     * *===========================================================================*/static void dp_pio16_getblock(dep, page, offset, size, dst)dpeth_t *dep;int page;size_t offset;size_t size;void *dst;{	offset = page * DP_PAGESIZE + offset;	outb_reg0(dep, DP_RBCR0, size & 0xFF);	outb_reg0(dep, DP_RBCR1, size >> 8);	outb_reg0(dep, DP_RSAR0, offset & 0xFF);	outb_reg0(dep, DP_RSAR1, offset >> 8);	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);	assert (!(size & 1));	insw(dep->de_data_port, dst, size);}/*===========================================================================* *				dp_pkt2user				     * *===========================================================================*/static int dp_pkt2user(dep, page, length)dpeth_t *dep;int page, length;{	int last, count;	if (!(dep->de_flags & DEF_READING))		return EGENERIC;	last = page + (length - 1) / DP_PAGESIZE;	if (last >= dep->de_stoppage)	{		count = (dep->de_stoppage - page) * DP_PAGESIZE -			sizeof(dp_rcvhdr_t);		/* Save read_iovec since we need it twice. */		dep->de_tmp_iovec = dep->de_read_iovec;		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +			sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);		(dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 				&dep->de_read_iovec, count, length - count);	}	else	{		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +			sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);	}	dep->de_read_s = length;	dep->de_flags |= DEF_PACK_RECV;	dep->de_flags &= ~DEF_READING;	return OK;}/*===========================================================================* *				dp_user2nic				     * *===========================================================================*/static void dp_user2nic(dep, iovp, offset, nic_addr, count)dpeth_t *dep;iovec_dat_t *iovp;vir_bytes offset;int nic_addr;vir_bytes count;{	vir_bytes vir_hw, vir_user;	int bytes, i, r;	vir_hw = dep->de_linmem + nic_addr;	i= 0;	while (count > 0)	{		if (i >= IOVEC_NR)		{			dp_next_iovec(iovp);			i= 0;			continue;		}		assert(i < iovp->iod_iovec_s);		if (offset >= iovp->iod_iovec[i].iov_size)		{			offset -= iovp->iod_iovec[i].iov_size;			i++;			continue;		}		bytes = iovp->iod_iovec[i].iov_size - offset;		if (bytes > count)			bytes = count;		r= sys_vircopy(iovp->iod_proc_nr, D,			iovp->iod_iovec[i].iov_addr + offset,			SELF, BIOS_SEG, vir_hw, bytes);		if (r != OK)			panic("DP8390", "dp_user2nic: sys_vircopy failed", r);		count -= bytes;		vir_hw += bytes;		offset += bytes;	}	assert(count == 0);}/*===========================================================================* *				dp_pio8_user2nic			     * *===========================================================================*/static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)dpeth_t *dep;iovec_dat_t *iovp;vir_bytes offset;int nic_addr;vir_bytes count;{	phys_bytes phys_user;	int bytes, i;	outb_reg0(dep, DP_ISR, ISR_RDC);	outb_reg0(dep, DP_RBCR0, count & 0xFF);	outb_reg0(dep, DP_RBCR1, count >> 8);	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);	i= 0;	while (count > 0)	{		if (i >= IOVEC_NR)		{			dp_next_iovec(iovp);			i= 0;			continue;		}		assert(i < iovp->iod_iovec_s);		if (offset >= iovp->iod_iovec[i].iov_size)		{			offset -= iovp->iod_iovec[i].iov_size;			i++;			continue;		}		bytes = iovp->iod_iovec[i].iov_size - offset;		if (bytes > count)			bytes = count;		do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,			iovp->iod_iovec[i].iov_addr + offset, bytes);		count -= bytes;		offset += bytes;	}	assert(count == 0);	for (i= 0; i<100; i++)	{		if (inb_reg0(dep, DP_ISR) & ISR_RDC)			break;	}	if (i == 100)	{		panic("", "dp8390: remote dma failed to complete", NO_NUM);	}}/*===========================================================================* *				dp_pio16_user2nic			     * *===========================================================================*/static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)dpeth_t *dep;iovec_dat_t *iovp;vir_bytes offset;int nic_addr;vir_bytes count;{	vir_bytes vir_user;	vir_bytes ecount;	int i, r, bytes, user_proc;	u8_t two_bytes[2];	int odd_byte;	ecount= (count+1) & ~1;	odd_byte= 0;	outb_reg0(dep, DP_ISR, ISR_RDC);	outb_reg0(dep, DP_RBCR0, ecount & 0xFF);	outb_reg0(dep, DP_RBCR1, ecount >> 8);	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);	i= 0;	while (count > 0)	{		if (i >= IOVEC_NR)		{			dp_next_iovec(iovp);			i= 0;			continue;		}		assert(i < iovp->iod_iovec_s);		if (offset >= iovp->iod_iovec[i].iov_size)		{			offset -= iovp->iod_iovec[i].iov_size;			i++;			continue;		}		bytes = iovp->iod_iovec[i].iov_size - offset;		if (bytes > count)			bytes = count;		user_proc= iovp->iod_proc_nr;		vir_user= iovp->iod_iovec[i].iov_addr + offset;		if (odd_byte)		{			r= sys_vircopy(user_proc, D, vir_user, 				SELF, D, (vir_bytes)&two_bytes[1], 1);			if (r != OK)			{				panic("DP8390",					"dp_pio16_user2nic: sys_vircopy failed",					r);			}			outw(dep->de_data_port, *(u16_t *)two_bytes);			count--;			offset++;			bytes--;			vir_user++;			odd_byte= 0;			if (!bytes)				continue;		}		ecount= bytes & ~1;		if (ecount != 0)		{			do_vir_outsw(dep->de_data_port, user_proc, vir_user,				ecount);			count -= ecount;			offset += ecount;			bytes -= ecount;			vir_user += ecount;		}		if (bytes)		{			assert(bytes == 1);			r= sys_vircopy(user_proc, D, vir_user, 				SELF, D, (vir_bytes)&two_bytes[0], 1);			if (r != OK)			{				panic("DP8390",					"dp_pio16_user2nic: sys_vircopy failed",					r);			}			count--;			offset++;			bytes--;			vir_user++;			odd_byte= 1;		}	}	assert(count == 0);	if (odd_byte)		outw(dep->de_data_port, *(u16_t *)two_bytes);	for (i= 0; i<100; i++)	{		if (inb_reg0(dep, DP_ISR) & ISR_RDC)			break;	}	if (i == 100)	{		panic("", "dp8390: remote dma failed to complete", NO_NUM);	}}/*===========================================================================* *				dp_nic2user				     * *===========================================================================*/

⌨️ 快捷键说明

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