📄 fxp.c
字号:
scr= mii_read(fp, MII_SCR); scr &= ~(MII_SCR_RES|MII_SCR_RES_1); return (fp->fxp_mii_scr != scr);}/*===========================================================================* * fxp_report_link * *===========================================================================*/static void fxp_report_link(fp)fxp_t *fp;{ port_t port; u16_t mii_ctrl, mii_status, mii_id1, mii_id2, mii_ana, mii_anlpa, mii_ane, mii_extstat, mii_ms_ctrl, mii_ms_status, scr; u32_t oui; int model, rev; int f, link_up, ms_regs; /* Assume an 82555 (compatible) PHY. The should be changed for * 82557 NICs with different PHYs */ ms_regs= 0; /* No master/slave registers. */ fp->fxp_report_link= FALSE; port= fp->fxp_base_port; scr= mii_read(fp, MII_SCR); scr &= ~(MII_SCR_RES|MII_SCR_RES_1); fp->fxp_mii_scr= scr; mii_ctrl= mii_read(fp, MII_CTRL); mii_read(fp, MII_STATUS); /* Read the status register twice, why? */ mii_status= mii_read(fp, MII_STATUS); mii_id1= mii_read(fp, MII_PHYID_H); mii_id2= mii_read(fp, MII_PHYID_L); mii_ana= mii_read(fp, MII_ANA); mii_anlpa= mii_read(fp, MII_ANLPA); mii_ane= mii_read(fp, MII_ANE); if (mii_status & MII_STATUS_EXT_STAT) mii_extstat= mii_read(fp, MII_EXT_STATUS); else mii_extstat= 0; if (ms_regs) { mii_ms_ctrl= mii_read(fp, MII_MS_CTRL); mii_ms_status= mii_read(fp, MII_MS_STATUS); } else { mii_ms_ctrl= 0; mii_ms_status= 0; } /* How do we know about the link status? */ link_up= !!(mii_status & MII_STATUS_LS); fp->fxp_link_up= link_up; if (!link_up) {#if VERBOSE printf("%s: link down\n", fp->fxp_name);#endif return; } oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) | ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT); model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT); rev= (mii_id2 & MII_PL_REV_MASK);#if VERBOSE printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);#endif if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO)) { printf("%s: PHY: ", fp->fxp_name); f= 1; if (mii_ctrl & MII_CTRL_LB) { printf("loopback mode"); f= 0; } if (mii_ctrl & MII_CTRL_PD) { if (!f) printf(", "); f= 0; printf("powered down"); } if (mii_ctrl & MII_CTRL_ISO) { if (!f) printf(", "); f= 0; printf("isolated"); } printf("\n"); return; } if (!(mii_ctrl & MII_CTRL_ANE)) { printf("%s: manual config: ", fp->fxp_name); switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB)) { case MII_CTRL_SP_10: printf("10 Mbps"); break; case MII_CTRL_SP_100: printf("100 Mbps"); break; case MII_CTRL_SP_1000: printf("1000 Mbps"); break; case MII_CTRL_SP_RES: printf("reserved speed"); break; } if (mii_ctrl & MII_CTRL_DM) printf(", full duplex"); else printf(", half duplex"); printf("\n"); return; } if (!debug) goto resspeed; printf("%s: ", fp->fxp_name); mii_print_stat_speed(mii_status, mii_extstat); printf("\n"); if (!(mii_status & MII_STATUS_ANC)) printf("%s: auto-negotiation not complete\n", fp->fxp_name); if (mii_status & MII_STATUS_RF) printf("%s: remote fault detected\n", fp->fxp_name); if (!(mii_status & MII_STATUS_ANA)) { printf("%s: local PHY has no auto-negotiation ability\n", fp->fxp_name); } if (!(mii_status & MII_STATUS_LS)) printf("%s: link down\n", fp->fxp_name); if (mii_status & MII_STATUS_JD) printf("%s: jabber condition detected\n", fp->fxp_name); if (!(mii_status & MII_STATUS_EC)) { printf("%s: no extended register set\n", fp->fxp_name); goto resspeed; } if (!(mii_status & MII_STATUS_ANC)) goto resspeed; printf("%s: local cap.: ", fp->fxp_name); if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) { printf("1000 Mbps: T-"); switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) { case MII_MSC_1000T_FD: printf("FD"); break; case MII_MSC_1000T_HD: printf("HD"); break; default: printf("FD/HD"); break; } if (mii_ana) printf(", "); } mii_print_techab(mii_ana); printf("\n"); if (mii_ane & MII_ANE_PDF) printf("%s: parallel detection fault\n", fp->fxp_name); if (!(mii_ane & MII_ANE_LPANA)) { printf("%s: link-partner does not support auto-negotiation\n", fp->fxp_name); goto resspeed; } printf("%s: remote cap.: ", fp->fxp_name); if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD)) { printf("1000 Mbps: T-"); switch(mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD)) { case MII_MSS_LP1000T_FD: printf("FD"); break; case MII_MSS_LP1000T_HD: printf("HD"); break; default: printf("FD/HD"); break; } if (mii_anlpa) printf(", "); } mii_print_techab(mii_anlpa); printf("\n"); if (ms_regs) { printf("%s: ", fp->fxp_name); if (mii_ms_ctrl & MII_MSC_MS_MANUAL) { printf("manual %s", (mii_ms_ctrl & MII_MSC_MS_VAL) ? "MASTER" : "SLAVE"); } else { printf("%s device", (mii_ms_ctrl & MII_MSC_MULTIPORT) ? "multiport" : "single-port"); } if (mii_ms_ctrl & MII_MSC_RES) printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES); printf(": "); if (mii_ms_status & MII_MSS_FAULT) printf("M/S config fault"); else if (mii_ms_status & MII_MSS_MASTER) printf("MASTER"); else printf("SLAVE"); printf("\n"); } if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD)) { if (!(mii_ms_status & MII_MSS_LOCREC)) { printf("%s: local receiver not OK\n", fp->fxp_name); } if (!(mii_ms_status & MII_MSS_REMREC)) { printf("%s: remote receiver not OK\n", fp->fxp_name); } } if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR)) { printf("%s", fp->fxp_name); if (mii_ms_status & MII_MSS_RES) printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES); if (mii_ms_status & MII_MSS_IDLE_ERR) { printf(" idle error %d", mii_ms_status & MII_MSS_IDLE_ERR); } printf("\n"); }resspeed:#if VERBOSE printf("%s: link up, %d Mbps, %s duplex\n", fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10, (scr & MII_SCR_FD) ? "full" : "half");#endif ;}/*===========================================================================* * fxp_stop * *===========================================================================*/static void fxp_stop(){ int i; port_t port; fxp_t *fp; for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++) { if (fp->fxp_mode != FM_ENABLED) continue; if (!(fp->fxp_flags & FF_ENABLED)) continue; port= fp->fxp_base_port; /* Reset device */ if (debug) printf("%s: resetting device\n", fp->fxp_name); fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET); } sys_exit(0);}/*===========================================================================* * reply * *===========================================================================*/static void reply(fp, err, may_block)fxp_t *fp;int err;int may_block;{ message reply; int status; int r; status = 0; if (fp->fxp_flags & FF_PACK_SENT) status |= DL_PACK_SEND; if (fp->fxp_flags & FF_PACK_RECV) status |= DL_PACK_RECV; reply.m_type = DL_TASK_REPLY; reply.DL_PORT = fp - fxp_table; reply.DL_PROC = fp->fxp_client; reply.DL_STAT = status | ((u32_t) err << 16); reply.DL_COUNT = fp->fxp_read_s;#if 0 reply.DL_CLCK = get_uptime();#else reply.DL_CLCK = 0;#endif r= send(fp->fxp_client, &reply); if (r == ELOCKED && may_block) {#if 0 printW(); printf("send locked\n");#endif return; } if (r < 0) panic("FXP","fxp: send failed:", r); fp->fxp_read_s = 0; fp->fxp_flags &= ~(FF_PACK_SENT | FF_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("FXP","fxp: unable to mess_reply", NO_NUM);}/*===========================================================================* * 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;{ int r; r= sys_vircopy(SELF, D, (vir_bytes)loc_addr, user_proc, D, user_addr, count); if (r != OK) panic("FXP","put_userdata: sys_vircopy failed", r);}/*===========================================================================* * eeprom_read * *===========================================================================*/PRIVATE u16_t eeprom_read(fp, reg)fxp_t *fp;int reg;{ port_t port; u16_t v; int b, i, alen; alen= fp->fxp_ee_addrlen; if (!alen) { eeprom_addrsize(fp); alen= fp->fxp_ee_addrlen; assert(alen == 6 || alen == 8); } port= fp->fxp_base_port; fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */ v= EEPROM_READ_PREFIX; for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--) { b= ((v & (1 << i)) ? CE_EEDI : 0); fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); fxp_outb(port, CSR_EEPROM, CE_EECS | b); micro_delay(EESK_PERIOD/2+1); } v= reg; for (i= alen-1; i >= 0; i--) { b= ((v & (1 << i)) ? CE_EEDI : 0); fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); fxp_outb(port, CSR_EEPROM, CE_EECS | b); micro_delay(EESK_PERIOD/2+1); } v= 0; for (i= 0; i<16; i++) { fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO); v= (v << 1) | b; fxp_outb(port, CSR_EEPROM, CE_EECS ); micro_delay(EESK_PERIOD/2+1); } fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */ micro_delay(EECS_DELAY); return v;}/*===========================================================================* * eeprom_addrsize * *===========================================================================*/PRIVATE void eeprom_addrsize(fp)fxp_t *fp;{ port_t port; u16_t v; int b, i; port= fp->fxp_base_port; /* Try to find out the size of the EEPROM */ fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */ v= EEPROM_READ_PREFIX; for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--) { b= ((v & (1 << i)) ? CE_EEDI : 0); fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); fxp_outb(port, CSR_EEPROM, CE_EECS | b); micro_delay(EESK_PERIOD/2+1); } for (i= 0; i<32; i++) { b= 0; fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); fxp_outb(port, CSR_EEPROM, CE_EECS | b); micro_delay(EESK_PERIOD/2+1); v= fxp_inb(port, CSR_EEPROM); if (!(v & CE_EEDO)) break; } if (i >= 32) panic("FXP","eeprom_addrsize: failed", NO_NUM); fp->fxp_ee_addrlen= i+1; /* Discard 16 data bits */ for (i= 0; i<16; i++) { fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */ micro_delay(EESK_PERIOD/2+1); fxp_outb(port, CSR_EEPROM, CE_EECS ); micro_delay(EESK_PERIOD/2+1); } fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */ micro_delay(EECS_DELAY);#if VERBOSE printf("%s EEPROM address length: %d\n", fp->fxp_name, fp->fxp_ee_addrlen);#endif}/*===========================================================================* * mii_read * *===========================================================================*/PRIVATE u16_t mii_read(fp, reg)fxp_t *fp;int reg;{ clock_t t0,t1; port_t port; u32_t v; port= fp->fxp_base_port; assert(!fp->fxp_mii_busy); fp->fxp_mii_busy++; if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY)) panic("FXP","mii_read: MDI not ready", NO_NUM); fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) | (reg << CM_REG_SHIFT)); getuptime(&t0); do { v= fxp_inl(port, CSR_MDI_CTL); if (v & CM_READY) break; } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000)); if (!(v & CM_READY)) panic("FXP","mii_read: MDI not ready after command", NO_NUM); fp->fxp_mii_busy--; assert(!fp->fxp_mii_busy); return v & CM_DATA_MASK;}/*===========================================================================* * fxp_set_timer * *===========================================================================*/PRIVATE void fxp_set_timer(tp, delta, watchdog)timer_t *tp; /* timer to be set */clock_t delta; /* in how many ticks */tmr_func_t watchdog; /* watchdog function to be called */{ clock_t now; /* current time */ int r; /* Get the current time. */ r= getuptime(&now); if (r != OK) panic("FXP","unable to get uptime from clock", r); /* Add the timer to the local timer queue. */ tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL); /* Possibly reschedule an alarm call. This happens when a new timer * is added in front. */ if (fxp_next_timeout == 0 || fxp_timers->tmr_exp_time < fxp_next_timeout) { fxp_next_timeout= fxp_timers->tmr_exp_time; #if VERBOSE printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n", fxp_next_timeout, fxp_next_timeout-now);#endif r= sys_setalarm(fxp_next_timeout, 1); if (r != OK) panic("FXP","unable to set synchronous alarm", r); }}/*===========================================================================* * fxp_expire_tmrs * *===========================================================================*/PRIVATE void fxp_expire_timers(){/* A synchronous alarm message was received. Check if there are any expired * timers. Possibly reschedule the next alarm. */ clock_t now; /* current time */ timer_t *tp; int r; /* Get the current time to compare the timers against. */ r= getuptime(&now); if (r != OK) panic("FXP","Unable to get uptime from clock.", r); /* Scan the timers queue for expired timers. Dispatch the watchdog function * for each expired timers. Possibly a new alarm call must be scheduled. */ tmrs_exptimers(&fxp_timers, now, NULL); if (fxp_timers == NULL) fxp_next_timeout= TMR_NEVER; else { /* set new alarm */ fxp_next_timeout = fxp_timers->tmr_exp_time; r= sys_setalarm(fxp_next_timeout, 1); if (r != OK) panic("FXP","Unable to set synchronous alarm.", r); }}static void micro_delay(unsigned long usecs){ tickdelay(MICROS_TO_TICKS(usecs));}static u8_t do_inb(port_t port){ int r; u32_t value; r= sys_inb(port, &value); if (r != OK) panic("FXP","sys_inb failed", r); return value;}static u32_t do_inl(port_t port){ int r; u32_t value; r= sys_inl(port, &value); if (r != OK) panic("FXP","sys_inl failed", r); return value;}static void do_outb(port_t port, u8_t value){ int r; r= sys_outb(port, value); if (r != OK) panic("FXP","sys_outb failed", r);}static void do_outl(port_t port, u32_t value){ int r; r= sys_outl(port, value); if (r != OK) panic("FXP","sys_outl failed", r);}/* * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -