📄 ax88796end.c
字号:
len = ax88796PacketGet (pDrvCtrl, pBuf + pDrvCtrl->offset);
if (len <= 0)
{
logMsg ("ax88796HandleRcvInt: bad packet! (len=%d)\n",
len, 0, 0, 0, 0, 0);
ax88796Config (pDrvCtrl, TRUE);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
break;
}
pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool,
M_DONTWAIT, MT_DATA);
if (!pMblk)
{
ENDLOGMSG (("ax88796HandleRcvInt: Out of M Blocks!\n",
0, 0, 0, 0, 0, 0));
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
break;
}
pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT);
if (!pClBlk)
{
ENDLOGMSG (("ax88796HandleRcvInt: Out of CL Blocks!\n",
0, 0, 0, 0, 0, 0));
netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk);
break;
}
/* Associate the data pointer with the MBLK */
netClBlkJoin (pClBlk, pBuf, AX88796_BUFSIZ, NULL, 0, 0, 0);
/* Associate the data pointer with the MBLK */
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkPktHdr.len = len;
/* Adjust mData to match n23000PacketGet() above */
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
/* record received packet */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
/* buffer was used, will need another next time around */
pBuf = NULL;
}
/* If we still have an unused buffer, free it */
if (pBuf)
netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf);
/* Re-enable the receive interrupt */
oldLevel = intLock ();
pDrvCtrl->flags &= ~END_RECV_HANDLING_FLAG;
pDrvCtrl->imask |= IM_PRXE;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
ENDLOGMSG (("ax88796HandleRcvInt: done (flags=%x, imask=%x)\n",
pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0));
intUnlock (oldLevel);
}
/*******************************************************************************
*
* ax88796DataIn - input bytes from AX88796 memory
*
* NOMANUAL
*/
LOCAL void ax88796DataIn
(
AX88796END_DEVICE * pDrvCtrl,
int eneAddress,
int len,
char * pData
)
{
if (len == 0)
return;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RREAD | CMD_START);
delay (20);
while (len--)
{
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, pData++);
}
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
}
/*******************************************************************************
*
* ax88796DataOut - output bytes to AX88796 memory
*
* NOMANUAL
*/
LOCAL void ax88796DataOut
(
AX88796END_DEVICE * pDrvCtrl,
char * pData,
int len,
int eneAddress
)
{
if (len == 0)
return;
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, (char)0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RWRITE | CMD_START);
while (len--)
{
SYS_OUT_CHAR (pDrvCtrl, ENE_DATA, *(pData++));
}
}
/*******************************************************************************
*
* ax88796Send - 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 ax88796Send
(
void* pCookie, /* device ptr */
M_BLK_ID pMblk /* data to send */
)
{
int len;
UCHAR cmdStat;
AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
{
return (END_ERR_BLOCK);
}
/* Note device receive interrupts may still be enabled */
END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
pDrvCtrl->flags |= END_TX_BLOCKED;
if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
{
int cnt;
ENDLOGMSG (("ax88796Send: waiting for TX_IN_PROGRESS\n",
0,0,0,0,0,0));
/* Wait up to 1 second */
cnt = sysClkRateGet ();
while ((pDrvCtrl->flags & END_TX_IN_PROGRESS) && (cnt-- > 0))
taskDelay (1);
}
/* Disable device interrupts and check for overwrite detected */
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
{
ENDLOGMSG (("ax88796Send: overwrite detected (timeout)\n",
0, 0, 0, 0, 0, 0));
pDrvCtrl->flags &= ~END_TX_BLOCKED;
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return (END_ERR_BLOCK);
}
/* If TX still in progress, re-configure chip */
if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
{
UCHAR tstat;
SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &tstat);
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
logMsg ("ax88796Send: timeout: flags=%x cmd=%02x stat=%02x\n",
pDrvCtrl->flags, cmdStat, tstat, 0, 0, 0);
ax88796Config (pDrvCtrl, TRUE);
return (ERROR);
}
/* Copy and free the MBLK */
len = netMblkToBufCopy (pMblk, pDrvCtrl->packetBuf, NULL);
netMblkClChainFree (pMblk);
len = max (len, ETHERSMALL);
/* Transfer to the device */
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0x00);
ax88796DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (AX88796_TSTART << 8));
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
/* kick Transmitter */
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE0);
SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, AX88796_TSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTH, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTL, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP | CMD_START);
/* mark tx as in progress */
pDrvCtrl->flags |= END_TX_IN_PROGRESS;
/* Re-enable device TX interrupts */
pDrvCtrl->imask |= (IM_TXEE | IM_PTXE);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
/* update statistics */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
return (OK);
}
/*******************************************************************************
*
* ax88796PacketGet - get next received message
*
* Get next received message. Returns NULL if none are
* ready.
*
* RETURNS: ptr to next packet, or NULL if none ready.
*/
LOCAL int ax88796PacketGet
(
AX88796END_DEVICE *pDrvCtrl,
char *pData
)
{
UINT packetSize;
UINT8 tempPage; /* used in buffer validation */
UINT8 pageCount; /* used in buffer validation */
UINT packetLen = 0;
AX88796_HEADER h;
if (pDrvCtrl->nextPacket == pDrvCtrl->current)
return (0);
ax88796DataIn (pDrvCtrl,
(((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff),
sizeof (AX88796_HEADER), (char *) &h);
/*
logMsg ("rstat = %x; next = %x; lowByteCnt = %x; uppByteCnt = %x\n",
h.rstat, h.next, h.lowByteCnt, h.uppByteCnt, 5, 6);
*/
/* compute packet size excluding Ethernet checksum bytes */
packetSize = (((UINT)h.uppByteCnt << 8) + h.lowByteCnt);
/* Check for packet (and header) shifted in memory (by heavy load).
* The method and solution are recommended by 3Com in their
* EtherLink II Adapter Technical Manual, with the addition of
* a reasonableness check on the next-page link.
*/
pageCount = (UCHAR) ((packetSize + sizeof (AX88796_HEADER)
+ (ENE_PAGESIZE - 1)) / ENE_PAGESIZE);
tempPage = (UCHAR) (pDrvCtrl->nextPacket + pageCount);
if (tempPage >= AX88796_PSTOP)
tempPage -= (AX88796_PSTOP - AX88796_PSTART);
if ((h.next != tempPage) ||
(h.next < AX88796_PSTART) || (h.next >= AX88796_PSTOP))
{
/* can't trust anything now */
pDrvCtrl->stats.badPacket++;
pDrvCtrl->stats.rerror++;
/* stop and restart the interface */
if (!(pDrvCtrl->flags & (END_OVERWRITE|END_OVERWRITE2)))
// ax88796Config (pDrvCtrl, TRUE);
return (-1);
}
/* reject runts, although we are configured to reject them */
if (packetSize < 60)
{
pDrvCtrl->stats.shortPacket++;
goto doneGet;
}
/* reject packets larger than our scratch buffer */
if (packetSize > AX88796_BUFSIZ)
goto doneGet;
/* Signal that we received a good packet */
packetLen = packetSize;
/* copy separated frame to a temporary buffer */
ax88796DataIn (pDrvCtrl,
((UINT)pDrvCtrl->nextPacket << 8) + sizeof (AX88796_HEADER),
packetLen,
pData);
doneGet:
pDrvCtrl->nextPacket = h.next;
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND,
(pDrvCtrl->nextPacket != AX88796_PSTART ?
pDrvCtrl->nextPacket - 1 : AX88796_PSTOP - 1));
return (packetLen);
}
/******************************************************************************
*
* ax88796PollRecv - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device.
*/
LOCAL STATUS ax88796PollRecv
(
void* pCookie, /* device ptr */
M_BLK_ID pMblk
)
{
int len;
AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;
/* If no packet is available return immediately */
pDrvCtrl->current = ax88796GetCurr (pDrvCtrl);
if (pDrvCtrl->nextPacket == pDrvCtrl->current)
return ((STATUS) (EAGAIN));
/* Upper layer provides the buffer, make sure it's big enough. */
if ((pMblk->mBlkHdr.mLen < AX88796_BUFSIZ)
|| !(pMblk->mBlkHdr.mFlags & M_EXT))
{
return ((STATUS) (EAGAIN));
}
ENDLOGMSG (("ax88796PollRecv: enter: imask=%02x\n",
pDrvCtrl->imask, 0, 0, 0, 0, 0));
len = ax88796PacketGet (pDrvCtrl, pMblk->mBlkHdr.mData + pDrvCtrl->offset);
if (len <= 0)
return ((STATUS) (EAGAIN));
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkPktHdr.len = len;
/* Adjust mData to match n23000PacketGet() above */
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
ENDLOGMSG (("ax88796PollRecv: done: imask=%02x\n",
pDrvCtrl->imask, 0, 0, 0, 0, 0));
return (OK);
}
/*******************************************************************************
*
* ax88796PollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*/
static STATUS ax88796PollSend
(
void* pCookie, /* device ptr */
M_BLK_ID pMblk
)
{
char * pBuf;
UCHAR cmdStat;
int len;
AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;
ENDLOGMSG (("ax88796PollSend: enter: imask=%x flags=%x\n",
pDrvCtrl->imask, pDrvCtrl->flags, 0, 0, 0, 0));
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
while (cmdStat & CMD_TXP)
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, &cmdStat);
/* Get the next TXD */
pBuf = pDrvCtrl->packetBuf;
len = netMblkToBufCopy (pMblk, pBuf, NULL);
len = max (len, ETHERSMALL);
/* Transfer to the device */
ax88796DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (AX88796_TSTART << 8));
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
/* kick Transmitter */
SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, AX88796_TSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTH, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTL, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP | CMD_START);
/* update statistics */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
/* Spin until the packet has been sent */
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
while (cmdStat & CMD_TXP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -