📄 ae531xmac.c
字号:
/* 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 + -