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