?? esmcend.c
字號:
/* Output Register Address */ for (i=4;i>=0;i--) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | ((RegAdd>>i) & 0x01) ); /* Implement Turnaround ('Z0') */ esmcClkMDIO(pDev, MII_MGMTval); #ifndef ESMC_LAN91C111 esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE);#endif /* Read Data */ wData = 0; for (i=15;i>=0;i--) {#ifdef ESMC_LAN91C111 WRITE_WORD(pDev, ESMC_MGMT, MII_MGMTval); WRITE_WORD(pDev, ESMC_MGMT, MII_MGMTval | ESMC_MGMT_MCLK); taskDelay (1); wData |= (((READ_WORD(pDev, ESMC_MGMT) & ESMC_MGMT_MDI) >> 1) << i); WRITE_WORD(pDev, ESMC_MGMT, MII_MGMTval);#else esmcClkMDIO(pDev, MII_MGMTval); wData |= (((READ_WORD(pDev,ESMC_MGMT) & ESMC_MGMT_MDI) >> 1) << i); #endif } #ifdef ESMC_LAN91C111 /* Send the Turnaround ('Z0') */ esmcClkMDIO(pDev, MII_MGMTval); #endif return (wData); } /********************************************************************************* mdioWrite - Write the MDI pin of the ESMC_MGMT register** RETURNS: N/A*/LOCAL void mdioWrite ( ESMC_DEVICE* pDev, unsigned char RegAdd, unsigned short data ) { int i; unsigned short MII_MGMTval; ESMC_SWITCH_BANK(pDev, 3); MII_MGMTval = READ_WORD(pDev, ESMC_MGMT); MII_MGMTval &= 0xfff0; /* masking off lowest nibble */ /* Output Preamble (32 '1's) */ for (i=0;i<32;i++) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | ESMC_MGMT_MDO); /* Output Start of Frame ('01') */ for (i=0;i<2;i++) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | i); /* Output OPCode ('01' for write or '10' for Read) */ esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | 0 ); esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | 1 ); /* Output PHY Address */ for (i=4;i>=0;i--) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | ((pDev->phyAddr>>i) & 0x01) ); /* Output Register Address */ for (i=4;i>=0;i--) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | ((RegAdd>>i) & 0x01) ); /* Implement Turnaround ('10') */ esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | 1 ); esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | 0 ); /* Write Data */ for (i=15;i>=0;i--) esmcClkMDIO(pDev, MII_MGMTval | ESMC_MGMT_MDOE | ((data>>i) & 0x01)); }/********************************************************************************* phyResetLAN91C111- reset LAN91C111 PHY** RETURNS: N/A*/LOCAL void phyResetLAN91C111 ( ESMC_DEVICE *pDev /* Pointer to device instance data */ ) { unsigned short rv = 0; unsigned short ID1; unsigned short ID2; unsigned short dataMacRPCR; unsigned short dataPhyCtrl; int timeout; int ticksPerSec = sysClkRateGet (); /* Reset the PHY, setting all other bits to zero */ mdioWrite(pDev, PHY_CONTROL, PHY_CTRL_RESET); /* * The loop delays for 125ms in order for the reset to complete. * If after 125ms the device hasn't reset, we wait for another 125ms. * We keep trying for this for 3 seconds before giving up. */ timeout = 24; /* 125ms * 24 = 3 seconds */ while (timeout--) { if (((rv = mdioRead(pDev, PHY_CONTROL)) & PHY_CTRL_RESET) == 0) { /* reset complete */ break; } taskDelay (ticksPerSec / 8); /* delay for 125ms */ } if (timeout < 1) { DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111 PHY reset not completed, timeout: %d, PHY_CONTROL: 0x%x\n", timeout, (int)rv, 3, 4, 5, 6); } DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: PHY reset completed, timeout: %d, PHY_CONTROL: 0x%x\n", timeout, (int)rv, 3, 4, 5, 6); /* Configure PHY Interrupt Mask register */ mdioWrite(pDev, PHY_MASK_REG, PHY_MASK_LNKFAIL | PHY_MASK_INT | PHY_MASK_LOSSSYNC | PHY_MASK_CWRD | PHY_MASK_SSD | PHY_MASK_ESD | PHY_MASK_RPOL | PHY_MASK_JAB | PHY_MASK_SPDDET | PHY_MASK_DPLXDET); /* If speed or duplex are equal to 2, we must auto-negotiation. */ if ((pDev->speed == 2) || (pDev->duplex == 2)) { /* Configure for auto-negotiation mode */ /* Configure the Receive/Phy Control register */ DRV_LOG (DRV_DEBUG_FN_TRACE, "((pDev->speed == 2) || (pDev->duplex == 2))" ,1, 2, 3, 4, 5, 6); ESMC_SWITCH_BANK(pDev, 0); WRITE_WORD(pDev, ESMC_RPCR, ESMC_RPCR_DEFAULT | ESMC_RPCR_ANEG); /* Update our Auto-Neg Advertisement Register */ mdioWrite (pDev, PHY_AUTO_AD, PHY_AUTO_AD_TA3 | PHY_AUTO_AD_TA2 | PHY_AUTO_AD_TA1 | PHY_AUTO_AD_TA0 | PHY_AUTO_AD_S0); /* Start auto-negotiation process */ mdioWrite (pDev, PHY_CONTROL, PHY_CTRL_NWAYEN | PHY_CTRL_NWAYREST); /* * The loop delays for 250ms in order for the auto-negitiation to complete. * If after 250ms a remote fault is reported, the process is restarted. * We keep trying for this for 3 seconds before giving up. */ timeout = 12; /* 250ms * 12 = 3 seconds */ while (timeout--) { taskDelay (ticksPerSec / 4); /* delay for 250ms */ rv = mdioRead(pDev, PHY_STATUS); DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: 2. Auto-negotiation, timeout: %d, PHY_STATUS: 0x%x\n", timeout, (int)rv, 3, 4, 5, 6); if (rv & PHY_STAT_NWAY_COMP) { /* auto-negotiate complete OK */ DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: Auto-negotiation OK, PHY_STATUS 0x%x\n", (int)rv, 2, 3, 4, 5, 6); break; } /* Restart auto-negotiation if remote fault */ if (rv & PHY_STAT_REM_FAULT) { /* Restart auto-negotiation */ mdioWrite(pDev, PHY_CONTROL, PHY_CTRL_NWAYEN | PHY_CTRL_NWAYREST | PHY_CTRL_SPEED | PHY_CTRL_DUPLEX); } } } else { /* Configure speed & duplex manually. */ /* Configure the Receive/Phy Control register */ dataMacRPCR = 0; dataPhyCtrl = 0; ESMC_SWITCH_BANK (pDev, 0); if (pDev->speed == 1) { /* 100MBPS */ dataMacRPCR |= ESMC_RPCR_SPEED; dataPhyCtrl |= PHY_CTRL_SPEED; } /* Set to Half or Full Duplex if necessary */ if (pDev->duplex == 1) { /* Full duplex */ dataMacRPCR |= ESMC_RPCR_DPLX; dataPhyCtrl |= PHY_CTRL_DUPLEX; } WRITE_WORD (pDev, ESMC_RPCR, dataMacRPCR | ESMC_RPCR_DEFAULT); mdioWrite (pDev, PHY_CONTROL, dataPhyCtrl); } /* Display the PHY ID registers */ ID1 = mdioRead(pDev, PHY_ID1); ID2 = mdioRead(pDev, PHY_ID2); DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: ID1 0x%x ID2 0x%x\n", ID1, ID2, 3, 4, 5, 6); (void)mdioRead(pDev, PHY_STATUS_OUTPUT); /* Read out old latched values */ rv = mdioRead(pDev, PHY_STATUS_OUTPUT); /* Read current status */ DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: STATUS_OUTPUT 0x%x\n", rv, 2, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_FN_TRACE, "phyResetLAN91C111: Device in %s MBPS Mode and %s duplex\n", (rv & PHY_STATUS_SPDDET) ? (int)"100" : (int)"10", (rv & PHY_STATUS_DPLXDET) ? (int)"full" : (int)"half", 3, 4, 5, 6); //sleep(2); }/********************************************************************************* phyReset- reset PHY** RETURNS: N/A*/LOCAL void phyReset ( ESMC_DEVICE *pDev ) { int rtn; unsigned short val1, val2; int setVal; int i; if (pDev->phyAddr == -1) { /* Read the ID of the register*/ for (i=0; i <= 0x1f; i++) { pDev->phyAddr = i; val1 = mdioRead(pDev, PHY_ID1); val2 = mdioRead(pDev, PHY_ID2); val2 &= 0xff00; DRV_LOG(DRV_DEBUG_CONFIG,"The val1 is 0x%x and vl2 is 0x%x for i = %d\n", val1, val2, i,4,5,6); if (val1 == PHY_SMSC83C180_ID1 && val2 == PHY_SMSC83C180_ID2) break; } } /* reset PHY */ mdioWrite(pDev, PHY_CONTROL, 0x8000); /* Wait for the reset bit to be cleared*/ while (1) { rtn = mdioRead(pDev, PHY_CONTROL); if (!(rtn & 0x8000)) break; } setVal = 0; /* Set to 100Mbits per sec if necessary */ if (pDev->speed == 1) { setVal |= 0x2000; } /* Set to Half or Full Duplex if necessary */ if (pDev->duplex == 1) { setVal |= 0x0100; } mdioWrite(pDev, PHY_CONTROL, setVal); rtn = mdioRead(pDev, PHY_CONTROL);}/********************************************************************************* esmcChipReset - reset SMC91c9x chip** RETURNS: N/A*/LOCAL void esmcChipReset ( ESMC_DEVICE *pDev ) { unsigned short val; DRV_LOG (DRV_DEBUG_FN_TRACE, "%s%d: esmcChipReset\n", (int) DEV_NAME, pDev->unit, 3, 4, 5, 6); ESMC_SWITCH_BANK (pDev, 2); WRITE_WORD(pDev,ESMC_INTERRUPT_, 0); /* lock INT */ ESMC_SWITCH_BANK (pDev,0); val = READ_WORD(pDev, ESMC_RCR); WRITE_WORD (pDev, ESMC_RCR, ESMC_RCR_EPH_RST); /* software reset */ val = READ_WORD(pDev, ESMC_RCR); WRITE_WORD (pDev, ESMC_RCR, 0x0000); /* RX disable */ WRITE_WORD (pDev, ESMC_TCR, 0x0000); /* TX disable */ if (pDev->chipId != LAN91C111) { /* Program buffer size */ WRITE_WORD(pDev, ESMC_MCR, 0x0006); /* 1532 bytes */ } ESMC_SWITCH_BANK (pDev,1); if (pDev->chipId == LAN91C100FD) { val = READ_WORD (pDev, ESMC_CONFIG); WRITE_WORD (pDev, ESMC_CONFIG, val | ESMC_CFG_NO_WAIT_ST); } val = READ_WORD (pDev, ESMC_CONTROL); WRITE_WORD (pDev, ESMC_CONTROL, val | ESMC_CTR_AUTO_RELEASE /* TX auto release */ | ESMC_CTR_LE_ENABLE); /* link error enable */ ESMC_SWITCH_BANK (pDev,2); WRITE_WORD (pDev, ESMC_MMU, ESMC_MMU_RESET); /* MMU reset */ if (pDev->chipId == LAN91C100FD) { /* Reset the PHY chip */ phyReset( pDev); } else if (pDev->chipId == LAN91C111) { /* Reset the LAN91C111 internel PHY */ phyResetLAN91C111 (pDev); }}/********************************************************************************* esmcMemInit - initialize memory for the chip** Using data in the control structure, setup and initialize the memory* areas needed. If the memory address is not already specified, then allocate* cache safe memory.** RETURNS: OK or ERROR.*/LOCAL STATUS esmcMemInit ( ESMC_DEVICE * pDev, /* device to be initialized */ int clNum /* number of clusters to allocate */ ) { CL_DESC clDesc; /* cluster description */ M_CL_CONFIG clConfig; bzero ((char *)&clConfig, sizeof(clConfig)); bzero ((char *)&clDesc, sizeof(clDesc)); pDev->endObj.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL)); if (pDev->endObj.pNetPool == NULL) return (ERROR); clDesc.clNum = clNum; clDesc.clSize = MEM_ROUND_UP(ESMC_BUFSIZ + pDev->offset); clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 4)) + 4); clConfig.mBlkNum = clDesc.clNum * 2; clConfig.clBlkNum = clDesc.clNum; /* * mBlk and cluster configuration memory size initialization * memory size adjusted to hold the netPool pointer at the head. */ clConfig.memSize = (clConfig.mBlkNum * (M_BLK_SZ + sizeof (long))) + (clConfig.clBlkNum * (CL_BLK_SZ + sizeof (long))); clConfig.memArea = (char *) memalign(sizeof (long), clConfig.memSize);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -