mac2500.c
来自「source code of armboot for s3c4510」· C语言 代码 · 共 942 行 · 第 1/2 页
C
942 行
/* Process all packets received. */ while (api_Mac_dev->RXDONEOFFSET != RXFDCNT) { pFd = api_Mac_dev->gpReceiveFrameDescStart + api_Mac_dev->RXDONEOFFSET; /* Check BDMA Receive Ownership */ if( ! pFd->rxStatusLength.owner ) { if(*(ulong *)(&(pFd->rxStatusLength)) & MACRXFRAMEERRMASK ){ /* Rx Error packet */ api_Mac_dev->statistics.rxBad++; if (api_Mac_dev->gpReceiveFrameDescStart->rxStatusLength.mso) api_Mac_dev->statistics.rxOvMaxSize++; /* * This state is not in descriptor. * if (api_Mac_dev->gpReceiveFrameDescStart->rxStatusLength.ctlRcv) * api_Mac_dev->statistics.rxCtlRecd++; */ if (api_Mac_dev->gpReceiveFrameDescStart->rxStatusLength.mRx10Stat) 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.mufs) api_Mac_dev->statistics.rxLongErr++; if (api_Mac_dev->gpReceiveFrameDescStart->rxStatusLength.rxParErr) api_Mac_dev->statistics.rxParErr++; if (api_Mac_dev->gpReceiveFrameDescStart->rxStatusLength.halted) api_Mac_dev->statistics.rxHalted++; }else if( pFd->rxStatusLength.bRxDone ){ /* Rx O.K. */ api_Mac_dev->statistics.rxGood++; frameLength = (*(ulong *)(&(pFd->rxStatusLength)) & 0xffff); pFrameData = (ushort *)pFd->rxFrameData; /* 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 break; /* Clear Reserved & Status/Length Field */ *(ulong *)(&(pFd->rxStatusLength)) = 0; /* Clear Framedata pointer already used */ pFd->rxStatusLength.owner = 1; api_Mac_dev->RXDONEOFFSET ++; if(api_Mac_dev->RXDONEOFFSET == RX_FD_NUM) api_Mac_dev->RXDONEOFFSET =0; } /*If not ownerstat than re_enable rx */ if(bmRxStat.rxStat_reg.bRxNO) { REG_IN_LONG(pEtherAddr, BDMARXCON, *(ulong *)(&bmRxCon)); bmRxCon.rxCon_reg.bRxEn =1; REG_OUT_LONG(pEtherAddr, BDMARXCON, *(ulong *)(&bmRxCon)); }}/********************************************************************************* 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 pEtherAddr=api_Mac_dev->EtherAddr; pTxFd = api_Mac_dev->gpTransmitFrameDescStart + api_Mac_dev->TXOFFSET; if (pTxFd->txStatusLength.owner) /* Ownership with BDMA? */ { printf("Error: Ownership with BDMA?\n"); return ERROR; } *(ulong *)(&bdmaTxCon) = 0; *(ulong *)(&macTxCon) = 0; /* <<Attention>> FIXUP Please for RTOS and Application */ /* FIXUP please not Use memory copy */ /*rtn(pData, (void *)pTxFd->txFrameData.frameDataPtr, len); */ pTxFd->txFrameData = pData; pTxFd->txStatusLength.TxWidget =0; pTxFd->txStatusLength.TxLength =len; pTxFd->txStatusLength.owner =1; /* place a transmit request */ /* oldLevel = SYS_INT_STOP(MAX_ILEV); */ /* now sndsEndInt won't get confused */ /* initiate device transmit */ REG_IN_LONG (pEtherAddr, BDMATXCON, bdmaTxCon.txCon_resetval); bdmaTxCon.txCon_reg.bTxEn= 1; REG_OUT_LONG (pEtherAddr, BDMATXCON, bdmaTxCon.txCon_resetval); REG_IN_LONG (pEtherAddr, MACTXCON, macTxCon.macTxCon_resetval); macTxCon.macTxCon_reg.mTxEn = 1; REG_OUT_LONG (pEtherAddr, MACTXCON, macTxCon.macTxCon_resetval); /* Advance our management index */ if(api_Mac_dev->TXOFFSET >= (TX_FD_NUM -1)) api_Mac_dev->TXOFFSET =0; else api_Mac_dev->TXOFFSET ++; /* SYS_INT_START (oldLevel); */ /* now sndsEndInt won't get confused */ 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 pEtherAddr=api_Mac_dev->EtherAddr; *(ulong *) (&staCon) = 0; staCon.staCon_reg.mPHYRegAddr= phyRegAddr; staCon.staCon_reg.mPHYaddr= phyAddr; staCon.staCon_reg.mPHYbusy= 1; REG_OUT_LONG (pEtherAddr, STACON, staCon.staCon_resetval); do { REG_IN_LONG(pEtherAddr, STACON, staCon.staCon_resetval); } while (staCon.staCon_resetval & 0x800); /***** Busy bit ***/ REG_IN_LONG(pEtherAddr, 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 pEtherAddr=api_Mac_dev->EtherAddr; REG_OUT_LONG (pEtherAddr, STADATA, phyData); *(ulong *) (&staCon) = 0; staCon.staCon_reg.mPHYRegAddr = phyRegAddr; staCon.staCon_reg.mPHYaddr = phyAddr; staCon.staCon_reg.mPHYbusy = 1; staCon.staCon_reg.mPHYwrite= 1; REG_OUT_LONG (pEtherAddr, STACON, staCon.staCon_resetval); do { REG_IN_LONG (pEtherAddr, 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){ api_Mac_dev->EtherAddr = ETHER_REG_ADDR_A; api_Mac_dev->ivecTx = INT_LVL_ETHTxA; api_Mac_dev->ivecRx = INT_LVL_ETHRxA; /* 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_S3C2500 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?