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 + -
显示快捷键?