📄 gei82543end.c
字号:
UINT8 tmpBuf[ETHER_ADDRESS_SIZE]; /* array to save ETH addr */
UINT16 hashVal; /* hash value for MTA */
UINT32 lowAdr; /* adr low in RTA */
UINT32 highAdr; /* adr high in RTA */
DRV_LOG (DRV_DEBUG_IOCTL, ("gei82543AddrFilterSet...\n"), 0,0,0,0,0,0);
/* clean up all multicasting address in RTA and MTA */
gei82543McastAdrClean(pDrvCtrl);
/* get the number of multicasting address */
if ((count = pDrvCtrl->drvObj.nMulti) == 0)
{
return;
}
if (count > MAX_NUM_MULTI)
{
LOGMSG("only accept %d multicast address\n",MAX_NUM_MULTI,2,3,4,5,6);
count = MAX_NUM_MULTI;
}
/*
* The first 15 multicast will stored in the RAT (RAL/RAH)
* the rest are stored in MAT
*/
pCurr = (ETHER_MULTI *)lstFirst(&(pDrvCtrl->drvObj.multiList));
/* the first entry (i=0) in RAT is not for multicast addr */
for (i = 1; i< NUM_RAR && count; i++, count--)
{
memcpy ((void * )tmpBuf, (const void *)pCurr->addr, ETHER_ADDRESS_SIZE);
lowAdr = tmpBuf[0] | (tmpBuf[1] << 8) | (tmpBuf[2] << 16) |
(tmpBuf[3] << 24);
highAdr = tmpBuf[4] | (tmpBuf[5] << 8);
GEI_WRITE_REG((INTEL_82543GC_RAL + 8 *(UINT32)i), lowAdr);
GEI_WRITE_REG((INTEL_82543GC_RAH +8 * (UINT32)i), (highAdr | RAH_AV_BIT));
pCurr = END_MULTI_LST_NEXT(pCurr);
}
/* configure MTA table if more multicast address remaining */
while (count--)
{
memcpy ((void *)tmpBuf, (const void *)pCurr->addr, ETHER_ADDRESS_SIZE);
/*
* compose hash value based on filter type :
* MULTI_FILTER_TYPE_47_36: 47 - 36 bits for dest multicast addr match
* MULTI_FILTER_TYPE_46_35: 46 - 35 bits for dest multicast addr match
* MULTI_FILTER_TYPE_45_34: 45 - 34 bits for dest multicast addr match
* MULTI_FILTER_TYPE_43_32: 43 - 32 bits for dest multicast addr match
*/
if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_47_36)
{
hashVal = (tmpBuf[4] >> 4) | ((UINT16)(tmpBuf[5]) << 4);
}
else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_46_35)
{
hashVal = (tmpBuf[4] >> 3) | ((UINT16)(tmpBuf[5]) << 5);
}
else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_45_34)
{
hashVal = (tmpBuf[4] >> 2) | ((UINT16)(tmpBuf[5]) << 6 );
}
else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_43_32)
{
hashVal = tmpBuf[4] | ((UINT16)(tmpBuf[5]) << 8 );
}
else
{
LOGMSG("Error in compose multicast hash value\n",1,2,3,4,5,6);
return;
}
/* the first 5 bits is the bit location (32 maximum) in a register */
col = hashVal & 0x1f;
/* the remaining 7 bits is for the register offset (128 maximum) */
row = (hashVal >> 5) & 0x7f;
GEI_READ_REG((INTEL_82543GC_MTA + (UINT32)row * 32), (UINT32)tmp);/*lint !e63*/
/* find the right bit location */
tmp |= (1 << col);
GEI_WRITE_REG((INTEL_82543GC_MTA +(UINT32)row * 32), (UINT32)tmp);
pCurr = END_MULTI_LST_NEXT(pCurr);
}
taskDelay (sysClkRateGet() / 20);
DRV_LOG (DRV_DEBUG_IOCTL,("gei82543AddrFilterSet...Done\n"), 0,0,0,0,0,0);
return;
}
/*************************************************************************
*
* gei82543EndMCastAdd - add a multicast address for the device
*
* This routine adds a multicast address to whatever the driver
* is already listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS gei82543EndMCastAdd
(
END_DEVICE * pDrvCtrl, /* pointer to drvObject */
char* pAddress /* address you want to add to list */
)
{
int error;
if ((error = etherMultiAdd (&pDrvCtrl->drvObj.multiList, pAddress)) ==
ENETRESET)
{
pDrvCtrl->drvObj.nMulti++;
if (pDrvCtrl->drvObj.nMulti > MAX_NUM_MULTI)
{
pDrvCtrl->drvObj.nMulti--;
etherMultiDel (&pDrvCtrl->drvObj.multiList,pAddress);
return ERROR;
}
else
gei82543AddrFilterSet(pDrvCtrl);
}
return (OK);
}
/*************************************************************************
*
* gei82543EndMCastDel - delete a multicast address for the device
*
* This routine removes a multicast address from whatever the driver
* is listening for. It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS gei82543EndMCastDel
(
END_DEVICE * pDrvCtrl, /* device pointer */
char * pAddress /* address to be deleted */
)
{
int error;
if ((error = etherMultiDel (&pDrvCtrl->drvObj.multiList,(char *)pAddress))
== ENETRESET)
{
gei82543AddrFilterSet(pDrvCtrl);
pDrvCtrl->drvObj.nMulti--;
}
return OK;
}
/*****************************************************************************
*
* gei82543EndMCastGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS gei82543EndMCastGet
(
END_DEVICE * pDrvCtrl, /* device pointer */
MULTI_TABLE * pTable /* address table to be filled in */
)
{
return (etherMultiGet (&pDrvCtrl->drvObj.multiList, pTable));
}
/*************************************************************************
*
* gei82543EndStop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS gei82543EndStop
(
END_DEVICE *pDrvCtrl /* device to be stopped */
)
{
/* check device attach flag */
if (pDrvCtrl->attach != TRUE)
{
return ERROR;
DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStop:Driver does not load successfully!\n", 1, 2,3, 4, 5, 6);
}
IF_DRV_TX_SEM_TAKE (&pDrvCtrl->drvObj, WAIT_FOREVER);
/* check device start flag */
if (pDrvCtrl->devStartFlag != TRUE)
{
DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStop:Driver has not been started!\n", 1, 2,3, 4, 5, 6);
IF_DRV_TX_SEM_GIVE(&pDrvCtrl->drvObj);
return OK;
}
/* turn off system interrupts */
if(ERROR == b_pciUnitIntDisable((UINT8)pDrvCtrl->drvObj.slot))
{
DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStop:Could not disable interrupt!\n", 1, 2, 3, 4, 5, 6);
}
/* disable TX/RX operation */
gei82543TxRxDisable (pDrvCtrl);
/*disable 82543 chip interrupt*/
gei82543DisableChipInt (pDrvCtrl);
/*wait for rx interrupt handling*/
while (pDrvCtrl->rxtxHandling)
{
DRV_LOG (DRV_DEBUG_LOAD,"gei82543EndStop:wait slot %d's Rx handler!\n", pDrvCtrl->drvObj.slot, 2, 3, 4, 5, 6);
taskDelay(1);
}
/*mark the driver stop*/
pDrvCtrl->devStartFlag = FALSE;
DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStop:Driver stops successfully!\n", 1, 2, 3, 4, 5, 6);
IF_DRV_TX_SEM_GIVE(&pDrvCtrl->drvObj);
return OK;
}
/*************************************************************************
*
* gei82543EndUnload - unload a driver from the system
*
* This function first brings down the device, and then frees any
* stuff that was allocated by the driver in the load function.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS gei82543EndUnload
(
END_DEVICE* pDrvCtrl /* device to be unloaded */
)
{
/* stop the device if not yet */
if (pDrvCtrl->devStartFlag != FALSE)
{
gei82543EndStop (pDrvCtrl);
}
/*
* netJob queue may still have some unfinished work for this device, so
* inserting the "unload" function after those unfinished work.
* Warning - It's not a good idea to place much burden on
* tNetTask since it may be the only vehicle to pass packets (including
* other interfaces) to the high layer.
*/
if (netTaskId != ERROR && netTaskId != 0)
{
fwdJobAdd ((FUNCPTR)gei8254xNowUnload , (int)pDrvCtrl,
0,0,0,0);
}
else
gei8254xNowUnload (pDrvCtrl);
return OK;
}
/*******************************************************************
* gei8254xNowUnload - free memory when unload the device
*
* This function will free all memory allocated by this devices;
* It is called when gei82543EndUnload is involved
*
* RETURN: N/A
*/
LOCAL void gei8254xNowUnload
(
END_DEVICE* pDrvCtrl /* device to be unloaded */
)
{
DRV_LOG (DRV_DEBUG_LOAD, ("gei82543Unload end....\n"), 1, 2, 3, 4, 5, 6);
if (pDrvCtrl->drvObj.txSem !=(SEM_ID) NULL)
semDelete (pDrvCtrl->drvObj.txSem);
/* free allocated memory */
pDrvCtrl->attach = FALSE;
gei82543MemAllFree (pDrvCtrl);
DRV_LOG (DRV_DEBUG_LOAD, ("gei82543Unload... Done\n"), 1, 2, 3, 4, 5, 6);
return (void)OK;
}
/**************************************************************************
*
* gei82543TxSetup - configure and setup TX for running
*
* This routine sets up the data structure for TX and configures transmitter
*
* RETURNS: N/A
*/
LOCAL void gei82543TxSetup
(
END_DEVICE * pDrvCtrl /* device to set up TX descriptors */
)
{
int ix;
INTEL82543_TX_DES* pTxDesc;
UINT32 txdctlVal; /* TXDCTL register value */
UINT32 count; /* temp var */
UINT32 tmpAddr=0;
char * pEndBuf;
/* initialization for TX operation*/
pDrvCtrl->txDescTail = 0;
pDrvCtrl->txStall = FALSE;
pDrvCtrl->txDescFreeNum = (volatile UINT32 )pDrvCtrl->txDescNum - 1;
pDrvCtrl->txDescLastCheck = (volatile UINT32 )pDrvCtrl->txDescNum - 1;
/* pre-init the transmit buffer memory */
for (ix = 0; ix < pDrvCtrl->txDescNum; ix++)
{
/*empty current DESC which packet have been sent out by MAC controller.*/
pEndBuf = pDrvCtrl->pEndBufForMng[ix];
if ((char *)NULL != pEndBuf)
{
DRV_LOG (DRV_DEBUG_LOAD, "gei82543TxSetup...Free TxBD!\n", 1, 2, 3, 4, 5, 6);
endPktFree(pEndBuf);/* clean the tx buffer */
pEndBuf=NULL;
pDrvCtrl->pEndBufForMng[ix]=NULL;
DRV_CHG_CNT(pDrvCtrl->txResFreeNum,1);
}
/*get the txBDs pointer*/
pTxDesc = (INTEL82543_TX_DES*)GEI_GET_TX_DESC_ADDR(ix);
/* set up the command field */
GEI_WRITE_DESC_BYTE(pTxDesc, TXDESC_CMD_OFFSET,
(TXD_CMD_EOP | TXD_CMD_IFCS |
TXD_CMD_IDE | TXD_CMD_RS));
/* set DD bits in STATUS field */
GEI_WRITE_DESC_BYTE(pTxDesc, TXDESC_STATUS_OFFSET, TXD_STAT_DD);
}
/* set the TX descriptor BASE register */
tmpAddr= (UINT32)sysVirtToPhys((void *)(pDrvCtrl->pTxDescBase));
GEI_WRITE_REG(INTEL_82543GC_TDBAL, tmpAddr);
GEI_WRITE_RE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -