📄 smsc911x.c
字号:
*/
/* Ethernet ISR link */
static isrLink_t sysEndIsrLink =
{
(void*)smsc911xInt, /* rtn */
0, /* arg */
NULL /* next */
};
/* register access routine */
void Lan_SetRegDW( DWORD dwBase, DWORD dwOffset, DWORD dwVal)
{
DWORD tmpvalue ;
tmpvalue = ((dwVal & 0xFF000000)>>24) | ((dwVal & 0xFF0000)>>8) | ((dwVal & 0xFF00)<<8) | ((dwVal & 0xFF)<<24 ) ;
(*(DWORD *)(dwBase + dwOffset)) = tmpvalue;
}
DWORD Lan_GetRegDW(DWORD dwBase, DWORD dwOffset)
{
DWORD tmpvalue ;
tmpvalue = (DWORD)(*(DWORD *)(dwBase + dwOffset));
tmpvalue = ((tmpvalue& 0xFF000000)>>24) | ((tmpvalue& 0xFF0000)>>8) |((tmpvalue& 0xFF00)<<8) | ((tmpvalue& 0xFF)<<24 ) ;
return tmpvalue;
}
VOID Lan_ClrBitsDW(DWORD dwBase, DWORD dwOffset ,DWORD dwBits)
{
DWORD dwData ;
dwData = Lan_GetRegDW( dwBase, dwOffset) ;
dwData &= ~dwBits ;
Lan_SetRegDW( dwBase, dwOffset, dwData ) ;
}
VOID Lan_SetBitsDW(DWORD dwBase, DWORD dwOffset, DWORD dwBits)
{
DWORD dwData ;
dwData = Lan_GetRegDW( dwBase, dwOffset) ;
dwData |= dwBits ;
Lan_SetRegDW( dwBase, dwOffset, dwData ) ;
}
BOOLEAN MacNotBusy(DWORD dwBase)
{
int i=0;
/* Assuming MacPhyAccessLock has already been acquired */
/* wait for MAC not busy, w/ timeout */
for(i=0;i<40;i++)
{
if((Lan_GetRegDW(dwBase,MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_)==(0UL)) {
return TRUE;
}
}
SMSC_WARNING("timeout waiting for MAC not BUSY. MAC_CSR_CMD = 0x%08lX",
Lan_GetRegDW(dwBase, MAC_CSR_CMD));
return FALSE;
}
DWORD Mac_GetRegDW(DWORD dwBase,DWORD dwRegOffset)
{
DWORD result=0xFFFFFFFFUL;
DWORD dwTemp=0;
SMSC_ASSERT(dwBase!=0);
/*Assuming MacPhyAccessLock has already been acquired */
/* wait until not busy */
if (Lan_GetRegDW(dwBase,MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_)
{
SMSC_WARNING("Mac_GetRegDW() failed, MAC already busy at entry");
goto DONE;
}
/* send the MAC Cmd w/ offset */
Lan_SetRegDW(dwBase, MAC_CSR_CMD,
((dwRegOffset & 0x000000FFUL) | MAC_CSR_CMD_CSR_BUSY_ | MAC_CSR_CMD_R_NOT_W_));
dwTemp=Lan_GetRegDW(dwBase,BYTE_TEST); /* to flush previous write */
dwTemp=dwTemp;
/* wait for the read to happen, w/ timeout */
if (!MacNotBusy(dwBase))
{
SMSC_WARNING("Mac_GetRegDW() failed, waiting for MAC not busy after read\r\n");
goto DONE;
} else {
/* finally, return the read data */
result=Lan_GetRegDW(dwBase,MAC_CSR_DATA);
}
DONE:
return result;
}
/*Sets a Mac register */
void Mac_SetRegDW(DWORD dwBase , DWORD dwRegOffset, DWORD dwVal)
{
DWORD dwTemp=0;
SMSC_ASSERT(dwBase!=0);
/*Assuming MacPhyAccessLock has already been acquired */
if (Lan_GetRegDW(dwBase, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY_)
{
SMSC_WARNING("Mac_SetRegDW() failed, MAC already busy at entry\r\n");
goto DONE;
}
/* send the data to write */
Lan_SetRegDW(dwBase,MAC_CSR_DATA,dwVal);
/* do the actual write */
Lan_SetRegDW(dwBase , MAC_CSR_CMD,((dwRegOffset & 0x000000FFUL) | MAC_CSR_CMD_CSR_BUSY_));
dwTemp=Lan_GetRegDW(dwBase,BYTE_TEST); /*force flush of previous write*/
dwTemp=dwTemp;
/* wait for the write to complete, w/ timeout */
if (!MacNotBusy(dwBase))
{
SMSC_WARNING("Mac_SetRegDW() failed, waiting for MAC not busy after write");
}
DONE:
return;
}
WORD Phy_GetRegW( PPRIVATE_DATA privateData, DWORD dwRegIndex)
{
DWORD dwAddr=0;
int i=0;
WORD result=0xFFFFU;
DWORD dwBase ;
SMSC_ASSERT(privateData!= NULL);
dwBase = privateData->dwLanBase ;
/* confirm MII not busy */
if ((Mac_GetRegDW(dwBase, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL)
{
SMSC_WARNING("MII is busy in Phy_GetRegW???\r\n");
result=0;
goto DONE;
}
/* set the address, index & direction (read from PHY) */
dwAddr = (((privateData->dwPhyAddress) & 0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6);
Mac_SetRegDW(dwBase, MII_ACC, dwAddr);
/* wait for read to complete w/ timeout */
for(i=0;i<100;i++) {
/* see if MII is finished yet */
if ((Mac_GetRegDW(dwBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)
{
/* get the read data from the MAC & return i */
result=((WORD)Mac_GetRegDW(dwBase, MII_DATA));
goto DONE;
}
}
SMSC_WARNING("timeout waiting for MII write to finish\r\n");
DONE:
return result;
}
/*Sets a phy register */
void Phy_SetRegW( PPRIVATE_DATA privateData, DWORD dwRegIndex,WORD wVal)
{
DWORD dwAddr=0;
DWORD dwBase ;
int i=0;
SMSC_ASSERT(privateData!=NULL);
dwBase = privateData->dwLanBase ;
/* confirm MII not busy */
if ((Mac_GetRegDW(dwBase, MII_ACC) & MII_ACC_MII_BUSY_) != 0UL)
{
SMSC_WARNING("MII is busy in Phy_SetRegW???\r\n");
goto DONE;
}
/* put the data to write in the MAC */
Mac_SetRegDW(dwBase, MII_DATA, (DWORD)wVal);
/* set the address, index & direction (write to PHY) */
dwAddr = (((privateData->dwPhyAddress) & 0x1FUL)<<11) | ((dwRegIndex & 0x1FUL)<<6) | MII_ACC_MII_WRITE_;
Mac_SetRegDW(dwBase, MII_ACC, dwAddr);
/* wait for write to complete w/ timeout */
for(i=0;i<100;i++) {
/* see if MII is finished yet */
if ((Mac_GetRegDW(dwBase, MII_ACC) & MII_ACC_MII_BUSY_) == 0UL)
{
goto DONE;
}
}
SMSC_WARNING("timeout waiting for MII write to finish\r\n");
DONE:
return;
}
/******************************************************************************
*
* lan91C111Load - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device-specific parameters are passed in <initString>, which
* expects a string of the following format:
*
* This routine can be called in two modes. If it is called with an empty but
* allocated string, it places the name of this device (that is, "ln") into
* the <initString> and returns 0.
*
* If the string is allocated and not empty, the routine attempts to load
* the driver using the values specified in the string.
*
* RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
* device if the <initString> was NULL.
*/
END_OBJ* smsc911xLoad
(
char* initString, /* string to be parse by the driver */
void* args
)
{
SMSC911XEND_DEVICE *pDrvCtrl;
PPRIVATE_DATA privateData ;
DWORD dwIntCfg ;
DWORD dwHigh16=0;
DWORD dwLow32=0;
DWORD dwBase ;
SMSC_TRACE("+smsc911xLoad\r\n");
if (initString == NULL)
{
SMSC_TRACE( "initString is NULL\r\n-smsc911xLoad\r\n") ;
return (NULL);
}
if (initString[0] == NULL)
{
bcopy((char *)SMSC911X_DEV_NAME, initString, SMSC911X_DEV_NAME_LEN);
SMSC_TRACE( "initString[0] is NULL\r\n-smsc911xLoad\r\n") ;
return (0);
}
/* allocate the device structure */
pDrvCtrl = (SMSC911XEND_DEVICE *)calloc (sizeof (SMSC911XEND_DEVICE), 1);
if (pDrvCtrl == NULL)
goto errorExit;
/* parse the init string, filling in the device structure */
if (smsc911xInitParse (pDrvCtrl, initString) == ERROR)
goto errorExit;
/* identify the chip */
if ( smsc911xIdentify(pDrvCtrl) == ERROR )
{
goto errorExit;
}
/* init the memory */
if (smsc911xMemInit (pDrvCtrl) == ERROR) {
SMSC_TRACE(" Memroy initialize failed\r\n") ;
goto errorExit ;
}
privateData = & pDrvCtrl->private_data ;
dwIntCfg=(((DWORD)22UL)<<24);
dwBase = privateData->dwLanBase ;
/* init the Lan */
if(!Lan_Initialize(privateData,dwIntCfg)) {
SMSC_TRACE(" Lan initialized failed\r\n") ;
goto errorExit;
}
/* init the irq */
sysEndIsrLink.arg = (UINT) pDrvCtrl;
if (sysIntAttach(pDrvCtrl->ilevel, &sysEndIsrLink, TRUE) == ERROR)
{
SMSC_TRACE("system request failed!\r\n");
goto errorExit;
}
SMSC_TRACE("system Interrupt connected\r\n");
Mac_Initialize(privateData);
if (Lan_GetRegDW(dwBase, E2P_CMD) & E2P_CMD_MAC_ADDR_LOADED_)
{
/* mac address alreay load from e2prom */
dwHigh16=Mac_GetRegDW(dwBase,ADDRH);
dwLow32=Mac_GetRegDW(dwBase,ADDRL);
SMSC_TRACE("Mac Address is read from LAN911x as 0x%04lX%08lX\r\n", dwHigh16,dwLow32);
/* save address */
pDrvCtrl->ucStationAddress[0] = LOBYTE(LOWORD(dwLow32));
pDrvCtrl->ucStationAddress[1] = HIBYTE(LOWORD(dwLow32));
pDrvCtrl->ucStationAddress[2] = LOBYTE(HIWORD(dwLow32));
pDrvCtrl->ucStationAddress[3] = HIBYTE(HIWORD(dwLow32));
pDrvCtrl->ucStationAddress[4] = LOBYTE(LOWORD(dwHigh16));
pDrvCtrl->ucStationAddress[5] = HIBYTE(LOWORD(dwHigh16));
}
else
{
dwHigh16=0x00000070UL;
dwLow32=0x110F9015UL; /*7006*/
Mac_SetRegDW(dwBase,ADDRH,dwHigh16);
Mac_SetRegDW(dwBase,ADDRL,dwLow32);
SMSC_TRACE("Mac Address is set by default to 0x%04lX%08lX\r\n",dwHigh16,dwLow32);
/* Save the MAC address. */
pDrvCtrl->ucStationAddress[0] = (BYTE)0x15; /* 0x10 parker */
pDrvCtrl->ucStationAddress[1] = (BYTE)0x90;
pDrvCtrl->ucStationAddress[2] = (BYTE)0x0F;
pDrvCtrl->ucStationAddress[3] = (BYTE)0x11;
pDrvCtrl->ucStationAddress[4] = (BYTE)0x70;
pDrvCtrl->ucStationAddress[5] = (BYTE)0x00; /* 0x00 parker */
}
if(!Phy_Initialize( privateData, pDrvCtrl->PhyAddress))
{
SMSC_WARNING("Failed to initialize Phy\r\n");
goto errorExit;
}
Tx_Initialize(privateData);
Rx_Initialize(privateData);
/* initialize the END of the structure */
if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, SMSC911X_DEV_NAME,
pDrvCtrl->unit, &smsc911xFuncTable,
"SMSC LAN91C111 Network Driver") == ERROR ||
END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
&pDrvCtrl->ucStationAddress[0], 6, ETHERMTU,
100000000) == ERROR )
goto errorExit;
SMSC_TRACE("endObj=%x,pDrvCtrl=%x,%s,unit=%d,bootDev=%s\r\n",pDrvCtrl->endObj,pDrvCtrl,SMSC911X_DEV_NAME,pDrvCtrl->unit,sysBootParams.bootDev);
/* set the flags to indicate readiness */
END_OBJ_READY (&pDrvCtrl->endObj,
IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
| IFF_MULTICAST | IFF_SIMPLEX |IFF_DEBUG);
SMSC_TRACE(" -Smsc911xLoad Success.\r\n") ;
return (&pDrvCtrl->endObj);
errorExit:
if (pDrvCtrl != NULL)
free ((char *)pDrvCtrl);
SMSC_TRACE(" -Smsc911xLoad failed.\r\n") ;
return NULL;
}
/*******************************************************************************
* smsc911xInitParse - parse the initialization string
*
* Parse the input string. Fill in values in the driver control structure.
* The initialization string format is:
* "<unit>:<IOBase>:<interruptVector>:<interruptLevel>:<offset>:<configValue>
*
* RETURNS: OK, or ERROR if any arguments are invalid.
*/
STATUS smsc911xInitParse
(
SMSC911XEND_DEVICE * pDrvCtrl,
char * initString
)
{
SMSC_TRACE("+smsc911xInitParse\r\n") ;
/* Parse the init string, initialize device structure */
if (sscanf(initString, "%x:%x:%x:%x:%x:%x",
&(pDrvCtrl->unit),
&(pDrvCtrl->IOBase),
&(pDrvCtrl->ivec),
&(pDrvCtrl->ilevel),
&(pDrvCtrl->offset),
&(pDrvCtrl->InitConfigVal)
) != 6
/* the number of parameters */ )
{
SMSC_TRACE(" Init string parsing failed!\r\n-smsc911xInitParser\r\n");
return (ERROR);
}
pDrvCtrl->IOBase = MEDUSA_BASE;
pDrvCtrl->ilevel = BSP_IPL_MEDUSA;
pDrvCtrl->offset = 2 ;
pDrvCtrl->unit = 0;
pDrvCtrl->private_data.dwLanBase = pDrvCtrl->IOBase ;
pDrvCtrl->fRxDMAMode=FALSE;
pDrvCtrl->fTxDMAMode=FALSE;
pDrvCtrl->PhyAddress=0xFFFFFFFF; /* internal PHY*/
SMSC_TRACE("-smsc911xInitParse\r\n") ;
return OK;
}
/*******************************************************************************
* smsc911xMemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
STATUS smsc911xMemInit
(
SMSC911XEND_DEVICE * pDrvCtrl /* device to be initialized */
)
{
SMSC_TRACE("+smsc911xMemInit\r\n");
pDrvCtrl->numFrames = 128;
/* Allocate space for the NET_POOL */
if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
return (ERROR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -