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

📄 smsc911x.c

📁 smsc911x.c smsc911x driver based vxworks network com 9700 stb cware dirver
💻 C
📖 第 1 页 / 共 5 页
字号:
	SMSC_ASSERT(privateData->dwLanBase!=0);

	if(dwPhyAddr!=0xFFFFFFFFUL) {
		switch(privateData->dwIdRev&0xFFFF0000) {
		case 0x01170000UL:
		case 0x01150000UL:
			{
				DWORD dwHwCfg=Lan_GetRegDW(dwBase, HW_CFG);
				if(dwHwCfg&HW_CFG_EXT_PHY_DET_) {
                    			/*External phy is requested, supported, and detected
					//Attempt to switch
					//NOTE: Assuming Rx and Tx are stopped
					//  because Phy_Initialize is called before 
					//  Rx_Initialize and Tx_Initialize */

					/*Disable phy clocks to the mac */
					dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);
					dwHwCfg|= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
					Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);
					smscDelay(10);/* wait for clocks to acutally stop */

					/*switch to external phy */
					dwHwCfg|=HW_CFG_EXT_PHY_EN_;
					Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);

					/*Enable phy clocks to the mac */
					dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);
					dwHwCfg|= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
					Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);
					smscDelay(10);/*wait for clocks to actually start*/

					dwHwCfg|=HW_CFG_SMI_SEL_;
					Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);

					/*Because this is part of the single threaded initialization
					//  path there is no need to acquire the MacPhyAccessLock */
					if(dwPhyAddr<=31) {
						/*only check the phy address specified */
						privateData->dwPhyAddress=dwPhyAddr;
						wPhyId1=Phy_GetRegW(privateData,PHY_ID_1);
						wPhyId2=Phy_GetRegW(privateData,PHY_ID_2);
					} else {
						/*auto detect phy */
						DWORD address=0;
						for(address=0;address<=31;address++) {
							privateData->dwPhyAddress=address;
							wPhyId1=Phy_GetRegW(privateData,PHY_ID_1);
							wPhyId2=Phy_GetRegW(privateData,PHY_ID_2);
							if((wPhyId1!=0xFFFFU)||(wPhyId2!=0xFFFFU)) {
								SMSC_TRACE("Detected Phy at address = 0x%02lX = %ld\r\n",
									address,address);
								break;
							}
						}
						if(address>=32) {
							SMSC_WARNING("Failed to auto detect external phy\r\n");
						}
					}
					if((wPhyId1==0xFFFFU)&&(wPhyId2==0xFFFFU)) {
						SMSC_WARNING("External Phy is not accessable\r\n");
						SMSC_WARNING("  using internal phy instead\r\n");
						/*revert back to interal phy settings. */

						/*Disable phy clocks to the mac */
						dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);
						dwHwCfg|= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
						Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);
						smscDelay(10);/*wait for clocks to actually stop */

						/*switch to internal phy */
						dwHwCfg&=(~HW_CFG_EXT_PHY_EN_);
						Lan_SetRegDW(dwBase, HW_CFG,dwHwCfg);
	
						/* Enable phy clocks to the mac */
						dwHwCfg&= (~HW_CFG_PHY_CLK_SEL_);
						dwHwCfg|= HW_CFG_PHY_CLK_SEL_INT_PHY_;
						Lan_SetRegDW(dwBase, HW_CFG,dwHwCfg);
						smscDelay(10);/*wait for clocks to actually start */

						dwHwCfg&=(~HW_CFG_SMI_SEL_);
						Lan_SetRegDW(dwBase,HW_CFG,dwHwCfg);
						goto USE_INTERNAL_PHY;
					} else {
						SMSC_TRACE("Successfully switched to external phy\r\n");
#ifdef USE_LED1_WORK_AROUND
						privateData->NotUsingExtPhy=0;
#endif
					}
				} else {
					SMSC_WARNING("No External Phy Detected\r\n");
					SMSC_WARNING("  using internal phy instead\r\n");
					goto USE_INTERNAL_PHY;
				}
			};break;
		default:
			SMSC_WARNING("External Phy is not supported\r\n");
			SMSC_WARNING("  using internal phy instead\r\n");
			goto USE_INTERNAL_PHY;
		}
	} else {
USE_INTERNAL_PHY:
		privateData->dwPhyAddress=1;
#ifdef USE_LED1_WORK_AROUND
		privateData->NotUsingExtPhy=1;
#endif
	}
    
	/*Because this is part of the single threaded initialization
	//  path there is no need to acquire the MacPhyAccessLock */
	wPhyId1=Phy_GetRegW(privateData,PHY_ID_1);
	wPhyId2=Phy_GetRegW(privateData,PHY_ID_2);
	if((wPhyId1==0xFFFFU)&&(wPhyId2==0xFFFFU)) {
		SMSC_WARNING("Phy Not detected\r\n");
		goto DONE;
	}
	
	/* reset the PHY */
#ifdef USE_PHY_WORK_AROUND
	Phy_Reset(privateData);
	if(!Phy_LoopBackTest(privateData)) {
		SMSC_WARNING("Failed Loop Back Test\r\n");
		goto DONE;
	} else {
		SMSC_TRACE("Passed Loop Back Test\r\n");
	}
#else
	Phy_SetRegW(privateData,PHY_BCR,PHY_BCR_RESET_);
    dwLoopCount=100000;
	do {
		smscDelay(10);
		wTemp=Phy_GetRegW(privateData,PHY_BCR);
		dwLoopCount--;
	} while((dwLoopCount>0) && (wTemp&PHY_BCR_RESET_));
	if(wTemp&PHY_BCR_RESET_) {
		SMSC_WARNING("PHY reset failed to complete.\r\n");
		goto DONE;
	}
#endif /* not USE_PHY_WORK_AROUND */
	
	Phy_SetLink(privateData);

/*
	init_timer(&(privateData->LinkPollingTimer));
	privateData->LinkPollingTimer.function=Phy_CheckLink;
	privateData->LinkPollingTimer.data=(unsigned long)privateData;
	privateData->LinkPollingTimer.expires=jiffies+HZ;
	add_timer(&(privateData->LinkPollingTimer));
*/
	result=TRUE;
DONE:
	SMSC_TRACE("-Phy_Initialize, result=%s\r\n",result?"TRUE":"FALSE");
	return result;
}

void Tx_Initialize(
	PPRIVATE_DATA privateData)
{
	DWORD dwRegVal=0;
	DWORD dwBase ;
	DWORD dwMacCr;
	SMSC_ASSERT(privateData!=NULL);
	SMSC_ASSERT(privateData->dwLanBase!=0);

	dwBase = privateData->dwLanBase ;
	dwRegVal=Lan_GetRegDW(dwBase, HW_CFG);
	dwRegVal&=(HW_CFG_TX_FIF_SZ_|0x00000FFFUL);
	dwRegVal|=HW_CFG_SF_;
	Lan_SetRegDW(dwBase,HW_CFG,dwRegVal);

	Lan_SetBitsDW(dwBase,FIFO_INT,0xFF000000UL);
	Lan_SetBitsDW(dwBase,INT_EN,INT_EN_TDFA_EN_);

	/*Because this is part of the single threaded initialization
	//  path there is no need to acquire the MacPhyAccessLock */
	dwMacCr=Mac_GetRegDW(dwBase, MAC_CR);
	dwMacCr|=(MAC_CR_TXEN_|MAC_CR_HBDIS_);
	Mac_SetRegDW(dwBase,MAC_CR,dwMacCr);
	Lan_SetRegDW(dwBase,TX_CFG,TX_CFG_TX_ON_);
}

void Rx_Initialize(
	PPRIVATE_DATA privateData)
{
	DWORD dwMacCr=0;
	DWORD dwBase ;
	SMSC_ASSERT(privateData!=NULL);

	dwBase = privateData->dwLanBase ;
	Lan_SetRegDW(dwBase, RX_CFG,0x00000200UL);
	
	/* Because this is part of the single threaded initialization
	//  path there is no need to acquire the MacPhyAccessLock */
	dwMacCr=Mac_GetRegDW(dwBase,MAC_CR);
	dwMacCr|=MAC_CR_RXEN_;
	Mac_SetRegDW(dwBase,MAC_CR,dwMacCr);

	Lan_ClrBitsDW(dwBase,FIFO_INT,0x000000FFUL);

	Lan_SetBitsDW(dwBase,INT_EN,INT_EN_RSFL_EN_);
}

/*******************************************************************************
* smsc911xStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/

STATUS smsc911xStart ( END_OBJ * pEnd	/* device ID */)
{
	SMSC_TRACE( "+smsc911xStart\r\n") ;

 	MEDUSA_INT_UNMASK() ;

	SMSC_TRACE("-smsc911xStart: Success\r\n");
	return (OK);
}

/*******************************************************************************
* smsc911xInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/

int netIntCount,netTest;
void smsc911xInt
	(
		SMSC911XEND_DEVICE * pDrvCtrl	/* device to be initialized */
	)
{
	DWORD dwIntSts, dwIntCfg;
	int currentKey;
	DWORD dwBase ;
	DWORD reservedBits=0x00FFCEEEUL;
	PPRIVATE_DATA privateData ;
	BOOLEAN serviced ;

	dwBase = pDrvCtrl->private_data.dwLanBase ;
	privateData = & pDrvCtrl->private_data ;

	currentKey = intLock();
	
	dwIntCfg=Lan_GetRegDW(dwBase, INT_CFG);
	netIntCount++;
	netTest = dwIntCfg;
	
	if((dwIntCfg&0x00001100)!=0x00001100) {
		SMSC_TRACE("In ISR, not my interrupt, dwIntCfg=0x%08lX\r\n", dwIntCfg);
		goto DONE;
	}

	if(dwIntCfg&reservedBits) {
		SMSC_WARNING("In ISR, reserved bits are high.\r\n");
		goto DONE;
	}

	dwIntSts=Lan_GetRegDW(dwBase,INT_STS);
	if(dwIntSts&INT_STS_SW_INT_) {
		Lan_ClrBitsDW(dwBase,INT_EN,INT_EN_SW_INT_EN_);
		Lan_SetRegDW(dwBase,INT_STS,INT_STS_SW_INT_);
	}
	
	if(dwIntSts&INT_STS_RXE_) {
		Lan_SetRegDW(dwBase,INT_STS,INT_STS_RXE_);
		goto DONE;
	}

	if(dwIntSts&INT_STS_RSFL_) {
		HandlerRxISR(pDrvCtrl) ; 
		Lan_SetRegDW(dwBase, INT_STS, INT_STS_RSFL_);
	}

	if(dwIntSts&INT_STS_TDFA_) {
		HandlerTxISR(pDrvCtrl) ;
		Lan_SetRegDW(dwBase, INT_STS, INT_STS_TDFA_);
	}

DONE:
    MEDUSA_INT_CLEAR();
    SPARC_COMMIT();
    SPARC_COMMIT();

    intUnlock(currentKey);

    return;

}


/*******************************************************************************
* smsc911xRecv - process the next incoming packet
*
* Handle one incoming packet.  The packet is checked for errors.
*
* RETURNS: N/A.
*/
STATUS smsc911xRecv
(
	SMSC911XEND_DEVICE *pDrvCtrl
	/*
	char *pData,
	UINT len*/
)
{

	M_BLK_ID 	pMblk;
	CL_BLK_ID	pClBlk;
	int len,type;
	int i;

	/* Grab a cluster block to marry to the cluster we received. */

	if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
	{
		netClFree (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pRxReadIndex->pData);
		SMSC_TRACE("smsc911xRecv: Out of Cluster Blocks!\r\n");
		END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
		goto cleanRXD;
	}

	/*
	 * OK, let's get an M_BLK_ID and marry it to the
	 * one in the ring.
	 */

	if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
	{
		netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
		netClFree (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pRxReadIndex->pData);
		SMSC_TRACE( "smsc911xRecv: Out of M Blocks!\n");
		END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
		goto cleanRXD;
	}

	/* Join the cluster to the MBlock */

	netClBlkJoin (pClBlk,(char*) pDrvCtrl->pRxReadIndex->pData, smsc911xClDescTbl[0].clSize, NULL, 0, 0, 0);
	netMblkClJoin (pMblk, pClBlk);

	len = pDrvCtrl->pRxReadIndex->len;

	pMblk->mBlkHdr.mData = (char *)(pDrvCtrl->pRxReadIndex->pData + 2);
	pMblk->mBlkHdr.mLen = len ;
	pMblk->mBlkHdr.mFlags |= M_PKTHDR;
	pMblk->mBlkPktHdr.len = len;

	SMSC_TRACE("RX : Pkt : Len %d\n",len);

	pDrvCtrl->pRxReadIndex->pData = NULL;	/* free the slot */

	if(pDrvCtrl->pRxReadIndex < pDrvCtrl->pRxBase + RX_PACKETS - 1)
		pDrvCtrl->pRxReadIndex++;
	else
		pDrvCtrl->pRxReadIndex = pDrvCtrl->pRxBase;


	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);

	END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);

	cleanRXD:
	return (OK);

}

/*******************************************************************************
* smsc911xHandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* The double loop is to protect against a race condition where the interrupt
* code see rxHandling as TRUE, but it is then turned off by task code.
* This race is not fatal, but does cause occassional delays until a second
* packet is received and then triggers the netTask to call this routine again.
*
* RETURNS: N/A.
*/

void smsc911xHandleRcvInt
	(
		SMSC911XEND_DEVICE *pDrvCtrl	/* interrupting device */
	)
{
	UINT receiveReady;
	int loopCount=0;

	pDrvCtrl->rxHandling = TRUE;

	SMSC_TRACE("+smsc911xHandleRcvInt\r\n");


	do
	{
		smsc911xRecv (pDrvCtrl);
		receiveReady = pDrvCtrl->pRxReadIndex->pData ? 1 : 0;
		loopCount++;

	}  while ((receiveReady != 0) && (loopCount <= 30));

	pDrvCtrl->rxHandling = FALSE;

	SMSC_TRACE("-smsc911xHandleRcvInt\r\n");

	return;
}

/******************************************************************************
* smsc911xSend - end send routine
*
* This routine will be called by the network stack whenever the upper layer want
* to send the datagram. It takes a pointer to mbuf. It extacts the data from the
* mbuf and writes in chip.
*
* RETURNS: status of the write operation
*/

STATUS smsc911xSend(END_OBJ *pEnd,M_BLK_ID pMblk)
{
    SMSC911XEND_DEVICE  	*pDrvCtrl = (SMSC911XEND_DEVICE *)pEnd;

    int currentKey;
    SMSC_TRACE("+smsc911xSend\r\n");

/* This Block is to put the packet sent by the upper layers in a ring Buffer.Here
 we are using ReadIndex and WriteIndex instead of allocpending and writepending Queues*/

/* First of all, put the upper layer into the queue.*/

    currentKey = intL

⌨️ 快捷键说明

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