📄 auend.c
字号:
/* Enable the MAC */
AU_MAC_ENABLE = AU_MAC_ENABLE_CLOCKS_ONLY;
SYS_WB_FLUSH();
AU_MAC_ENABLE = AU_MAC_ENABLE_NORMAL & ~AU_MAC_ENABLE_TS;
SYS_WB_FLUSH();
/* Configure the MAC */
#if (_BYTE_ORDER == _BIG_ENDIAN)
AU_MAC_CONTROL = AU_MAC_CONTROL_EM_BIG | AU_MAC_CONTROL_DO;
#else
AU_MAC_CONTROL = AU_MAC_CONTROL_DO;
#endif
enetAddr = pDrvCtrl->enetAddr;
AU_MAC_ADDRESS_HIGH = (enetAddr[5] << 8) | enetAddr[4];
AU_MAC_ADDRESS_LOW = ((enetAddr[3] << 24)
| (enetAddr[2] << 16)
| (enetAddr[1] << 8)
| (enetAddr[0] << 0));
DRV_LOG (DRV_DEBUG_LOAD, "auConfig: MAC addr is(%08x %08x)\n",
AU_MAC_ADDRESS_HIGH,
AU_MAC_ADDRESS_LOW, 0, 0, 0, 0);
DRV_LOG (DRV_DEBUG_LOAD, "auConfig: Initial multi addr is (%08x %08x)\n",
AU_MULTICAST_HASH_ADDRESS_HIGH,
AU_MULTICAST_HASH_ADDRESS_LOW, 0, 0, 0, 0);
/* Configure MII */
/* Setup RxD and TxD pointers: / and % */
pDrvCtrl->rmdIndex = (AU_RX_ADDRESS(0) >> 2) & 0x03;
pDrvCtrl->tmdIndex = (AU_TX_ADDRESS(0) >> 2) & 0x03;
pDrvCtrl->tmdLastIndex = pDrvCtrl->tmdIndex;
#ifdef AU_PROMISCUOS_MODE
/* Handle promiscuous mode */
if (pDrvCtrl->flags & AU_PROMISCUOUS_FLAG)
AU_MAC_CONTROL |= AU_MAC_CONTROL_PR;
#endif
for (i = 0; i < pDrvCtrl->rringSize; ++i)
AU_RX_ADDRESS(i)
= ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[i])) | 1;
/* Enable transmit and receive */
AU_MAC_CONTROL |= AU_MAC_CONTROL_TE | AU_MAC_CONTROL_RE;
SYS_WB_FLUSH();
DRV_LOG (DRV_DEBUG_LOAD, "auConfig...done\n", 1, 2, 3, 4, 5, 6);
}
/******************************************************************************
*
* auAddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list of
* addresses (added with the auAddrAdd()(auMCastAddrAdd??) routine) and sets the
* device's filter correctly.
*
* RETURNS: N/A
*/
LOCAL void auAddrFilterSet
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
ETHER_MULTI * pCurr;
UINT8 * pCp;
UINT8 byte;
UINT32 crc;
int len;
int count;
pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
while (pCurr != NULL)
{
pCp = (UINT8 *)&pCurr->addr;
crc = 0xffffffff;
for (len = AU_LA_LEN; --len >= 0;)
{
byte = *pCp++;
for (count = 0; count < AU_LAF_LEN; count++)
{
if ((byte & 0x01) ^ (crc & 0x01))
{
crc >>= 1;
crc = crc ^ AU_CRC_POLYNOMIAL;
}
else
{
crc >>= 1;
}
byte >>= 1;
}
}
/* Just want the 6 most significant bits. */
crc = AU_CRC_TO_LAF_IX (crc);
pCurr = END_MULTI_LST_NEXT(pCurr);
}
}
/*******************************************************************************
*
* auPollReceive - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device. This routine return OK if it is successful in getting the packet
*
* RETURNS: OK or EAGAIN.
*/
LOCAL STATUS auPollReceive
(
AU_DRV_CTRL * pDrvCtrl, /* driver control structure */
M_BLK_ID pMblk
)
{
int len;
char * pBuf;
UINT32 status;
UINT32 ERROR_MASK=0x812bc000;
int rmdIndex;
DRV_LOG (DRV_DEBUG_POLL_RX, "auPollReceive: Poll Rx...\n", 1, 2, 3, 4, 5, 6);
/* Handle zero or more newly received frames */
if (!(AU_RX_ADDRESS(pDrvCtrl->rmdIndex) & (1<<1)))
{
pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
/* goto cleanRx; */
return (EAGAIN);
}
/* Extract packet particulators */
rmdIndex = pDrvCtrl->rmdIndex;
/* Read the device status register */
status = AU_RX_STATUS(rmdIndex);
len = AU_RX_STATUS (rmdIndex) & 0x3fff; /* get packet length */
pBuf = pDrvCtrl->pRxMem[rmdIndex];
if (status & (ERROR_MASK & ~0x0))
{
DRV_LOG (DRV_DEBUG_POLL_RX, "auPollReceive: Poll Rx error, status=0x%x\n", status, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
/* restart chip on fatal error.??? */
if (status & ERROR_MASK & 0x0) /* memory error */
{
END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
DRV_LOG (DRV_DEBUG_POLL_RX, "auPollReceive: Poll Rx restart\n", 1, 2, 3, 4, 5, 6);
auRestart (pDrvCtrl);
return (EAGAIN);
}
/* goto cleanRx; */
goto cleanRx;
}
if (!len)
{
DRV_LOG (DRV_DEBUG_RX, "auPollReceive: RMD error!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
goto cleanRx; /* skip to clean up */
}
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
/* Upper layer provides the buffer. */
if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
{
DRV_LOG (DRV_DEBUG_POLL_RX, "auPollReceive: bad mblk,len:%d flags:%d\n",
pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6);
return (EAGAIN);
}
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
bcopy (pBuf, pMblk->mBlkHdr.mData, len);
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
cleanRx:
/* Restore the receiver buffer */
DRV_LOG (DRV_DEBUG_RX, "auPollReceive: error occurs, clean index %d %08x\n",
rmdIndex, AU_RX_ADDRESS(rmdIndex) & 0x1f, 0, 0, 0, 0);
AU_RX_STATUS(rmdIndex) = 0;
AU_RX_ADDRESS(rmdIndex)
= ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[rmdIndex])) | 1;
SYS_WB_FLUSH();
/* Advance our management index */
pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
DRV_LOG (DRV_DEBUG_POLL_RX, "auPollReceive: Poll Rx...done\n", 1, 2, 3, 4, 5, 6);
return (OK);
}
/*******************************************************************************
*
* auPollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*
* RETURNS: OK or EAGAIN.
*/
LOCAL STATUS auPollSend
(
AU_DRV_CTRL * pDrvCtrl, /* driver control structure */
M_BLK_ID pMblk
)
{
char * pBuf;
int index;
int len = 0;
UINT32 addr;
DRV_LOG (DRV_DEBUG_POLL_TX, "auPollSend: Poll Tx...\n", 1, 2, 3, 4, 5, 6);
/* Advance our management index (first) */
index = pDrvCtrl->tmdIndex;
if (AU_TX_ADDRESS(index) & 0x01)
{
DRV_LOG (DRV_DEBUG_POLL_TX, "auPollSend: Out of tmds.\n", 1, 2, 3, 4, 5, 6);
if (!pDrvCtrl->txCleaning)
auTRingScrub (pDrvCtrl);
return (EAGAIN);
}
pBuf = pDrvCtrl->pTxMem[index];
if (pBuf == NULL)
return (EAGAIN);
/* copy and release the packet */
len = netMblkToBufCopy (pMblk, pBuf, NULL);
if (len < ETHERSMALL)
{
/* Pad to ETHERSMALL with zeros, required by H/W */
bzero (&pBuf[len], ETHERSMALL - len);
len = ETHERSMALL;
}
addr = ((UINT32)AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pTxMem[index]) | 1);
AU_TX_LENGTH(index) = len;
AU_TX_STATUS(index) = 0;
AU_TX_ADDRESS(index) = addr;
SYS_WB_FLUSH();
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
/* Spin until we think we've sent it. */
while (!(AU_TX_ADDRESS(index) & (1<<1)));
AU_TX_ADDRESS(index) = 0;
AU_TX_STATUS(index) = 0;
AU_TX_LENGTH(index) = 0;
SYS_WB_FLUSH();
index = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
pDrvCtrl->tmdIndex = index;
pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) &
(pDrvCtrl->tringSize - 1);
DRV_LOG (DRV_DEBUG_POLL_TX, "auPollSend: Poll Tx...done\n", 1, 2, 3, 4, 5, 6);
return (OK);
}
/*****************************************************************************
*
* auMCastAddrAdd - 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
*/
LOCAL STATUS auMCastAddrAdd
(
AU_DRV_CTRL * pDrvCtrl, /* control structure */
char * pAddress
)
{
#ifdef AU_END_MULTICAST
int error;
if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList,
pAddress)) == ENETRESET)
auConfig (pDrvCtrl);
#endif
return (OK);
}
/*****************************************************************************
*
* auMCastAddrDel - 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.
*/
LOCAL STATUS auMCastAddrDel
(
AU_DRV_CTRL * pDrvCtrl, /* control structure */
char * pAddress
)
{
#if AU_END_MULTICAST
int error;
if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList,
(char *)pAddress)) == ENETRESET)
auConfig (pDrvCtrl);
#endif
return (OK);
}
/*****************************************************************************
*
* auMCastAddrGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK/ERROR
*/
LOCAL STATUS auMCastAddrGet
(
AU_DRV_CTRL * pDrvCtrl, /* control structure */
MULTI_TABLE * pTable
)
{
int error;
error = etherMultiGet (&pDrvCtrl->endObj.multiList, pTable);
return (error);
}
/*******************************************************************************
*
* auStop - 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 auStop
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
STATUS result = OK;
/* Stop the device. */
auReset (pDrvCtrl);
/* disable interrupt */
SYS_INT_DISABLE (pDrvCtrl);
/* mark the interface as down */
END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
/* disconnect the interrupt handler */
SYS_INT_DISCONNECT (pDrvCtrl, auInt, (int)pDrvCtrl, &result);
if (result == ERROR)
{
DRV_LOG (DRV_DEBUG_LOAD, "auStop: Could not disconnect interrupt!\n",
1, 2, 3, 4, 5, 6);
}
return (result);
}
/******************************************************************************
*
* auUnload - 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. The controller
* structure should be free by who ever is calling this function.
*
* RETURNS: OK
*/
LOCAL STATUS auUnload
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
/* Free the shared DMA memory. */
if (pDrvCtrl->pRxMem)
{
cacheDmaFree (pDrvCtrl->pRxMemBase);
pDrvCtrl->pRxMemBase = NULL;
}
if (pDrvCtrl->pTxMem)
{
cache
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -