⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mvphy.c

📁 atheros ar531x ethernet driver
💻 C
📖 第 1 页 / 共 3 页
字号:
* RETURNS:*    TRUE  --> at least 1 PHY with LINK*    FALSE --> no LINKs on this ethernet unit*/BOOLmv_phySetup(int ethUnit, UINT32 phyBase){    int     phyUnit;    int     liveLinks = 0;    BOOL    foundPhy = FALSE;    UINT32  phyAddr;    UINT16  atuControl;    /*     * Allow platform-specific code to determine the default Ethernet MAC     * at run-time.  If phyEthMacDefault returns a negative value, use the     * static mvPhyInfo table "as is".  But if phyEthMacDefault returns a     * non-negative value, use it as the default ethernet unit.     */    {        int ethMacDefault = phyEthMacDefault();        if (ethMacDefault >= 0) {            for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {                MV_ETHUNIT(phyUnit)=ethMacDefault;            }        }    }    /*     * See if there's any configuration data for this enet,     * and set up phyBase in table.     */    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {        if (MV_ETHUNIT(phyUnit) != ethUnit) {            continue;        }        MV_PHYBASE(phyUnit) = phyBase;        MV_PRINT(MV_DEBUG_PHYSETUP,("phyBase =%x unit = %d\n",phyBase, phyUnit ));        foundPhy = TRUE;    }    if (!foundPhy) {        return FALSE; /* No PHY's configured for this ethUnit */    }    /* Verify that the switch is what we think it is, and that it's ready */    mv_verifyReady(ethUnit);    /* Initialize global switch settings */    atuControl  = MV_ATUCTRL_AGE_TIME_DEFAULT << MV_ATUCTRL_AGE_TIME_SHIFT;    atuControl |= MV_ATUCTRL_ATU_SIZE_DEFAULT << MV_ATUCTRL_ATU_SIZE_SHIFT;    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_CONTROL, atuControl);    /* Reset PHYs and start autonegoation on each. */    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {        if (MV_ETHUNIT(phyUnit) != ethUnit) {            continue;        }        phyBase = MV_PHYBASE(phyUnit);        phyAddr = MV_PHYADDR(phyUnit);        phyRegWrite(phyBase, phyAddr, MV_PHY_CONTROL,                    MV_CTRL_SOFTWARE_RESET | MV_CTRL_AUTONEGOTIATION_ENABLE);    }#if 0 /* Don't wait -- we'll detect shortly after the link comes up */{    int timeout;    UINT16  phyHwStatus;    /*     * Wait 5 seconds for ALL associated PHYs to finish autonegotiation.     */    timeout=50;    for (phyUnit=0; (phyUnit < MV_PHY_MAX) && (timeout > 0); phyUnit++) {        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        for (;;) {            phyBase = MV_PHYBASE(phyUnit);            phyAddr = MV_PHYADDR(phyUnit);            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);            if (MV_AUTONEG_DONE(phyHwStatus)) {                break;            }            if (--timeout == 0) {                break;            }            sysMsDelay(100);        }    }}#endif    /*     * All PHYs have had adequate time to autonegotiate.     * Now initialize software status.     *     * It's possible that some ports may take a bit longer     * to autonegotiate; but we can't wait forever.  They'll     * get noticed by mv_phyCheckStatusChange during regular     * polling activities.     */    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        if (mv_phyIsLinkAlive(phyUnit)) {            liveLinks++;            MV_IS_PHY_ALIVE(phyUnit) = TRUE;        } else {            MV_IS_PHY_ALIVE(phyUnit) = FALSE;        }        MV_PRINT(MV_DEBUG_PHYSETUP,            ("ethmac%d: Phy Status=%4.4x\n",            ethUnit,             phyRegRead(MV_PHYBASE(phyUnit),                       MV_PHYADDR(phyUnit),                       MV_PHY_SPECIFIC_STATUS)));    }    mv_VLANInit(ethUnit);    mv_enableConfiguredPorts(ethUnit);    return (liveLinks > 0);}/******************************************************************************** mv_phyIsDuplexFull - Determines whether the phy ports associated with the* specified device are FULL or HALF duplex.** RETURNS:*    1 --> at least one associated PHY in FULL DUPLEX*    0 --> all half duplex*   -1 --> No links*/intmv_phyIsFullDuplex(int ethUnit){    int     phyUnit;    UINT32  phyBase;    UINT32  phyAddr;    UINT16  phyHwStatus;    int     oneIsReady=0;    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        if (mv_phyIsLinkAlive(phyUnit)) {	    oneIsReady = 1;            phyBase = MV_PHYBASE(phyUnit);            phyAddr = MV_PHYADDR(phyUnit);            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);            if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {//            	printf("full duplex mode\n");                return 1;            }        }    }    if (oneIsReady)    {//	printf("half duplex mode\n");	return 0;    }	    else	return -1;}/******************************************************************************** mv_phyIsSpeed100 - Determines the speed of a phy port** RETURNS:*    TRUE --> PHY operating at 100 Mbit*    FALSE --> link down, or not operating at 100 Mbit*/BOOLmv_phyIsSpeed100(int phyUnit){    UINT16  phyHwStatus;    UINT32  phyBase;    UINT32  phyAddr;    if (MV_IS_ENET_PORT(phyUnit)) {        if (mv_phyIsLinkAlive(phyUnit)) {            phyBase = MV_PHYBASE(phyUnit);            phyAddr = MV_PHYADDR(phyUnit);            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);            if (phyHwStatus & MV_STATUS_RESOLVED_SPEED_100) {                return TRUE;            }        }    }    return FALSE;}BOOLmv_phyIsFullDuplex_ext(int phyUnit){    UINT16  phyHwStatus;    UINT32  phyBase;    UINT32  phyAddr;    if (MV_IS_ENET_PORT(phyUnit)) {        if (mv_phyIsLinkAlive(phyUnit)) {            phyBase = MV_PHYBASE(phyUnit);            phyAddr = MV_PHYADDR(phyUnit);            phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);            if (phyHwStatus & MV_STATUS_RESOLVED_DUPLEX_FULL) {                return TRUE;            }        }    }    return FALSE;}#ifdef CONFIG_VENETDEV_ATH/******************************************************************************** mv_phyDetermineSource - Examine a received frame's Egress Trailer* to determine whether it came from a LAN or WAN port.** RETURNS:*    Sets *pFromLAN: 1-->LAN, 0-->WAN*    Modifies *pLen to remove PHY trailer from frame*/#define IFLAN  1#define IFWAN  0voidmv_phyDetermineSource(char *data, int len, int *pFromLAN){    unsigned char *phyTrailer;    unsigned char incomingPort;    #ifdef HEADER_MODE    incomingPort = data[1];#else    phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];//    ASSERT(phyTrailer[0] == MV_EGRESS_TRAILER_VALID);    incomingPort = phyTrailer[1];#endif         if (MV_IS_LAN_PORT(incomingPort)) {        *pFromLAN = IFLAN;    } else {//        ASSERT(MV_IS_WAN_PORT(incomingPort));        *pFromLAN = IFWAN;    }     }/******************************************************************************** mv_phySetDestinationPort - Set the Ingress Trailer to force the* frame to be sent to LAN or WAN, as specified.**/voidmv_phySetDestinationPort(char *data, int len, int from){    char *phyTrailer;#ifdef HEADER_MODE    char *phyHeader;    phyHeader = &data[0];    if (from == IFLAN) {        /* LAN ports: Use default settings, as per mvPhyInfo */        phyHeader[0] = 0x00;        phyHeader[1] = 0x0f;    } else {        /* WAN port: Direct to WAN port */        phyHeader[0] = 0x10;        phyHeader[1] = 1 << MV_WAN_PORT;    }        #else	    phyTrailer = &data[len - MV_PHY_TRAILER_SIZE];    if (from == IFLAN) {        /* LAN ports: Use default settings, as per mvPhyInfo */        phyTrailer[0] = 0x00;//MV_INGRESS_TRAILER_OVERRIDE;        phyTrailer[1] = 0x0f;//0x00;    } else {        /* WAN port: Direct to WAN port */        phyTrailer[0] = MV_INGRESS_TRAILER_OVERRIDE;        phyTrailer[1] = 1 << MV_WAN_PORT;    }    phyTrailer[2] = 0x00;    phyTrailer[3] = 0x00;#endif     }#endif/******************************************************************************* Validate that the specified PHY unit number is a valid PHY ID.* Print a message if it is invalid.* RETURNS*   TRUE  --> valid*   FALSE --> invalid*/LOCAL BOOLmv_validPhyId(int phyUnit){    if ((phyUnit >= MV_ID_MIN) && (phyUnit <= MV_ID_MAX)) {        return TRUE;    } else {        PRINTF("PHY unit number must be in the range [%d..%d]\n",            MV_ID_MIN, MV_ID_MAX);        return FALSE;    } }/******************************************************************************* mv_waitWhileATUBusy - spins until the ATU completes* its previous operation.*/LOCAL voidmv_waitWhileATUBusy(UINT32 phyBase){    BOOL   isBusy;    UINT16 ATUOperation;    do {        ATUOperation = phyRegRead(phyBase, MV_SWITCH_GLOBAL_ADDR,                                  MV_ATU_OPERATION);        isBusy = (ATUOperation & MV_ATU_BUSY_MASK) == MV_ATU_IS_BUSY;    } while(isBusy);}/******************************************************************************* mv_flushATUDB - flushes ALL entries in the Address Translation Unit* DataBase associated with phyUnit.  [Since we use a single DB for* all PHYs, this flushes the entire shared DataBase.]** The current implementation flushes even more than absolutely needed --* it flushes all entries for all phyUnits on the same ethernet as the* specified phyUnit.** It is called only when a link failure is detected on a port that was* previously working.  In other words, when the cable is unplugged.*/voidmv_flushATUDB(int phyUnit){    UINT32 phyBase;    if (!mv_validPhyId(phyUnit)) {        PRINTF("Invalid port number: %d\n", phyUnit);        return;    }    phyBase = MV_PHYBASE(phyUnit);        /* Wait for previous operation (if any) to complete */    mv_waitWhileATUBusy(phyBase);    /* Tell hardware to flush all entries */    phyRegWrite(phyBase, MV_SWITCH_GLOBAL_ADDR, MV_ATU_OPERATION,                 MV_ATU_OP_FLUSH_ALL | MV_ATU_IS_BUSY);    mv_waitWhileATUBusy(phyBase);} /******************************************************************************* mv_phyCheckStatusChange -- checks for significant changes in PHY state.** A "significant change" is:*     dropped link (e.g. ethernet cable unplugged) OR*     autonegotiation completed + link (e.g. ethernet cable plugged in)*/voidmv_phyCheckStatusChange(int ethUnit){    int           phyUnit;    UINT16        phyHwStatus;    mvPhyInfo_t   *lastStatus;    int           linkCount   = 0;    int           lostLinks   = 0;    int           gainedLinks = 0;    UINT32        phyBase;    UINT32        phyAddr;    for (phyUnit=0; phyUnit < MV_PHY_MAX; phyUnit++) {        if (!MV_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        phyBase = MV_PHYBASE(phyUnit);        phyAddr = MV_PHYADDR(phyUnit);        lastStatus = &mvPhyInfo[phyUnit];        phyHwStatus = phyRegRead(phyBase, phyAddr, MV_PHY_SPECIFIC_STATUS);        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */            /* See if we've lost link */            if (phyHwStatus & MV_STATUS_REAL_TIME_LINK_UP) {                linkCount++;            } else {                lostLinks++;                mv_flushATUDB(phyUnit);                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d down\n",                                               ethUnit, phyUnit));                lastStatus->isPhyAlive = FALSE;            }        } else { /* last known link status was DEAD */            /* Check for AutoNegotiation complete */            if (MV_AUTONEG_DONE(phyHwStatus)) {                gainedLinks++;		linkCount++;                MV_PRINT(MV_DEBUG_PHYCHANGE,("\nethmac%d port%d up\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -