📄 dp8390.c
字号:
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 + -