📄 fxp.c
字号:
size= 0; o= 0; for (i= 0; i<count; i += IOVEC_NR, iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0])) { n= IOVEC_NR; if (i+n > count) n= count-i; r= sys_vircopy(fxp_client, D, iov_src, SELF, D, (vir_bytes)fp->fxp_iovec, n * sizeof(fp->fxp_iovec[0])); if (r != OK) panic("FXP","fxp_readv: sys_vircopy failed", r); for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++) { s= iovp->iov_size; if (size + s > packlen) { assert(packlen > size); s= packlen-size; } r= sys_vircopy(SELF, D, (vir_bytes)(rfdp->rfd_buf+o), fxp_client, D, iovp->iov_addr, s); if (r != OK) { panic("FXP","fxp_readv: sys_vircopy failed", r); } size += s; if (size == packlen) break; o += s; } if (size == packlen) break; } if (size < packlen) { assert(0); } } else { assert(0); } fp->fxp_read_s= packlen; fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV; /* Re-init the current buffer */ rfdp->rfd_status= 0; rfdp->rfd_command= RFDC_EL; rfdp->rfd_reserved= 0; rfdp->rfd_res= 0; rfdp->rfd_size= sizeof(rfdp->rfd_buf); fxp_rx_nbuf= fp->fxp_rx_nbuf; if (fxp_rx_head == 0) { prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1]; } else prev_rfdp= &rfdp[-1]; assert(prev_rfdp->rfd_command & RFDC_EL); prev_rfdp->rfd_command &= ~RFDC_EL; fxp_rx_head++; if (fxp_rx_head == fxp_rx_nbuf) fxp_rx_head= 0; assert(fxp_rx_head < fxp_rx_nbuf); fp->fxp_rx_head= fxp_rx_head; if (!from_int) reply(fp, OK, FALSE); return;suspend: if (fp->fxp_rx_need_restart) { fp->fxp_rx_need_restart= 0; /* Check the status of the RU */ scb_status= fxp_inb(port, SCB_STATUS); if ((scb_status & SS_RUS_MASK) != SS_RU_NORES) { /* Race condition? */ printf("fxp_readv: restart race: 0x%x\n", scb_status); assert((scb_status & SS_RUS_MASK) == SS_RU_READY); } else { fxp_restart_ru(fp); } } if (from_int) { assert(fp->fxp_flags & FF_READING); /* No need to store any state */ return; } fp->fxp_rx_mess= *mp; assert(!(fp->fxp_flags & FF_READING)); fp->fxp_flags |= FF_READING; reply(fp, OK, FALSE);}/*===========================================================================* * fxp_do_conf * *===========================================================================*/static void fxp_do_conf(fp)fxp_t *fp;{ int r; u32_t bus_addr; struct cbl_conf cc; clock_t t0,t1; /* Configure device */ cc.cc_status= 0; cc.cc_command= CBL_C_EL | CBL_CONF; cc.cc_linkaddr= 0; memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes)); r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc), &bus_addr); if (r != OK) panic("FXP","sys_umap failed", r); fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */); getuptime(&t0); do { /* Wait for CU command to complete */ if (cc.cc_status & CBL_F_C) break; } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000)); if (!(cc.cc_status & CBL_F_C)) panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM); if (!(cc.cc_status & CBL_F_OK)) panic("FXP","fxp_do_conf: CU command failed", NO_NUM);}/*===========================================================================* * fxp_cu_ptr_cmd * *===========================================================================*/static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)fxp_t *fp;int cmd;phys_bytes bus_addr;int check_idle;{ clock_t t0,t1; port_t port; u8_t scb_cmd; port= fp->fxp_base_port; if (check_idle) { /* Consistency check. Make sure that CU is idle */ if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE) panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM); } fxp_outl(port, SCB_POINTER, bus_addr); fxp_outb(port, SCB_CMD, cmd); /* What is a reasonable time-out? There is nothing in the * documentation. 1 ms should be enough. */ getuptime(&t0); do { /* Wait for CU command to be accepted */ scb_cmd= fxp_inb(port, SCB_CMD); if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP) break; } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000)); if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP) panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);}/*===========================================================================* * fxp_ru_ptr_cmd * *===========================================================================*/static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)fxp_t *fp;int cmd;phys_bytes bus_addr;int check_idle;{ clock_t t0,t1; port_t port; u8_t scb_cmd; port= fp->fxp_base_port; if (check_idle) { /* Consistency check, make sure that RU is idle */ if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE) panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM); } fxp_outl(port, SCB_POINTER, bus_addr); fxp_outb(port, SCB_CMD, cmd); getuptime(&t0); do { /* Wait for RU command to be accepted */ scb_cmd= fxp_inb(port, SCB_CMD); if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP) break; } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000)); if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP) panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);}/*===========================================================================* * fxp_restart_ru * *===========================================================================*/static void fxp_restart_ru(fp)fxp_t *fp;{ int i, fxp_rx_nbuf; port_t port; struct rfd *rfdp; port= fp->fxp_base_port; fxp_rx_nbuf= fp->fxp_rx_nbuf; for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++) { rfdp->rfd_status= 0; rfdp->rfd_command= 0; if (i == fp->fxp_rx_nbuf-1) rfdp->rfd_command= RFDC_EL; rfdp->rfd_reserved= 0; rfdp->rfd_res= 0; rfdp->rfd_size= sizeof(rfdp->rfd_buf); } fp->fxp_rx_head= 0; /* Make sure that RU is in the 'No resources' state */ if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES) panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM); fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr, FALSE /* do not check idle */);}/*===========================================================================* * fxp_getstat * *===========================================================================*/static void fxp_getstat(mp)message *mp;{ clock_t t0,t1; int dl_port; port_t port; fxp_t *fp; u32_t *p; eth_stat_t stats; dl_port = mp->DL_PORT; if (dl_port < 0 || dl_port >= FXP_PORT_NR) panic("FXP","fxp_getstat: illegal port", dl_port); fp= &fxp_table[dl_port]; fp->fxp_client= mp->DL_PROC; assert(fp->fxp_mode == FM_ENABLED); assert(fp->fxp_flags & FF_ENABLED); port= fp->fxp_base_port; p= &fp->fxp_stat.sc_tx_fcp; *p= 0; /* The dump commmand doesn't take a pointer. Setting a pointer * doesn't hard though. */ fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */); getuptime(&t0); do { /* Wait for CU command to complete */ if (*p != 0) break; } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000)); if (*p == 0) panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM); if (*p != SCM_DSC) panic("FXP","fxp_getstat: bad magic", NO_NUM); stats.ets_recvErr= fp->fxp_stat.sc_rx_crc + fp->fxp_stat.sc_rx_align + fp->fxp_stat.sc_rx_resource + fp->fxp_stat.sc_rx_overrun + fp->fxp_stat.sc_rx_cd + fp->fxp_stat.sc_rx_short; stats.ets_sendErr= fp->fxp_stat.sc_tx_maxcol + fp->fxp_stat.sc_tx_latecol + fp->fxp_stat.sc_tx_crs; stats.ets_OVW= fp->fxp_stat.sc_rx_overrun; stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc; stats.ets_frameAll= fp->fxp_stat.sc_rx_align; stats.ets_missedP= fp->fxp_stat.sc_rx_resource; stats.ets_packetR= fp->fxp_stat.sc_rx_good; stats.ets_packetT= fp->fxp_stat.sc_tx_good; stats.ets_transDef= fp->fxp_stat.sc_tx_defered; stats.ets_collision= fp->fxp_stat.sc_tx_totcol; stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol; stats.ets_carrSense= fp->fxp_stat.sc_tx_crs; stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun; stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun; stats.ets_CDheartbeat= 0; stats.ets_OWC= fp->fxp_stat.sc_tx_latecol; put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, (vir_bytes) sizeof(stats), &stats); reply(fp, OK, FALSE);}/*===========================================================================* * fxp_getname * *===========================================================================*/static void fxp_getname(mp)message *mp;{ int r; strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; mp->m_type= DL_NAME_REPLY; r= send(mp->m_source, mp); if (r != OK) panic("FXP", "fxp_getname: send failed", r);}/*===========================================================================* * fxp_handler * *===========================================================================*/static int fxp_handler(fp)fxp_t *fp;{ int port; u16_t isr; RAND_UPDATE port= fp->fxp_base_port; /* Ack interrupt */ isr= fxp_inb(port, SCB_INT_STAT); fxp_outb(port, SCB_INT_STAT, isr); if (isr & SIS_FR) { isr &= ~SIS_FR; if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING)) { fp->fxp_got_int= TRUE; interrupt(fxp_tasknr); } } if (isr & SIS_CNA) { isr &= ~SIS_CNA; if (!fp->fxp_tx_idle) { fp->fxp_send_int= TRUE; if (!fp->fxp_got_int) { fp->fxp_got_int= TRUE; interrupt(fxp_tasknr); } } } if (isr & SIS_RNR) { isr &= ~SIS_RNR; /* Assume that receive buffer is full of packets. fxp_readv * will restart the RU. */ fp->fxp_rx_need_restart= 1; } if (isr) { printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n", isr); } return 1;}/*===========================================================================* * fxp_check_ints * *===========================================================================*/static void fxp_check_ints(fp)fxp_t *fp;{ int n, fxp_flags, prev_tail; int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold; port_t port; u32_t busaddr; u16_t tx_status; u8_t scb_status; struct tx *txp; fxp_flags= fp->fxp_flags; if (fxp_flags & FF_READING) { if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C)) ; /* Nothing */ else if (fp->fxp_rx_mess.m_type == DL_READV) { fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */, TRUE /* vectored */); } else { assert(fp->fxp_rx_mess.m_type == DL_READ); fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */, FALSE /* !vectored */); } } if (fp->fxp_tx_idle) ; /* Nothing to do */ else if (fp->fxp_send_int) { fp->fxp_send_int= FALSE; fxp_tx_tail= fp->fxp_tx_tail; fxp_tx_nbuf= fp->fxp_tx_nbuf; n= 0; for (;;) { txp= &fp->fxp_tx_buf[fxp_tx_tail]; tx_status= txp->tx_status; if (!(tx_status & TXS_C)) break; n++; assert(tx_status & TXS_OK); if (tx_status & TXS_U) { fxp_tx_threshold= fp->fxp_tx_threshold; if (fxp_tx_threshold < TXTT_MAX) { fxp_tx_threshold++; fp->fxp_tx_threshold= fxp_tx_threshold; } printf( "fxp_check_ints: fxp_tx_threshold = 0x%x\n", fxp_tx_threshold); } if (txp->tx_command & TXC_EL) { fp->fxp_tx_idle= 1; break; } fxp_tx_tail++; if (fxp_tx_tail == fxp_tx_nbuf) fxp_tx_tail= 0; assert(fxp_tx_tail < fxp_tx_nbuf); } if (fp->fxp_need_conf) { /* Check the status of the CU */ port= fp->fxp_base_port; scb_status= fxp_inb(port, SCB_STATUS); if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE) { /* Nothing to do */ printf("scb_status = 0x%x\n", scb_status); } else { printf("fxp_check_ints: fxp_need_conf\n"); fp->fxp_need_conf= FALSE; fxp_do_conf(fp); } } if (n) { if (!fp->fxp_tx_idle) { fp->fxp_tx_tail= fxp_tx_tail; /* Check the status of the CU */ port= fp->fxp_base_port; scb_status= fxp_inb(port, SCB_STATUS); if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE) { /* Nothing to do */ printf("scb_status = 0x%x\n", scb_status); } else { if (fxp_tx_tail == 0) prev_tail= fxp_tx_nbuf-1; else prev_tail= fxp_tx_tail-1; busaddr= fp->fxp_tx_buf[prev_tail]. tx_linkaddr; fxp_cu_ptr_cmd(fp, SC_CU_START, busaddr, 1 /* check idle */); } } if (fp->fxp_flags & FF_SEND_AVAIL) { if (fp->fxp_tx_mess.m_type == DL_WRITEV) { fxp_writev(&fp->fxp_tx_mess, TRUE /* from int */, TRUE /* vectored */); } else { assert(fp->fxp_tx_mess.m_type == DL_WRITE); fxp_writev(&fp->fxp_tx_mess, TRUE /* from int */, FALSE /* !vectored */); } } } } if (fp->fxp_report_link) fxp_report_link(fp); if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV)) reply(fp, OK, TRUE);}/*===========================================================================* * fxp_watchdog_f * *===========================================================================*/static void fxp_watchdog_f(tp)timer_t *tp;{ int i; fxp_t *fp; tmr_arg(&fxp_watchdog)->ta_int= 0; fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f); for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++) { if (fp->fxp_mode != FM_ENABLED) continue; /* Handle race condition, MII interface mgith be busy */ if(!fp->fxp_mii_busy) { /* Check the link status. */ if (fxp_link_changed(fp)) {#if VERBOSE printf("fxp_watchdog_f: link changed\n");#endif fp->fxp_report_link= TRUE; fp->fxp_got_int= TRUE; interrupt(fxp_tasknr); } } if (!(fp->fxp_flags & FF_SEND_AVAIL)) { /* Assume that an idle system is alive */ fp->fxp_tx_alive= TRUE; continue; } if (fp->fxp_tx_alive) { fp->fxp_tx_alive= FALSE; continue; } fp->fxp_need_reset= TRUE; fp->fxp_got_int= TRUE; interrupt(fxp_tasknr); }}/*===========================================================================* * fxp_link_changed * *===========================================================================*/static int fxp_link_changed(fp)fxp_t *fp;{ u16_t scr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -