📄 dev_sb1250_ethernet.c
字号:
framecfg |= V_MAC_IFG_RX_1000 | V_MAC_IFG_TX_1000 | V_MAC_IFG_THRSH_1000 | V_MAC_SLOT_SIZE_1000; cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; break; default: return 0; } /* * Send the bits back to the hardware */ SBETH_WRITECSR(s->sbe_framecfg,framecfg); SBETH_WRITECSR(s->sbe_maccfg,cfg); return 1;}/* ********************************************************************* * SBETH_SET_DUPLEX(s,duplex,fc) * * Set Ethernet duplex and flow control options for this MAC * * Input parameters: * s - sbeth structure * duplex - duplex setting (see sbeth_duplex_t) * fc - flow control setting (see sbeth_fc_t) * * Return value: * 1 if ok * 0 if an invalid parameter combination was specified ********************************************************************* */static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc){ uint64_t cfg; /* * Read current register values */ cfg = SBETH_READCSR(s->sbe_maccfg); /* * Mask off the stuff we're about to change */ cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); switch (duplex) { case sbeth_duplex_half: switch (fc) { case sbeth_fc_disabled: cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; break; case sbeth_fc_collision: cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; break; case sbeth_fc_carrier: cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; break; case sbeth_fc_frame: /* not valid in half duplex */ default: /* invalid selection */ return 0; } break; case sbeth_duplex_full: switch (fc) { case sbeth_fc_disabled: cfg |= V_MAC_FC_CMD_DISABLED; break; case sbeth_fc_frame: cfg |= V_MAC_FC_CMD_ENABLED; break; case sbeth_fc_collision: /* not valid in full duplex */ case sbeth_fc_carrier: /* not valid in full duplex */ /* fall through */ default: return 0; } break; } /* * Send the bits back to the hardware */ SBETH_WRITECSR(s->sbe_maccfg,cfg); return 1;}/* ********************************************************************* * SBETH_TRANSMIT(s,pkt,len,arg) * * Transmits a packet. * * Input parameters: * s - mac to tramsmit on * chan - DMA Channel number (0 or 1) * pkt,len - buffer and length * arg - arg for callback * * Return value: * 1 if packet was queued * 0 if packet was not queued ********************************************************************* */static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg){ return sbdma_addbuffer(&(s->sbe_txdma[chan]),pkt,length,arg);}/* ********************************************************************* * SBETH_ADDRCVBUF(s,pkt,len,arg) * * Add a receive buffer to the ring * * Input parameters: * s - mac to add rx buffer to * chan - DMA Channel number (0 or 1) * pkt,len - buffer and length * arg - arg for callback * * Return value: * 1 if packet was queued * 0 if packet was not queued ********************************************************************* */static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg){ return sbdma_addbuffer(&(s->sbe_rxdma[chan]),pkt,length,arg);}/* ********************************************************************* * SBETH_FILLRXRING(s,chan) * * Make sure there are at least "sbe_minrxring" packets on the * receive ring for this device. * * Input parameters: * s - mac structure * * Return value: * nothing ********************************************************************* */static void sbeth_fillrxring(sbeth_t *s,int chan){ sbeth_pkt_t *pkt; while (s->sbe_rxdma[chan].sbdma_onring < s->sbe_minrxring) { pkt = sbeth_alloc_pkt(s); if (!pkt) break; if (!sbeth_addrcvbuf(s,chan,pkt->buffer,pkt->length,pkt)) { sbeth_free_pkt(s,pkt); break; } }}/* ********************************************************************* * SBETH_ISR() * * Interrupt handler for MAC interrupts * * Input parameters: * MAC structure * * Return value: * nothing ********************************************************************* */static void sbeth_isr(sbeth_t *s){ uint64_t isr; for (;;) { /* * Read the ISR (this clears the bits in the real register) */ isr = SBETH_READCSR(s->sbe_isr); if (isr == 0) { break; } /* * for now, don't bother asking why we were interrupted, * just process the descriptors in any event. */ /* * Transmits on channel 0 */ if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) { sbdma_procbuffers(&(s->sbe_txdma[0]),s->sbe_txdma[0].sbdma_upcall); }#if (SBETH_DMA_CHANNELS == 2) /* * Transmits on channel 1 */ if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH1)) { sbdma_procbuffers(&(s->sbe_txdma[1]),s->sbe_txdma[1].sbdma_upcall); }#endif /* * Receives on channel 0 */ if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { sbdma_procbuffers(&(s->sbe_rxdma[0]),s->sbe_rxdma[0].sbdma_upcall); }#if (SBETH_DMA_CHANNELS == 2) /* * Receives on channel 1 */ if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH1)) { sbdma_procbuffers(&(s->sbe_rxdma[1]),s->sbe_rxdma[1].sbdma_upcall); }#endif }}/* ********************************************************************* * SBETH_MII_FINDPHY(s) * * Find the first available PHY. * * Input parameters: * s - sbeth structure * * Return value: * nothing ********************************************************************* */static void sbeth_mii_findphy(sbeth_t *s){ int phy; uint16_t bmsr; uint16_t id1, id2; for (phy = 0; phy < 31; phy++) { bmsr = sbeth_mii_read(s,phy,MII_BMSR); if (bmsr != 0) { s->sbe_phyaddr = phy; id1 = sbeth_mii_read(s,phy,MII_PHYIDR1); id2 = sbeth_mii_read(s,phy,MII_PHYIDR2); s->sbe_phyvendor = ((uint32_t)id1 << 6) | ((id2 >> 10) & 0x3F); s->sbe_phydevice = (id2 >> 4) & 0x3F;#if 0 /* for debugging */ xprintf("sbeth: found phy %d, vendor %06X part %02X\n", phy, s->sbe_phyvendor, s->sbe_phydevice);#endif return; } } s->sbe_phyaddr = 0;}/* ********************************************************************* * SBETH_MII_POLL(s) * * Ask the PHY what is going on, and configure speed appropriately. * For the moment, we only support automatic configuration. * * Input parameters: * s - sbeth structure * noisy - display console messages * * Return value: * 1 if something has changed and we should restart the channel * 0 if nothing has changed. ********************************************************************* */static int sbeth_mii_poll(sbeth_t *s,int noisy){ uint16_t bmsr,bmcr,k1stsr,anlpar; int chg; char buffer[100]; char *p = buffer; char *devname; /* Read the mode status and mode control registers. */ bmsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMSR); bmcr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR); /* get the link partner status */ anlpar = sbeth_mii_read(s,s->sbe_phyaddr,MII_ANLPAR); /* if supported, read the 1000baseT register */ if (bmsr & BMSR_1000BT_XSR) { k1stsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_K1STSR); } else { k1stsr = 0; } chg = 0; if ((s->sbe_phy_oldbmsr != bmsr) || (s->sbe_phy_oldbmcr != bmcr) || (s->sbe_phy_oldanlpar != anlpar) || (s->sbe_phy_oldk1stsr != k1stsr)) { s->sbe_phy_oldbmsr = bmsr; s->sbe_phy_oldbmcr = bmcr; s->sbe_phy_oldanlpar = anlpar; s->sbe_phy_oldk1stsr = k1stsr; chg = 1; } if (chg == 0) return 0; if (!s->sbe_autospeed) return 0; p += xsprintf(p,"Link speed: "); if (k1stsr & K1STSR_LP1KFD) { s->sbe_speed = sbeth_speed_1000; s->sbe_duplex = sbeth_duplex_full; s->sbe_fc = sbeth_fc_frame; s->sbe_linkstat = ETHER_SPEED_1000FDX; p += xsprintf(p,"1000BaseT FDX"); } else if (k1stsr & K1STSR_LP1KHD) { s->sbe_speed = sbeth_speed_1000; s->sbe_duplex = sbeth_duplex_half; s->sbe_fc = sbeth_fc_disabled; s->sbe_linkstat = ETHER_SPEED_1000HDX; p += xsprintf(p,"1000BaseT HDX"); } else if (anlpar & ANLPAR_TXFD) { s->sbe_speed = sbeth_speed_100; s->sbe_duplex = sbeth_duplex_full; s->sbe_fc = (anlpar & ANLPAR_PAUSE) ? sbeth_fc_frame : sbeth_fc_disabled; s->sbe_linkstat = ETHER_SPEED_100FDX; p += xsprintf(p,"100BaseT FDX"); } else if (anlpar & ANLPAR_TXHD) { s->sbe_speed = sbeth_speed_100; s->sbe_duplex = sbeth_duplex_half; s->sbe_fc = sbeth_fc_disabled; s->sbe_linkstat = ETHER_SPEED_100HDX; p += xsprintf(p,"100BaseT HDX"); } else if (anlpar & ANLPAR_10FD) { s->sbe_speed = sbeth_speed_10; s->sbe_duplex = sbeth_duplex_full; s->sbe_fc = sbeth_fc_frame; s->sbe_linkstat = ETHER_SPEED_10FDX; p += xsprintf(p,"10BaseT FDX"); } else if (anlpar & ANLPAR_10HD) { s->sbe_speed = sbeth_speed_10; s->sbe_duplex = sbeth_duplex_half; s->sbe_fc = sbeth_fc_collision; s->sbe_linkstat = ETHER_SPEED_10HDX; p += xsprintf(p,"10BaseT HDX"); } else { s->sbe_linkstat = ETHER_SPEED_UNKNOWN; p += xsprintf(p,"Unknown"); }#if defined(_BCM91120C_DIAG_CFG_) || defined(_BCM91125C_DIAG_CFG_) || \ defined(_CSWARM_DIAG_CFG_) || defined(_CSWARM_DIAG3E_CFG_) || \ defined(_PTSWARM_DIAG_CFG_) || defined(_PTSWARM_CFG_) noisy = 0;#endif if (noisy) { devname = s->sbe_devctx ? cfe_device_name(s->sbe_devctx) : "eth?"; console_log("%s: %s",devname,buffer); } return 1;}/* ********************************************************************* * SBETH_MII_SETUP(s) * * * Input parameters: * s - sbeth * * Various boards have PHYs that are incorrectly strapped or * need other preconfiguration to enable autonegotiation and * establish a valid link. * * Return value: * TRUE if we were on a 5411 ********************************************************************* */static int sbeth_mii_setup(sbeth_t *s){ if (s->sbe_phyvendor == OUI_BCM) { int phy_addr = s->sbe_phyaddr; switch (s->sbe_phydevice) { case DEV_BCM5411: /* The CSWARM boards leave the PHYs in JTAG mode. The * sequence * below turns off JTAG mode and puts the * PHYs back * into their regular reset state. This * is only used with the BCM5411 */ /* clear ext loopback */ sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0420); /* clear swap rx MDIX/TXHalfOut bits */ sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0004); /* set up 10/100 advertisement */ sbeth_mii_write(s,phy_addr,MII_ANAR,0x01E1); /* set up 1000 advertisement */ sbeth_mii_write(s,phy_addr,MII_K1CTL,0x0300); /* set autonegotiate bit and restart autoneg */ sbeth_mii_write(s,phy_addr,MII_BMCR,0x1340); break; case DEV_BCM5421: /* * Make sure that the part is in GMII, not SGMII. * This was a problem with 5421 A0 silicon * the FDX pin */ sbeth_mii_write(s,phy_addr,0x18,0x0392); break; case DEV_BCM5461: /* Note: The bcm5461 and bcm5461S have the same device code. The following is for a 5461S. */#if defined(_BCM91125CPCI_) { /* The 5461S attached to the 1125 MAC is for GMII to copper but is strapped for GMII to SerDes with autodetect enabled. That leaves the wrong set of PHY registers visible. */ uint16_t mode_ctrl, auto_det;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -