📄 auend.c
字号:
pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
goto cleanRXD;
}
/*
* OK we've got a spare, 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, pCluster);
DRV_LOG (DRV_DEBUG_RX, "auRecv: Out of M Blocks!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
goto cleanRXD;
}
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
bcopy (pBuf, pCluster + pDrvCtrl->offset, len);
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
/* restore the receiver buffer */
DRV_LOG (DRV_DEBUG_RX, "auRecv: data trans to clusters OK, 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);
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);
return (OK);
cleanRXD:
/* Restore the receiver buffer */
DRV_LOG (DRV_DEBUG_RX, "auRecv: 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);
return (OK);
}
/*******************************************************************************
*
* auSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer. The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS auSend
(
AU_DRV_CTRL * pDrvCtrl, /* driver control structure */
M_BLK_ID pMblk /* data to send */
)
{
char * pBuf;
int index;
int len = 0;
UINT32 addr;
DRV_LOG (DRV_DEBUG_TX, "auSend...\n", 1, 2, 3, 4, 5, 6);
/* check device mode */
if (pDrvCtrl->flags & AU_POLLING)
{
netMblkClChainFree (pMblk);
errno = EINVAL;
return (ERROR);
}
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
/* Advance our management index (first) */
index = pDrvCtrl->tmdIndex;
if (AU_TX_ADDRESS(index) & 0x03)
{
/* Are we still on the first chunk? */
DRV_LOG (DRV_DEBUG_TX, "auSend: Out of TMDs! addr=%08x astat=%08x stat=%08x\n",
AU_TX_ADDRESS(index) & ~0x1f,
AU_TX_ADDRESS(index) & 0x1f,
AU_TX_STATUS(index), 4, 5, 6);
#ifdef DRV_DEBUG
auDump (pDrvCtrl->unit);
#endif
pDrvCtrl->txBlocked = TRUE;
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return (END_ERR_BLOCK);
}
pBuf = pDrvCtrl->pTxMem[index];
DRV_LOG (DRV_DEBUG_TX, "auSend: pBuf = 0x%X\n", (int)pBuf, 2, 3, 4, 5, 6);
if (pBuf == NULL)
{
pDrvCtrl->txBlocked = TRUE;
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return (END_ERR_BLOCK);
}
/* copy and release the packet */
len = netMblkToBufCopy (pMblk, pBuf, NULL);
netMblkClChainFree (pMblk);
if (len < ETHERSMALL)
{
/* Pad to ETHERSMALL with zeros, required by H/W */
bzero (&pBuf[len], ETHERSMALL - len);
len = ETHERSMALL;
}
/* setting DMA regs to prepare transmit */
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();
DRV_LOG (DRV_DEBUG_TX, "auSend: index %d len %d\n",
index, len, 3, 4, 5, 6);
DRV_LOG (DRV_DEBUG_TX, "auSend: dst=%02x:%02x:%02x:%02x:%02x:%02x\n",
pBuf[0]&0xff, pBuf[1]&0xff, pBuf[2]&0xff,
pBuf[3]&0xff, pBuf[4]&0xff, pBuf[5]&0xff);
DRV_LOG (DRV_DEBUG_TX, "auSend src=%02x:%02x:%02x:%02x:%02x:%02x\n",
pBuf[6]&0xff, pBuf[7]&0xff, pBuf[8]&0xff,
pBuf[9]&0xff, pBuf[10]&0xff, pBuf[11]&0xff);
DRV_LOG (DRV_DEBUG_RX, "auSend: type(len)=%02x %02x\n",
pBuf[12]&0xff, pBuf[13]&0xff, 0,0,0,0);
/* Advance our management index */
index = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
pDrvCtrl->tmdIndex = index;
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
DRV_LOG (DRV_DEBUG_TX, "auSend...Done\n", 1, 2, 3, 4, 5, 6);
return (OK);
}
/*******************************************************************************
*
* auIoctl - the driver I/O control routine
*
* Process a ioctl request.
*
* RETURNS OK or ERROR value
*/
LOCAL int auIoctl
(
AU_DRV_CTRL * pDrvCtrl, /* driver control structure */
int cmd, /* ioctl command to execute */
caddr_t data /* data to get or set */
)
{
long value;
int error = 0;
switch (cmd)
{
case EIOCSADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
END_HADDR_LEN (&pDrvCtrl->endObj));
break;
case EIOCGADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data,
END_HADDR_LEN (&pDrvCtrl->endObj));
break;
case EIOCSFLAGS:
value = (long)data;
if (value < 0)
{
value = -value;
value--; /* complement code? */
END_FLAGS_CLR (&pDrvCtrl->endObj, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->endObj, value);
}
auConfig (pDrvCtrl);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj);
break;
case EIOCMULTIADD:
error = auMCastAddrAdd (pDrvCtrl, (char *) data);
break;
case EIOCMULTIDEL:
error = auMCastAddrDel (pDrvCtrl, (char *) data);
break;
case EIOCMULTIGET:
error = auMCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data);
break;
case EIOCPOLLSTART:
error = auPollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP:
error = auPollStop (pDrvCtrl);
break;
case EIOCGMIB2:
if (data == NULL)
return (EINVAL);
bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->endObj.mib2Tbl));
break;
case EIOCGFBUF:
if (data == NULL)
return (EINVAL);
*(int *)data = AU_MIN_FBUF;
break;
case EIOCGMWIDTH:
if (data == NULL)
return (EINVAL);
*(int *)data = 4;
break;
case EIOCGHDRLEN:
if (data == NULL)
return (EINVAL);
*(int *)data = 14;
break;
default:
error = EINVAL;
}
return (error);
}
/*******************************************************************************
*
* auReset - hardware reset of chip (stop it)
*
* This routine is responsible for resetting the device.
*
* RETURNS: OK/ERROR
*/
LOCAL int auReset
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
int i;
DRV_LOG (DRV_DEBUG_LOAD, "auReset...\n", 1, 2, 3, 4, 5, 6);
/* Reset MAC & DMA units */
AU_MAC_ENABLE = 0;
/* setup Rx DMA registers */
pDrvCtrl->rmdIndex = 0;
for (i = 0; i < pDrvCtrl->rringSize; ++i)
{
AU_RX_STATUS(i) = 0;
AU_RX_ADDRESS(i) = 0;
}
/* setup Tx DMA registers */
pDrvCtrl->tmdIndex = 0;
pDrvCtrl->tmdLastIndex = 0;
for (i = 0; i < pDrvCtrl->tringSize; ++i)
{
AU_TX_STATUS(i) = 0;
AU_TX_LENGTH(i) = 0;
AU_TX_ADDRESS(i) = 0;
}
SYS_WB_FLUSH();
DRV_LOG (DRV_DEBUG_LOAD, "auReset...done\n", 1, 2, 3, 4, 5, 6);
return (OK);
}
/*******************************************************************************
*
* auRestartSetup - setup memory descriptors and turn on chip
*
* This routine initializes all the shared memory structures and turns on
* the chip.
*
* RETURNS OK/ERROR
*/
LOCAL STATUS auRestartSetup
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
DRV_LOG (DRV_DEBUG_LOAD, "auRestartSetup...\n", 1, 2, 3, 4, 5, 6);
/* reset the device */
auReset (pDrvCtrl);
DRV_LOG (DRV_DEBUG_LOAD, "auRestartSetup: MAC DMA reset complete\n", 1, 2, 3, 4, 5, 6);
/* reconfigure the device */
auConfig (pDrvCtrl);
DRV_LOG (DRV_DEBUG_LOAD, "auRestartSetup...done\n", 1, 2, 3, 4, 5, 6);
return (OK);
}
/*******************************************************************************
*
* auRestart - restart the device after a fatal error
*
* This routine takes care of all the messy details of a restart. The device
* is reset and re-initialized. The driver state is re-synchronized.
*
* RETURNS: N/A
*/
LOCAL void auRestart
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
auRestartSetup (pDrvCtrl);
/* set the flags to indicate readiness */
END_OBJ_READY (&pDrvCtrl->endObj,
IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
| IFF_MULTICAST);
}
/******************************************************************************
*
* auConfig - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode, and changing the
* multicast interface list.
*
* RETURNS: N/A
*/
LOCAL void auConfig
(
AU_DRV_CTRL * pDrvCtrl /* control structure */
)
{
UCHAR * enetAddr;
int i;
DRV_LOG (DRV_DEBUG_LOAD, "auConfig...\n", 1, 2, 3, 4, 5, 6);
/* Set promiscuous mode if it's asked for. */
if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC)
{
DRV_LOG (DRV_DEBUG_LOAD, "auConfig: promiscuous flag set!\n",
1, 2, 3, 4, 5, 6);
/* chip will be in promiscuous mode */
pDrvCtrl->flags |= AU_PROMISCUOUS_FLAG;
}
else
{
DRV_LOG (DRV_DEBUG_LOAD, "auConfig: promiscuous flag un-set!\n",
1, 2, 3, 4, 5, 6);
pDrvCtrl->flags &= ~AU_PROMISCUOUS_FLAG;
}
/* Set up address filter for multicasting. */
if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0)
{
auAddrFilterSet (pDrvCtrl);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -