📄 lance.c
字号:
printf("WERR\n");#endif ec->eth_stat.ets_sendErr++; } if (isr & ISR_WINT) {#if 0 printf("WINT\n");#endif /* status check: restart if needed. */ status = lp->tx_ring[cur_tx_slot_nr].u.base; /* ??? */ if (status & 0x40000000) { status = lp->tx_ring[cur_tx_slot_nr].misc; ec->eth_stat.ets_sendErr++; if (status & 0x0400) ec->eth_stat.ets_transAb++; if (status & 0x0800) ec->eth_stat.ets_carrSense++; if (status & 0x1000) ec->eth_stat.ets_OWC++; if (status & 0x4000) { ec->eth_stat.ets_fifoUnder++; must_restart=1; } } else { if (status & 0x18000000) ec->eth_stat.ets_collision++; ec->eth_stat.ets_packetT++; } } /* transmit a packet on the next slot if it exists. */ check = 0; if (isstored[cur_tx_slot_nr]==1) { /* free the tx-slot just transmitted */ isstored[cur_tx_slot_nr]=0; cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK; /* next tx-slot is ready? */ if (isstored[cur_tx_slot_nr]==1) check=1; else check=0; } else { panic( "lance", "got premature WINT...", NO_NUM); } if (check==1) { lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83; out_word(ioaddr+LANCE_ADDR, 0x0000); out_word(ioaddr+LANCE_DATA, 0x0048); } else if (check==-1) continue; /* we set a buffered message in the slot if it exists. */ /* and transmit it, if needed. */ if (ec->flags & ECF_SEND_AVAIL) ec_send(ec); } if (isr & ISR_RINT) {#if 0 printf("RINT\n");#endif ec_recv(ec); } if (isr & ISR_RST) { ec->flags = ECF_STOPPED; break; } /* ??? cf. lance driver on linux */ if (must_restart == 1) {#if 0 printf("ETH: restarting...\n");#endif out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ out_word(ioaddr+LANCE_DATA, 0x2); /* start */ } } if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) {#if 0 printf("ETH: resetting...\n");#endif ec_reset(ec); }}/*===========================================================================* * ec_reset * *===========================================================================*/static void ec_reset(ec)ether_card_t *ec;{ /* Stop/start the chip, and clear all RX,TX-slots */ unsigned short ioaddr = ec->ec_port; int i; out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ out_word(ioaddr+LANCE_DATA, 0x2); /* start */ /* purge Tx-ring */ tx_slot_nr = cur_tx_slot_nr = 0; for (i=0; i<TX_RING_SIZE; i++) { lp->tx_ring[i].u.base = 0; isstored[i]=0; } /* re-init Rx-ring */ rx_slot_nr = 0; for (i=0; i<RX_RING_SIZE; i++) { lp->rx_ring[i].buf_length = -ETH_FRAME_LEN; lp->rx_ring[i].u.addr[3] |= 0x80; } /* store a buffered message on the slot if exists */ ec_send(ec); ec->flags &= ~ECF_STOPPED;}/*===========================================================================* * ec_send * *===========================================================================*/static void ec_send(ec)ether_card_t *ec;{ /* from ec_check_ints() or ec_reset(). */ /* this function proccesses the buffered message. (slot/transmit) */ if (!(ec->flags & ECF_SEND_AVAIL)) return; ec->flags &= ~ECF_SEND_AVAIL; switch(ec->sendmsg.m_type) { case DL_WRITE: do_vwrite(&ec->sendmsg, TRUE, FALSE); break; case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE); break; default: panic( "lance", "wrong type:", ec->sendmsg.m_type); break; }}/*===========================================================================* * do_vread * *===========================================================================*/static void do_vread(mp, vectored)message *mp;int vectored;{ int port, count, size; ether_card_t *ec; port = mp->DL_PORT; count = mp->DL_COUNT; ec= &ec_table[port]; ec->client= mp->DL_PROC; if (vectored) { get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t), ec->read_iovec.iod_iovec); ec->read_iovec.iod_iovec_s = count; ec->read_iovec.iod_proc_nr = mp->DL_PROC; ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; ec->tmp_iovec = ec->read_iovec; size= calc_iovec_size(&ec->tmp_iovec); } else { ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT; ec->read_iovec.iod_iovec_s = 1; ec->read_iovec.iod_proc_nr = mp->DL_PROC; ec->read_iovec.iod_iovec_addr = 0; size= count; } ec->flags |= ECF_READING; ec_recv(ec); if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) ec_reset(ec); reply(ec, OK, FALSE);}/*===========================================================================* * ec_recv * *===========================================================================*/static void ec_recv(ec)ether_card_t *ec;{ vir_bytes length; int packet_processed; int status; unsigned short ioaddr = ec->ec_port; if ((ec->flags & ECF_READING)==0) return; if (!(ec->flags & ECF_ENABLED)) return; /* we check all the received slots until find a properly received packet */ packet_processed = FALSE; while (!packet_processed) { status = lp->rx_ring[rx_slot_nr].u.base >> 24; if ( (status & 0x80) == 0x00 ) { status = lp->rx_ring[rx_slot_nr].u.base >> 24; /* ??? */ if (status != 0x03) { if (status & 0x01) ec->eth_stat.ets_recvErr++; if (status & 0x04) ec->eth_stat.ets_fifoOver++; if (status & 0x08) ec->eth_stat.ets_CRCerr++; if (status & 0x10) ec->eth_stat.ets_OVW++; if (status & 0x20) ec->eth_stat.ets_frameAll++; length = 0; } else { ec->eth_stat.ets_packetR++; length = lp->rx_ring[rx_slot_nr].msg_length; } if (length > 0) { ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]), &ec->read_iovec, 0, length); ec->read_s = length; ec->flags |= ECF_PACK_RECV; ec->flags &= ~ECF_READING; packet_processed = TRUE; } /* set up this slot again, and we move to the next slot */ lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN; lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80; out_word(ioaddr+LANCE_ADDR, 0x00); out_word(ioaddr+LANCE_DATA, 0x7940); rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK; } else break; }}/*===========================================================================* * do_vwrite * *===========================================================================*/static void do_vwrite(mp, from_int, vectored)message *mp;int from_int;int vectored;{ int port, count, check; ether_card_t *ec; unsigned short ioaddr; port = mp->DL_PORT; count = mp->DL_COUNT; ec = &ec_table[port]; ec->client= mp->DL_PROC; if (isstored[tx_slot_nr]==1) { /* all slots are used, so this message is buffered */ ec->sendmsg= *mp; ec->flags |= ECF_SEND_AVAIL; reply(ec, OK, FALSE); return; } /* convert the message to write_iovec */ if (vectored) { get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t), ec->write_iovec.iod_iovec); ec->write_iovec.iod_iovec_s = count; ec->write_iovec.iod_proc_nr = mp->DL_PROC; ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR; ec->tmp_iovec = ec->write_iovec; ec->write_s = calc_iovec_size(&ec->tmp_iovec); } else { ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR; ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT; ec->write_iovec.iod_iovec_s = 1; ec->write_iovec.iod_proc_nr = mp->DL_PROC; ec->write_iovec.iod_iovec_addr = 0; ec->write_s = mp->DL_COUNT; } /* copy write_iovec to the slot on DMA address */ ec_user2nic(ec, &ec->write_iovec, 0, (int)(lp->tbuf[tx_slot_nr]), ec->write_s); /* set-up for transmitting, and transmit it if needed. */ lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s; lp->tx_ring[tx_slot_nr].misc = 0x0; lp->tx_ring[tx_slot_nr].u.base = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff; isstored[tx_slot_nr]=1; if (cur_tx_slot_nr == tx_slot_nr) check=1; else check=0; tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK; if (check == 1) { ioaddr = ec->ec_port; lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83; out_word(ioaddr+LANCE_ADDR, 0x0000); out_word(ioaddr+LANCE_DATA, 0x0048); } ec->flags |= ECF_PACK_SEND; /* reply by calling do_int() if this function is called from interrupt. */ if (from_int) return; reply(ec, OK, FALSE);}/*===========================================================================* * 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_local(user_proc, user_addr, count); if (!src) panic( "lance", "umap failed", NO_NUM); phys_copy(src, vir2phys(loc_addr), (phys_bytes) count); */ int cps; cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count); if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);}/*===========================================================================* * ec_user2nic * *===========================================================================*/static void ec_user2nic(ec, iovp, offset, nic_addr, count)ether_card_t *ec;iovec_dat_t *iovp;vir_bytes offset;int nic_addr;vir_bytes count;{ /*phys_bytes phys_hw, phys_user;*/ int bytes, i, r; /* phys_hw = vir2phys(nic_addr); */ i= 0; while (count > 0) { if (i >= IOVEC_NR) { ec_next_iovec(iovp); i= 0; continue; } 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_local(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes); phys_copy(phys_user, phys_hw, (phys_bytes) bytes); */ if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, SELF, nic_addr, count )) != OK ) panic( "lance", "sys_datacopy failed", r ); count -= bytes; nic_addr += bytes; offset += bytes; }}/*===========================================================================* * ec_nic2user * *===========================================================================*/static void ec_nic2user(ec, nic_addr, iovp, offset, count)ether_card_t *ec;int nic_addr;iovec_dat_t *iovp;vir_bytes offset;vir_bytes count;{ /*phys_bytes phys_hw, phys_user;*/ int bytes, i, r; /*phys_hw = vir2phys(nic_addr);*/ i= 0; while (count > 0) { if (i >= IOVEC_NR) { ec_next_iovec(iovp); i= 0; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -