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

📄 ae531xmac.c

📁 atheros ar531x ethernet driver
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* Initialize Rx buffer descriptors */    for (i=0, descAddr=q->firstDescAddr;         i<count;         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE))    {        void *swptr;        char *rxBuffer;        int  rxBufferSize;        swptr = ae531x_rxbuf_alloc(MACInfo, &rxBuffer, &rxBufferSize);        if (swptr == NULL) {                AE531X_PRINT(AE531X_DEBUG_RESET,                          ("ethmac%d RX queue: ae531x_rxbuf_alloc failed\n",                           MACInfo->unit));                ae531x_QueueDestroy(q);                return -1;        }        AE531X_DESC_SWPTR_SET(descAddr, swptr);        AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);        AE531X_DESC_CTRLEN_SET(descAddr, rxBufferSize);        AE531X_DESC_BUFPTR_SET(descAddr, virt_to_bus(rxBuffer));        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);    } /* for each desc */    /* Make the queue circular */    AE531X_DESC_CTRLEN_SET(q->lastDescAddr,                       DescEndOfRing|AE531X_DESC_CTRLEN_GET(q->lastDescAddr));    AE531X_PRINT(AE531X_DEBUG_RESET,              ("ethmac%d Rxbuf begin = %x, end = %x\n",              MACInfo->unit,              (UINT32)q->firstDescAddr,              (UINT32)q->lastDescAddr));    LEAVE();    return 0;}/******************************************************************************* ae531x_QueueDestroy -- Free all buffers and descriptors associated * with a queue.*/static voidae531x_QueueDestroy(AE531X_QUEUE *q){    int i;    int count;    VIRT_ADDR    descAddr;    ARRIVE();    count = q->count;    for (i=0, descAddr=q->firstDescAddr;         i<count;         i++, descAddr=(VIRT_ADDR)((UINT32)descAddr + AE531X_QUEUE_ELE_SIZE)) {        AE531X_DESC_STATUS_SET(descAddr, 0);        AE531X_DESC_CTRLEN_SET(descAddr, 0);        AE531X_DESC_BUFPTR_SET(descAddr, (UINT32)0);        AE531X_DESC_LNKBUF_SET(descAddr, (UINT32)0);        ae531x_swptr_free(descAddr); /* Free OS-specific software pointer */    }    LEAVE();}static voidae531x_TxQueueDestroy(ae531x_MAC_t *MACInfo){    ae531x_QueueDestroy(&MACInfo->txQueue);}static voidae531x_RxQueueDestroy(ae531x_MAC_t *MACInfo){    ae531x_QueueDestroy(&MACInfo->rxQueue);}/******************************************************************************* ae531x_AllocateQueues - Allocate receive and transmit queues*/intae531x_AllocateQueues(ae531x_MAC_t *MACInfo){    size_t QMemSize;    char *pTxBuf = NULL;    char *pRxBuf = NULL;    ARRIVE();    MACInfo->txDescCount = AE531X_TX_DESC_COUNT_DEFAULT;    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->txDescCount;    pTxBuf = MALLOC(QMemSize);    if (pTxBuf == NULL) {        AE531X_PRINT(AE531X_DEBUG_RESET,                  ("ethmac%d Failed to allocate TX queue\n", MACInfo->unit));        goto AllocQFail;    }    if (ae531x_TxQueueCreate(MACInfo, &MACInfo->txQueue, pTxBuf,                          MACInfo->txDescCount) < 0)    {        AE531X_PRINT(AE531X_DEBUG_RESET,                ("ethmac%d Failed to create TX queue\n", MACInfo->unit));        goto AllocQFail;    }    MACInfo->rxDescCount = AE531X_RX_DESC_COUNT_DEFAULT;    QMemSize = AE531X_QUEUE_ELE_SIZE * MACInfo->rxDescCount;    pRxBuf = MALLOC(QMemSize);    if (pRxBuf == NULL) {        AE531X_PRINT(AE531X_DEBUG_RESET,                  ("ethmac%d Failed to allocate RX queue\n", MACInfo->unit));        goto AllocQFail;    }    if (ae531x_RxQueueCreate(MACInfo, &MACInfo->rxQueue, pRxBuf,                          MACInfo->rxDescCount) < 0)    {        AE531X_PRINT(AE531X_DEBUG_RESET,                ("ethmac%d Failed to create RX queue\n", MACInfo->unit));        goto AllocQFail;    }    AE531X_PRINT(AE531X_DEBUG_RESET,            ("ethmac%d Memory setup complete.\n", MACInfo->unit));    LEAVE();    return 0;AllocQFail:    MACInfo->txDescCount = 0; /* sanity */    MACInfo->rxDescCount = 0; /* sanity */    if (pTxBuf) {        FREE(pTxBuf);    }    if (pRxBuf) {        FREE(pRxBuf);    }        LEAVE();    return -1;}/******************************************************************************** ae531x_FreeQueues - Free Transmit & Receive queues*/voidae531x_FreeQueues(ae531x_MAC_t *MACInfo){    ae531x_TxQueueDestroy(MACInfo);    FREE(MACInfo->txQueue.firstDescAddr);    ae531x_RxQueueDestroy(MACInfo);    FREE(MACInfo->rxQueue.firstDescAddr);}/******************************************************************************** ae531x_DmaReset - Reset DMA and TLI controllers** RETURNS: N/A*/voidae531x_DmaReset(ae531x_MAC_t *MACInfo){    int        i;    UINT32     descAddr;    ARRIVE();    /* Disable device interrupts prior to any errors during stop */    intDisable(MACInfo->ilevel);    /* Disable MAC rx and tx */    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));    udelay(1);    /* Reset dma controller */        ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaResetOn);    /* Delay 2 usec */    sysUDelay(2);    /* Flush the rx queue */    descAddr = (UINT32)MACInfo->rxQueue.firstDescAddr;    MACInfo->rxQueue.curDescAddr = MACInfo->rxQueue.firstDescAddr;    for (i=0;         i<(MACInfo->rxDescCount);         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {            AE531X_DESC_STATUS_SET(descAddr, DescOwnByDma);    }    /* Flush the tx queue */    descAddr = (UINT32)MACInfo->txQueue.firstDescAddr;    MACInfo->txQueue.curDescAddr = MACInfo->txQueue.firstDescAddr;    MACInfo->txQueue.reapDescAddr = MACInfo->txQueue.lastDescAddr;    for (i=0;         i<(MACInfo->txDescCount);         i++, descAddr += AE531X_QUEUE_ELE_SIZE) {            AE531X_DESC_STATUS_SET (descAddr, 0);    }    /* Set init register values  */    ae531x_WriteDmaReg(MACInfo, DmaBusMode, DmaBusModeInit);    /* Install the first Tx and Rx queues on the device */    ae531x_WriteDmaReg(MACInfo, DmaRxBaseAddr,                      virt_to_bus(MACInfo->rxQueue.firstDescAddr));    ae531x_WriteDmaReg(MACInfo, DmaTxBaseAddr,                      virt_to_bus(MACInfo->txQueue.firstDescAddr));#if 0    ae531x_WriteDmaReg(MACInfo, DmaControl, DmaStoreAndForward);#else    //ae531x_WriteDmaReg(MACInfo, DmaControl, DmaTxSecondFrame | DmaTxThreshCtl256);    ae531x_WriteDmaReg(MACInfo, DmaControl, DmaTxThreshCtl032);#endif     ae531x_WriteDmaReg(MACInfo, DmaIntrEnb, DmaIntDisable);    AE531X_PRINT(AE531X_DEBUG_RESET,              ("ethmac%d: DMA RESET!\n", MACInfo->unit));    /* Turn on device interrupts -- enable most errors */    ae531x_DmaIntClear(MACInfo);    /* clear interrupt requests  */    ae531x_DmaIntEnable(MACInfo);   /* enable interrupts */    ae531x_EndResetMode(MACInfo);    intEnable(MACInfo->ilevel);    LEAVE();}/******************************************************************************** ae531x_MACAddressSet - Set the ethernet address** Sets the ethernet address according to settings in flash.** RETURNS: void*/static voidae531x_MACAddressSet(ae531x_MAC_t *MACInfo){    unsigned int    data;    UINT8 *macAddr;    ARRIVE();            macAddr = ae531x_enet_mac_address_get(MACInfo->unit);    /* set our MAC address  */    data = (macAddr[5]<<8) | macAddr[4];    ae531x_WriteMacReg(MACInfo, MacAddrHigh, data );    data = (macAddr[3]<<24) | (macAddr[2]<<16) | (macAddr[1]<<8) | macAddr[0];    ae531x_WriteMacReg(MACInfo, MacAddrLow, data );    AE531X_PRINT(AE531X_DEBUG_RESET,              ("ethmac%d Verify MAC address %8.8X %8.8X \n",               MACInfo->unit,               ae531x_ReadMacReg(MACInfo, MacAddrLow),               ae531x_ReadMacReg(MACInfo, MacAddrHigh)));    AE531X_PRINT(AE531X_DEBUG_RESET,              ("  sb = %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",               0xff&macAddr[0],               0xff&macAddr[1],               0xff&macAddr[2],               0xff&macAddr[3],               0xff&macAddr[4],               0xff&macAddr[5]));    LEAVE();}/******************************************************************************** ae_SetMACFromPhy - read Phy settings and update Mac*                    with current duplex and speed.** RETURNS:*/static voidae531x_SetMACFromPhy(ae531x_MAC_t *MACInfo){    UINT32  macCtl;    BOOL    fullDuplex;    UINT32  timeout;    ARRIVE();    timeout = jiffies+(HZ/1000)*AE531X_NEGOT_TIMEOUT;    /* Get duplex mode from Phy */    while (((fullDuplex = phyIsFullDuplex(MACInfo->unit)) == -1) &&	   (jiffies <= timeout));    /* Flag is set for full duplex mode, else cleared */    macCtl = ae531x_ReadMacReg(MACInfo, MacControl);    if (1/*fullDuplex*/) {        /* set values of control registers */        macCtl &= ~MacDisableRxOwn;        macCtl |= MacFullDuplex;        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitFdx);    } else {	/* set values of control registers */        ae531x_WriteMacReg(MACInfo, MacFlowControl, MacFlowControlInitHdx);        macCtl |= MacDisableRxOwn;        macCtl &= ~MacFullDuplex;        ae531x_WriteMacReg(MACInfo, MacControl, macCtl);    }    LEAVE();}/******************************************************************************* ae531x_MACReset -- sets MAC address and duplex.*/voidae531x_MACReset(ae531x_MAC_t *MACInfo){    ae531x_MACAddressSet(MACInfo);#ifndef CONFIG_AR531X_COBRA    ae531x_SetMACFromPhy(MACInfo);#endif}/******************************************************************************* ae531x_EnableComm -- enable Transmit and Receive*/voidae531x_EnableComm(ae531x_MAC_t *MACInfo){    ae531x_SetMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));    ae531x_DmaRxStart(MACInfo);     /* start receiver  */    ae531x_DmaTxStart(MACInfo);     /* start transmitter */}/******************************************************************************* ae531x_DisableComm -- disable Transmit and Receive*/voidae531x_DisableComm(ae531x_MAC_t *MACInfo){    ae531x_ClearMacReg(MACInfo, MacControl, (MacRxEnable | MacTxEnable));}/******************************************************************************* ae531x_reset -- Cold reset ethernet interface*/voidae531x_reset(ae531x_MAC_t *MACInfo){    UINT32 mask = 0;    UINT32 regtmp;#ifndef CONFIG_AR531X_COBRA       if (MACInfo->unit == 0) {        mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;    } else {        mask = AR531X_RESET_ENET1 | AR531X_RESET_EPHY1;    }    /* Put into reset */    regtmp = sysRegRead(AR531X_RESET);    sysRegWrite(AR531X_RESET, regtmp | mask);    sysMsDelay(15);    /* Pull out of reset */    regtmp = sysRegRead(AR531X_RESET);    sysRegWrite(AR531X_RESET, regtmp & ~mask);    sysUDelay(25);    /* Enable */    if (MACInfo->unit == 0) {        mask = AR531X_ENABLE_ENET0;    } else {        mask = AR531X_ENABLE_ENET1;    }    regtmp = sysRegRead(AR531X_ENABLE);    sysRegWrite(AR531X_ENABLE, regtmp | mask);#else    if (MACInfo->unit == 0) {        mask = AR531X_RESET_ENET0 | AR531X_RESET_EPHY0;    }    /* Enable Arbitration for Ethernet bus */    regtmp = sysRegRead(AR531XPLUS_AHB_ARB_CTL);    regtmp |= ARB_ETHERNET;    sysRegWrite(AR531XPLUS_AHB_ARB_CTL, regtmp);    /* Put into reset */    regtmp = sysRegRead(AR531X_RESET);    sysRegWrite(AR531X_RESET, regtmp | mask);    sysMsDelay(10);    /* Pull out of reset */    regtmp = sysRegRead(AR531X_RESET);    sysRegWrite(AR531X_RESET, regtmp & ~mask);    sysMsDelay(10);    regtmp = sysRegRead(AR531XPLUS_IF_CTL);    regtmp |= IF_TS_LOCAL;    sysRegWrite(AR531XPLUS_IF_CTL, regtmp);#endif}/******************************************************************************* ae531x_unitLinkLost -- Called from PHY layer to notify the MAC layer* that there are no longer any live links associated with a MAC.*/voidae531x_unitLinkLost(int ethUnit){    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,             ("enetmac%d link down\n", ethUnit));}/******************************************************************************* ae531x_unitLinkGained -- Called from PHY layer to notify the MAC layer* that there are 1 or more live links associated with a MAC.*/voidae531x_unitLinkGained(int ethUnit){#if CONFIG_AR531X_COBRA#define AE531X_POLL_MILLI_SECONDS 200     ae531x_MAC_t *MACInfo = ae531x_getMAcInfo(ethUnit);    while(!MACInfo || !MACInfo->port_is_up)    {        set_current_state(TASK_UNINTERRUPTIBLE);        schedule_timeout((AE531X_POLL_MILLI_SECONDS * HZ)/1000);        MACInfo = ae531x_getMAcInfo(ethUnit);    }    ae531x_SetMACFromPhy(MACInfo);#endif    AE531X_PRINT(AE531X_DEBUG_LINK_CHANGE,             ("enet%d link up\n", ethUnit));}/******************************************************************************* ae531x_ethMacDefault -- Called from PHY layer to determine the default* ethernet MAC.  On some "twisted" platforms, the only usable MAC is 1,* while on others the usable MAC is 0.  Future boards may allow both MACs* to be used; in this case, return -1 to indicate that there IS NO default* MAC.*/intae531x_ethMacDefault(void){    if (ae531x_twisted_enet())        return 1;    return 0;}

⌨️ 快捷键说明

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