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