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

📄 dp8390.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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);
		curr = inb_reg1(dep, DP_CURR);
		outb_reg0(dep, DP_CR, CR_PS_P0);

		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 < 60 || length > 1514)
		{
			printf(
			"dp8390: packet with strange length arrived: %d\n",
				length);
			next= curr;
		}
		else if (next < dep->de_startpage || next >= dep->de_stoppage)
		{
			printf("dp8390: strange next page\n");
			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;
				printW();
				printf("dropping proto %04x packet\n",
					ntohs(eth_ign_proto));
			}
			dep->de_stat.ets_packetR++;
			next = curr;
		}
		else if (header.dr_status & RSR_FO)
		{
			/* This is very serious, so we issue a warning and
			 * reset the buffers */
			printf(
			"dp8390: fifo overrun, resetting receive buffer\n");
			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;
{
	u16_t *ha;
	int i;

	ha = (u16_t *) dst;
	offset = page * DP_PAGESIZE + offset;
	assert(!(size & 1));
	for (i= 0; i<size; i+=2)
	{
		*ha = mem_rdw(dep->de_memsegm, offset+i);
		ha++;
	}
}


/*===========================================================================*
 *				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;
{
	u8_t *ha;
	int i;

	ha = (u8_t *) 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);

	for (i= 0; i<size; i++)
		ha[i]= in_byte(dep->de_data_port);
}


/*===========================================================================*
 *				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;
{
	u16_t *ha;
	int i;

	ha = (u16_t *) 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));
	size /= 2;
	for (i= 0; i<size; i++)
		ha[i]= in_word(dep->de_data_port);
}


/*===========================================================================*
 *				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;
{
	phys_bytes phys_hw, phys_user;
	int bytes, i;

	phys_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;

		phys_user = numap(iovp->iod_proc_nr,
			iovp->iod_iovec[i].iov_addr + offset, bytes);
		if (!phys_user)
			panic("dp8390: umap failed\n", NO_NUM);
		phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
		count -= bytes;
		phys_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;

		phys_user = numap(iovp->iod_proc_nr,
			iovp->iod_iovec[i].iov_addr + offset, bytes);
		if (!phys_user)
			panic("dp8390: umap failed\n", NO_NUM);
		port_write_byte(dep->de_data_port, phys_user, 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;
{
	phys_bytes phys_user;
	vir_bytes ecount;
	int bytes, i;
	u8_t two_bytes[2];
	phys_bytes phys_2bytes;
	int odd_byte;

	ecount= (count+1) & ~1;
	phys_2bytes = vir2phys(two_bytes);
	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;

		phys_user = numap(iovp->iod_proc_nr,
			iovp->iod_iovec[i].iov_addr + offset, bytes);
		if (!phys_user)
			panic("dp8390: umap failed\n", NO_NUM);
		if (odd_byte)
		{
			phys_copy(phys_user, phys_2bytes+1,
				(phys_bytes) 1);
			out_word(dep->de_data_port, *(u16_t *)two_bytes);
			count--;
			offset++;
			bytes--;
			phys_user++;
			odd_byte= 0;
			if (!bytes)
				continue;
		}
		ecount= bytes & ~1;
		if (ecount != 0)
		{
			port_write(dep->de_data_port, phys_user, ecount);
			count -= ecount;
			offset += ecount;
			bytes -= ecount;
			phys_user += ecount;
		}
		if (bytes)
		{
			assert(bytes == 1);
			phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
			count--;
			offset++;
			bytes--;
			phys_user++;
			odd_byte= 1;
		}
	}
	assert(count == 0);

	if (odd_byte)
		out_word(dep->de_data_port, *(u16_t *)two_bytes);

⌨️ 快捷键说明

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