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

📄 dp8390.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 4 页
字号:

	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				     *
 *===========================================================================*/
static void dp_nic2user(dep, nic_addr, iovp, offset, count)
dpeth_t *dep;
int nic_addr;
iovec_dat_t *iovp;
vir_bytes offset;
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_hw, phys_user, (phys_bytes) bytes);
		count -= bytes;
		phys_hw += bytes;
		offset += bytes;
	}
	assert(count == 0);
}


/*===========================================================================*
 *				dp_pio8_nic2user			     *
 *===========================================================================*/
static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
dpeth_t *dep;
int nic_addr;
iovec_dat_t *iovp;
vir_bytes offset;
vir_bytes count;
{
	phys_bytes phys_user;
	int bytes, i;

	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_RR | 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_read_byte(dep->de_data_port, phys_user, bytes);
		count -= bytes;
		offset += bytes;
	}
	assert(count == 0);
}


/*===========================================================================*
 *				dp_pio16_nic2user			     *
 *===========================================================================*/
static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
dpeth_t *dep;
int nic_addr;
iovec_dat_t *iovp;
vir_bytes offset;
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_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_RR | 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_2bytes+1, phys_user, (phys_bytes) 1);
			count--;
			offset++;
			bytes--;
			phys_user++;
			odd_byte= 0;
			if (!bytes)
				continue;
		}
		ecount= bytes & ~1;
		if (ecount != 0)
		{
			port_read(dep->de_data_port, phys_user, ecount);
			count -= ecount;
			offset += ecount;
			bytes -= ecount;
			phys_user += ecount;
		}
		if (bytes)
		{
			assert(bytes == 1);
			*(u16_t *)two_bytes= in_word(dep->de_data_port);
			phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
			count--;
			offset++;
			bytes--;
			phys_user++;
			odd_byte= 1;
		}
	}
	assert(count == 0);
}


/*===========================================================================*
 *				dp_next_iovec					     *
 *===========================================================================*/
static void dp_next_iovec(iovp)
iovec_dat_t *iovp;
{
	assert(iovp->iod_iovec_s > IOVEC_NR);

	iovp->iod_iovec_s -= IOVEC_NR;

	iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);

	get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
		(iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
		sizeof(iovec_t), iovp->iod_iovec); 
}


/*===========================================================================*
 *				dp_handler				     *
 *===========================================================================*/
static int dp_handler(irq)
int irq;
{
/* DP8390 interrupt, send message and reenable interrupts. */

	assert(irq >= 0 && irq < NR_IRQ_VECTORS);
	int_pending[irq]= 1;
	interrupt(dpeth_tasknr);
	return 1;
}

/*===========================================================================*
 *				conf_hw					     *
 *===========================================================================*/
static void conf_hw(dep)
dpeth_t *dep;
{
	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };

	int ifnr;
	dp_conf_t *dcp;

	dep->de_mode= DEM_DISABLED;	/* Superfluous */
	ifnr= dep-de_table;

	dcp= &dp_conf[ifnr];
	update_conf(dep, dcp);
	if (dep->de_mode != DEM_ENABLED)
			return;
	if (!wdeth_probe(dep) && !ne_probe(dep))
	{
		printf("dp8390: warning no ethernet card found at 0x%x\n", 
			dep->de_base_port);
		dep->de_mode= DEM_DISABLED;
		return;
	}

	/* Allocate a memory segment, programmed I/O should set the
	 * memory segment (linmem) to zero.
	 */
	if (dep->de_linmem != 0)
	{
		if (protected_mode)
		{
			init_dataseg(&gdt[dcp->dpc_prot_sel / DESC_SIZE],
				dep->de_linmem, dep->de_ramsize,
				TASK_PRIVILEGE);
			dep->de_memsegm= dcp->dpc_prot_sel;
		}
		else
		{
			dep->de_memsegm= physb_to_hclick(dep->de_linmem);
		}
	}

/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;

	dep->de_flags = DEF_EMPTY;
	dep->de_stat = empty_stat;
}


/*===========================================================================*
 *				update_conf				     *
 *===========================================================================*/
static void update_conf(dep, dcp)
dpeth_t *dep;
dp_conf_t *dcp;
{
	long v;
	static char dpc_fmt[] = "x:d:x";

	/* Get the default settings and modify them from the environment. */
	dep->de_mode= DEM_SINK;
	v= dcp->dpc_port;
	switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x000L, 0x3FFL)) {
	case EP_OFF:
		dep->de_mode= DEM_DISABLED;
		break;
	case EP_ON:
	case EP_SET:
		dep->de_mode= DEM_ENABLED;	/* Might become disabled if 
						 * all probes fail */
		break;
	}
	dep->de_base_port= v;

	v= dcp->dpc_irq | DEI_DEFAULT;
	(void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
						(long) NR_IRQ_VECTORS - 1);
	dep->de_irq= v;

	v= dcp->dpc_mem;
	(void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, LONG_MAX);
	dep->de_linmem= v;
}


/*===========================================================================*
 *				calc_iovec_size				     *
 *===========================================================================*/
static int calc_iovec_size(iovp)
iovec_dat_t *iovp;
{
	/* Calculate the size of a request. Note that the iovec_dat
	 * structure will be unusable after calc_iovec_size.
	 */
	int size;
	int i;

	size= 0;
	i= 0;
	while (i < iovp->iod_iovec_s)
	{
		if (i >= IOVEC_NR)
		{
			dp_next_iovec(iovp);
			i= 0;
			continue;
		}
		size += iovp->iod_iovec[i].iov_size;
		i++;
	}
	return size;
}


/*===========================================================================*
 *				reply					     *
 *===========================================================================*/
static void reply(dep, err, may_block)
dpeth_t *dep;
int err;
int may_block;
{
	message reply;
	int status;
	int r;

	status = 0;
	if (dep->de_flags & DEF_PACK_SEND)
		status |= DL_PACK_SEND;
	if (dep->de_flags & DEF_PACK_RECV)
		status |= DL_PACK_RECV;

	reply.m_type = DL_TASK_REPLY;
	reply.DL_PORT = dep - de_table;
	reply.DL_PROC = dep->de_client;
	reply.DL_STAT = status | ((u32_t) err << 16);
	reply.DL_COUNT = dep->de_read_s;
	reply.DL_CLCK = get_uptime();
	r= send(dep->de_client, &reply);
#if 0
	/* XXX  What is the reason that this doesn't happen? */
	if (result == ELOCKED && may_block)
		return;
#endif
	if (r < 0)
		panic("dp8390: send failed:", r);
	
	dep->de_read_s = 0;
	dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
}


/*===========================================================================*
 *				mess_reply				     *
 *===========================================================================*/
static void mess_reply(req, reply_mess)
message *req;
message *reply_mess;
{
	if (send(req->m_source, reply_mess) != OK)
		panic("dp8390: unable to mess_reply", NO_NUM);
}


/*===========================================================================*
 *				get_userdata				     *
 *===========================================================================*/
static void get_userdata(user_proc, user_addr, count, loc_addr)
int user_proc;
vir_bytes user_addr;
vir_bytes count;
void *loc_addr;
{
	phys_bytes src;

	src = numap(user_proc, user_addr, count);
	if (!src)
		panic("dp8390: umap failed", NO_NUM);

	phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
}


/*===========================================================================*
 *				put_userdata				     *
 *===========================================================================*/
static void put_userdata(user_proc, user_addr, count, loc_addr)
int user_proc;
vir_bytes user_addr;
vir_bytes count;
void *loc_addr;
{
	phys_bytes dst;

	dst = numap(user_proc, user_addr, count);
	if (!dst)
		panic("dp8390: umap failed", NO_NUM);

	phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
}

#endif /* ENABLE_NETWORKING */

/*
 * $PchHeader: /mount/hd2/minix/sys/kernel/ibm/RCS/dp8390.c,v 1.4 1995/06/13 08:10:42 philip Exp $
 */

⌨️ 快捷键说明

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