📄 mac8947.c
字号:
ushort* pFrameData; ulong frameLength; ulong BdmaAddr=api_Mac_dev->BdmaAddr; REG_IN_LONG(BdmaAddr, BDMASTAT ,bdmaStat.stat_resetval); REG_OUT_LONG(BdmaAddr, BDMASTAT ,bdmaStat.stat_resetval); REG_IN_LONG(BdmaAddr, BDMARXPTR, *(ulong *)(&pReceiveFrameDesc)); if ((*(ulong *) (&(api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength)) == 0) return; do { /* * Check if Null list interrupt has occurred. If yes, reset * and restart the Ethernet MAC (as given in Samsung sample code. */ if (bdmaStat.stat_reg.bdmaRxNullList) { api_MacHWStop(api_Mac_dev); /* Stop RX and TX */ api_MacHWReset(api_Mac_dev); /* reset the chip */ api_MacBuffFree(api_Mac_dev); /* Free the FDs */ api_MacBuffInit(api_Mac_dev); /* Reinitialize FDs */ api_MacHWInit(api_Mac_dev); /* Initialize MAC */ api_MacHWStart(api_Mac_dev); /* Start RX and TX */ break; } /* * Received a good frame */ frameLength = (api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.frameLength; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.good) { api_Mac_dev->statistics.rxGood++; pFrameData = (ushort *)((api_Mac_dev->gpReceiveFrameDescStart)->rxFrameData.frameDataPtr); /* Pass the packet up to the protocol layers. */ NetRxPackets[api_Mac_dev->statistics.rxGood%RX_FD_NUM] = (uchar *)(pFrameData); NetReceive(NetRxPackets[api_Mac_dev->statistics.rxGood%RX_FD_NUM], frameLength); /*SYS_MAC_RECV(api_Mac_dev, (char *)pFrameData, frameLength); */ } else /* Update error statistics counters */ { api_Mac_dev->statistics.rxBad++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.ovMax) api_Mac_dev->statistics.rxOvMaxSize++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.ctlRcv) api_Mac_dev->statistics.rxCtlRecd++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.rx10Stat) api_Mac_dev->statistics.rx10Stat++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.alignErr) api_Mac_dev->statistics.rxAlignErr++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.crcErr) api_Mac_dev->statistics.rxCRCErr++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.overFlow) api_Mac_dev->statistics.rxOverflowErr++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.longErr) api_Mac_dev->statistics.rxLongErr++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.rxPar) api_Mac_dev->statistics.rxParErr++; if ((api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength.rxHalted) api_Mac_dev->statistics.rxHalted++; } *(ulong *)(&(api_Mac_dev->gpReceiveFrameDescStart)->rxStatusLength) = 0; /* Rx status length field */ (api_Mac_dev->gpReceiveFrameDescStart)->rxFrameData.o_bit = 1; /* Ownership back to BDMA */ (api_Mac_dev->gpReceiveFrameDescStart) = (api_Mac_dev->gpReceiveFrameDescStart)->nextRxFrameDesc; } while ((api_Mac_dev->gpReceiveFrameDescStart) != pReceiveFrameDesc); /*If not ownerstat than re_enable rx */ REG_IN_LONG(BdmaAddr, BDMARXCON, *(ulong *) (&bdmaRxCon)); if(bdmaRxCon.rxCon_reg.enable == 0) { bdmaRxCon.rxCon_reg.enable = 1; REG_OUT_LONG(BdmaAddr, BDMARXCON, *(ulong *) (&bdmaRxCon)); }}/********************************************************************************* api_MacSend - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacSend(API_DEVICE *api_Mac_dev, ulong pData, int len){ TRANSMIT_FRAME_DESC *pTxFd; uBDMATXCON bdmaTxCon; uMACTXCON macTxCon; ulong pBdmaAddr=api_Mac_dev->BdmaAddr; ulong pMacAddr=api_Mac_dev->MacAddr; *(ulong *)(&bdmaTxCon) = 0; *(ulong *)(&macTxCon) = 0;#ifdef TEST_MAC_SEND printf("entering api_MacSend...\n");#endif if ((api_Mac_dev->gpTransmitFrameDescStart)->txFrameData.o_bit) /* Ownership with BDMA? */ { printf("Error: Ownership with BDMA?\n"); return ERROR; } pTxFd = (api_Mac_dev->gpTransmitFrameDescStart); /* <<Attention>> FIXUP Please for RTOS and Application */ /* FIXUP please not Use memory copy */ /*rtn(pData, (void *)pTxFd->txFrameData.frameDataPtr, len); */ pTxFd->txFrameData.frameDataPtr = pData; pTxFd->txFrameData.frameDataPtr |= NON_CACHE_REGION; *(ulong *)(&pTxFd->txControl) = 0; /* Reset control word */ pTxFd->txControl.t_bit = 1; pTxFd->txControl.a_bit = 1;#if BIG_ENDIAN pTxFd->txControl.l_bit = 0;#else /*BIG_ENDIAN*/ pTxFd->txControl.l_bit = 1;#endif /*BIG_ENDIAN*/ pTxFd->txStatusLength.frameLength = len; pTxFd->txFrameData.o_bit = 1; /* place a transmit request */ /* oldLevel = SYS_INT_STOP(MAX_ILEV);*/ /* now sndsEndInt won't get confused */ /* initiate device transmit */ REG_IN_LONG (pBdmaAddr, BDMATXCON, bdmaTxCon.txCon_resetval); bdmaTxCon.txCon_reg.enable = 1; REG_OUT_LONG (pBdmaAddr, BDMATXCON, bdmaTxCon.txCon_resetval); REG_IN_LONG (pMacAddr, MACTXCON, macTxCon.macTxCon_resetval); macTxCon.macTxCon_reg.transmitEnable = 1; REG_OUT_LONG (pMacAddr, MACTXCON, macTxCon.macTxCon_resetval);#ifdef TEST_MAC_SEND printf("initiate device transmit...done\n");#endif /*SYS_INT_START (oldLevel);*/ /* now sndsEndInt won't get confused */ /* Advance our management index */ (api_Mac_dev->gpTransmitFrameDescStart) = (api_Mac_dev->gpTransmitFrameDescStart)->nextTxFrameDesc; return OK;}/********************************************************************************* api_MacIntEnable - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacIntEnable(API_DEVICE *api_Mac_dev){ STATUS status = OK; /* Not use system interrupt handler */ /* SYS_INT_CONNECT(api_Mac_dev->ivecRx, api_Mac_dev->ihandleFuncRx); SYS_INT_CONNECT(api_Mac_dev->ivecTx, api_Mac_dev->ihandleFuncTx); */ intEnable(api_Mac_dev->ivecRx); intEnable(api_Mac_dev->ivecTx); api_Mac_dev->status = INT_ENABLE_STATUS; return status;}/********************************************************************************* api_MacIntDisable - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacIntDisable(API_DEVICE *api_Mac_dev){ STATUS status = OK; /* Not use system interrupt handler */ /* SYS_INT_CONNECT(api_Mac_dev->ivecRx, dummyIsr); SYS_INT_CONNECT(api_Mac_dev->ivecTx, dummyIsr); */ intDisable(api_Mac_dev->ivecRx); intDisable(api_Mac_dev->ivecTx); api_Mac_dev->status = INT_DISABLE_STATUS; return status;}/******************************************************************************* sndsEndPhyRead - Read PHY device* This function is used to read a byte from the PHY device*/ulong miiRead(API_DEVICE *api_Mac_dev, ulong phyAddr, /* Address of the PHY chip (usually 0 for single PHY) */ ulong phyRegAddr, /* Address of PHY register to be read */ ulong *phyData) /* Data to be Read */{ uSTACON staCon; ulong MacAddr=api_Mac_dev->MacAddr; *(ulong *) (&staCon) = 0; staCon.staCon_reg.phyRegisterAddr = phyRegAddr; staCon.staCon_reg.phyAddr = phyAddr; staCon.staCon_reg.busy = 1; REG_OUT_LONG (MacAddr, STACON, staCon.staCon_resetval); do { REG_IN_LONG(MacAddr, STACON, staCon.staCon_resetval); } while (staCon.staCon_resetval & 0x800); /***** Busy bit ***/ REG_IN_LONG(MacAddr, STADATA, *phyData); return 0;}/******************************************************************************* sndsEndPhyWrite - Wrire into PHY device* This function is used to write a byte to the PHY device*/void miiWrite(API_DEVICE *api_Mac_dev, ulong phyAddr, /* Address of the PHY chip (usually 0 for single PHY) */ ulong phyRegAddr, /* Address of PHY register to be written */ ulong phyData) /* Data to be written */{ uSTACON staCon; ulong count = 1000; ulong MacAddr=api_Mac_dev->MacAddr; REG_OUT_LONG (MacAddr, STADATA, phyData); *(ulong *) (&staCon) = 0; staCon.staCon_reg.phyRegisterAddr = phyRegAddr; staCon.staCon_reg.phyAddr = phyAddr; staCon.staCon_reg.busy = 1; staCon.staCon_reg.write = 1; REG_OUT_LONG (MacAddr, STACON, staCon.staCon_resetval); do { REG_IN_LONG (MacAddr, STACON, staCon.staCon_resetval); } while (staCon.staCon_resetval & 0x800) ; /***** Busy bit ***/ while (count--) ; /* Dummy delay after PHY write */}/******************************************************************************* FUNCTION** MII_AutoNeg** DESCRIPTION** Using the mii_ReadMII and mii_WriteMII routines supplied by the driver* to access the MII registers, this routine directs the auto-negotiation* process of an MII PHY.** INPUTS** *api_Mac_dev * phyAddr* retries * *isFullDuplexP * *is100Mbps * miiRead* miiWrite** OUTPUTS** SUCCESS * * * TIMEOUT * * NOT_PRESENT * INVALID_OPERATION * * INVALID_FUNCTION * INVALID_POINTER* *****************************************************************************//*STATUS MII_AutoNeg(DV_DEVICE_ENTRY* deviceP, int phyAddr, unsigned long retries, int* isFullDuplexP, int* is100MbpsP, mii_ReadMII miiRead, mii_WriteMII miiWrite)*/#if 0STATUS MII_AutoNeg(API_DEVICE *api_Mac_dev, unsigned long retries, int *isFullDuplexP, int *is100MbpsP){ unsigned long miiControl; unsigned long miiStatus = 0; unsigned long miiAutoNeg = MII_ADVR_802_3; unsigned long tries = ((unsigned long)(0xFFFFFFFF)); STATUS status = OK; ulong phyAddr = 0; if (api_Mac_dev->channel == 0) { phyAddr = PHY_ADDR_A; } else { phyAddr = PHY_ADDR_B; } /* Reset PHY via software */ miiRead(api_Mac_dev, phyAddr, MII_CONTROL, &miiControl); miiControl |= MII_CTRL_RESET; miiWrite(api_Mac_dev, phyAddr, MII_CONTROL, miiControl); /* Wait for PHY to complete reset */ do { miiRead(api_Mac_dev, phyAddr, MII_CONTROL, &miiControl); } while((miiControl & MII_CTRL_RESET) != 0); /* Power up PHY and set options */ miiControl &= ~(MII_CTRL_LOOPBACK | MII_CTRL_POWER_DOWN | MII_CTRL_ISOLATE | MII_CTRL_COLL_TEST); miiControl |= (MII_CTRL_AUTO_NEG); miiWrite(api_Mac_dev, phyAddr, MII_CONTROL, miiControl); /* Read PHY status and capabilities */ miiRead(api_Mac_dev, phyAddr, MII_STATUS, &miiStatus); /* This driver relies on PHY being capable of auto-negotiation */ if((miiStatus & MII_STAT_AUTO_NEG) == 0) { status = ERROR; } /* Determine PHY capabilities to be advertised during auto-negotiation */ if((miiStatus & MII_STAT_TX) && (*is100MbpsP == TRUE)) { miiAutoNeg |= MII_ADVR_TX; if((miiStatus & MII_STAT_TX_FULL_DUPLEX) && (*isFullDuplexP == TRUE)) miiAutoNeg |= MII_ADVR_TX_FULL_DUPLEX; } if(miiStatus & MII_STAT_10) { miiAutoNeg |= MII_ADVR_10; if((miiStatus & MII_STAT_10_FULL_DUPLEX) && (*isFullDuplexP == TRUE)) miiAutoNeg |= MII_ADVR_10_FULL_DUPLEX; } /* Indicate advertised capabilities */ miiWrite(api_Mac_dev, phyAddr, MII_ADVERTISEMENT, miiAutoNeg); /* Restart auto-negotiation process */ miiRead(api_Mac_dev, phyAddr, MII_CONTROL, &miiControl); miiControl |= MII_CTRL_RESTART; miiWrite(api_Mac_dev, phyAddr, MII_CONTROL, miiControl); /* Wait for PHY to auto-negotiate */ if(retries != 0) /* If not infinite retries... */ tries = retries; /* Initialize attempts remaining */ do { miiRead(api_Mac_dev, phyAddr, MII_STATUS, &miiStatus); if((miiStatus & MII_STAT_REMOTE_FAULT) != 0) { status = ERROR; } if(retries != 0) /* If not infinite retries... */ tries -= 1; /* Decrement attempts remaining */ } while((tries != 0) && ((miiStatus & MII_STAT_AUTO_NEG_DONE) == 0)); /* Obtain link partner response */ miiRead(api_Mac_dev, phyAddr, MII_LINK_PARTNER, &miiAutoNeg);// if((miiAutoNeg & MII_LINK_REMOTE_FAULT) != 0) if(miiAutoNeg & MII_LINK_REMOTE_FAULT) { status = ERROR; } /* Configure PHY for link partner */ miiRead(api_Mac_dev, phyAddr, MII_CONTROL, &miiControl); /* Select 100 Mbps if this PHY is 100Base-TX capable, the driver asked for 100Mbps and not only 10Mbps, and the link partner responded with 100Base-TX or did not respond at all. The "no response" behavior is done to allow a wire to be plugged in later and have the PHY negotiate the best speed. */ if((miiStatus & MII_STAT_TX) && (*is100MbpsP == TRUE) && ((miiAutoNeg & MII_LINK_TX) || (!(miiAutoNeg & MII_LINK_ACK)))) { miiControl |= MII_CTRL_100MBPS; *is100MbpsP = TRUE; } else /* Use only 10Mbps, because of options or link partner */ { miiControl &= (~(MII_CTRL_100MBPS)); *is100MbpsP = FALSE; } if((miiAutoNeg & MII_LINK_ACK) && (*isFullDuplexP == TRUE) && (((*is100MbpsP == TRUE) && (miiStatus & MII_STAT_TX_FULL_DUPLEX) && (miiAutoNeg & MII_LINK_TX_FULL_DUPLEX)) || ((*is100MbpsP == FALSE) && (miiStatus & MII_STAT_10_FULL_DUPLEX) && (miiAutoNeg & MII_LINK_10_FULL_DUPLEX)))) { /* Select full duplex if link partner responded and both the link partner and this PHY are full duplex capable */ miiControl |= MII_CTRL_FULL_DUPLEX; *isFullDuplexP = TRUE; } else /* Use only half duplex, because of options or link partner */ { miiControl &= (~(MII_CTRL_FULL_DUPLEX)); *isFullDuplexP = FALSE; } miiWrite(api_Mac_dev, phyAddr, MII_CONTROL, miiControl); if(tries == 0) { status = ERROR; } return status;}#endifint MAC_PHY_INIT(void){// int isFullDuplexP=0; // int is100MbpsP=0; STATUS status = OK; #if 0 if((status = MII_AutoNeg(&api_Mac_dev, 0, &isFullDuplexP, &is100MbpsP)) != OK) { printf("ERROR: MII AutoNeg \n"); return status; } printf("MII Status Full Duplex=%d, 100Mbps=%d\n", isFullDuplexP, is100MbpsP);#endif return status;}void api_init(bd_t *bd, API_DEVICE *api_Mac_dev){#ifdef S5N8947_AP api_Mac_dev->BdmaAddr = BDMA_REG_ADDR_B; api_Mac_dev->MacAddr = MAC_REG_ADDR_B; //api_Mac_dev->ivecTx = INT_LVL_ETHTxB; api_Mac_dev->ivecTx = INT_LVL_MAC_TX; //api_Mac_dev->ivecRx = INT_LVL_ETHRxB; api_Mac_dev->ivecRx = INT_LVL_MAC_RX;#else api_Mac_dev->BdmaAddr = BDMA_REG_ADDR_A; api_Mac_dev->MacAddr = MAC_REG_ADDR_A; //api_Mac_dev->ivecTx = INT_LVL_ETHTxA; api_Mac_dev->ivecTx = INT_LVL_BDMA_TX; //api_Mac_dev->ivecRx = INT_LVL_ETHRxA; api_Mac_dev->ivecRx = INT_LVL_BDMA_RX;#endif /* Set MAC PHY Register */ api_Mac_dev->autoNeg = 0; api_Mac_dev->netSpeed = 0; api_Mac_dev->duplexMode = 0; /* Set Ethernet address */// SYS_ENET_ADDR_GET(api_Mac_dev, EnetAddrA); SYS_ENET_ADDR_GET(api_Mac_dev, bd->bi_enetaddr); api_Mac_dev->channel = 0;}#endif /* COMMANDS & CFG_NET */#endif /* CONFIG_S5N8947 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -