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

📄 esmcend.c

📁 基于嵌入式操作系统VxWorks的lan91c111的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* 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 + -