📄 rtl81x9.c
字号:
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
break;
case EIOCPOLLSTART:
error = rtl81x9PollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP:
error = rtl81x9PollStop (pDrvCtrl);
break;
case EIOCGMIB2:
if (data == NULL)
return (EINVAL);
bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->end.mib2Tbl));
break;
case EIOCGFBUF:
if (data == NULL)
return (EINVAL);
*(int *)data = RTL_MIN_FBUF;
break;
case EIOCGMWIDTH:
if (data == NULL)
return (EINVAL);
*(int *)data = pDrvCtrl->memWidth;
break;
case EIOCGHDRLEN:
if (data == NULL)
return (EINVAL);
*(int *)data = 14;
break;
default:
error = EINVAL;
}
return (error);
}
/*******************************************************************************
*
* rtl81x9Wait - wait for the command completion
*
* This function waits for the command completion
* It is possible the chip can wedge and the 'command in progress' bit may
* never clear. Hence, we wait only a finite amount of time to avoid getting
* caught in an infinite loop. Normally this delay routine would be a macro,
* but it isn't called during normal operation so we can afford to make it a
* function.
*
* RETURNS: N/A
*/
LOCAL void rtl81x9Wait
(
RTL81X9END_DEVICE * pDrvCtrl /* device control structure */
)
{
register int ix;
for (ix = 0; ix < RTL_TIMEOUT; ix++)
{
/*if ((rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 0x10) == 0)*/
if ((rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 0x10) == 0)
break; /*vicadd*/
}
if (ix == RTL_TIMEOUT)
DRV_LOG (DRV_DEBUG_ALL, "rtl81x9Wait - rtlPci%d: command never completed!\n",
pDrvCtrl->unit, 2, 3, 4, 5, 6);
return;
}
/*******************************************************************************
*
* rtl81x9Reset - Reset the chip
*
* This routine does a soft reset on the chip.
*
* RETURNS: OK, Always.
*/
LOCAL STATUS rtl81x9Reset
(
RTL81X9END_DEVICE * pDrvCtrl /* pointer to device control structure */
)
{
/* issue the reset command */
/*DRV_LOG (DRV_DEBUG_LOAD, " rtl81x9Reset\n",0,0,0,0,0,0);*/
/*rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RESET, RTL_WIN_0);*/
rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RESET, RTL_WIN_0);
rtl81x9Wait(pDrvCtrl); /* wait for the command to complete */
/* wait for a while */
SYS_DELAY(10);/*vicadd*/
return OK;
}
/*******************************************************************************
*
* rtl81x9LowPowerMode - Enter low power mode
*
*
* RETURNS: N/A
*
* NOMANUAL
*/
void rtl81x9LowPowerMode (RTL81X9END_DEVICE* pDrvCtrl)
{
/*
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, 0xC0, RTL_WIN_0);
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CONFIG_1, 0x03, RTL_WIN_0);
*/
}
/*******************************************************************************
*
* rtl81x9NormalPowerMode - Come out of Low power mode
*
*
* RETURNS: N/A
*
* NOMANUAL
*/
/*
void rtl81x9NormalPowerMode (RTL81X9END_DEVICE* pDrvCtrl)
{
rtl81x9CsrWrite(pDrvCtrl, RTL_REGS_CONFIG_1, 0x00, RTL_WIN_0);
}
*/
/*******************************************************************************
*
* rtl81x9Stop - stop the device
*
* This routine marks the interface as down and resets the device. This
* includes disabling interrupts, stopping the transmitter and receiver.
*
* The complement of this routine is rtl81x9Start. Once a unit is
* stop in this routine, it may be re-initialized to a running state by
* rtl81x9Start.
*
* RETURNS: OK or ERROR
*/
LOCAL STATUS rtl81x9Stop
(
RTL81X9END_DEVICE * pDrvCtrl
)
{
STATUS result = OK;
DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9Stop\n",0,0,0,0,0,0);
/* Disable interrupts by clearing the interrupt mask. */
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
/* Stop the chip's Tx and Rx DMA processes. */
rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CHIP_CMD, 0x00, NONE);
/* Green! Put the chip in low-power mode. */
rtl81x9LowPowerMode (pDrvCtrl);
SYS_INT_DISCONNECT (pDrvCtrl, rtl81x9Int, (int)pDrvCtrl, &result);
if (result == ERROR)
DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9Stop - Could not disconnect interrupt!\n"
,0,0,0,0,0,0);
return result;
}
/******************************************************************************
*
* rtl81x9AddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list
* of addresses (added with the rtl81x9AddrAdd() routine) and sets the
* device's filter correctly.
*
* NOMANUAL
*/
LOCAL void rtl81x9AddrFilterSet
(
RTL81X9END_DEVICE *pDrvCtrl
)
{
ETHER_MULTI* pCurr;
rtl_ib* pIb;
u_char* pCp;
u_char c;
u_long crc;
u_long carry;
int i, j;
pIb = pDrvCtrl->ib;
RTL_ADDRF_CLEAR (pIb);
pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
while (pCurr != NULL)
{
pCp = (unsigned char *)&pCurr->addr;
crc = 0xFFFFFFFF; /* initial value */
for (i = 0; i < 6; i++)
{
c = *(pCp + i);
for (j = 0; j < 8; j++)
{
carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01);
crc <<= 1;
c >>= 1;
if (carry)
crc = (crc ^ 0x04c11db6) | carry;
}
}
/* Just want the 6 most significant bits. */
crc = crc >> 26;
/* Turn on the corresponding bit in the filter. */
RTL_ADDRF_SET (pIb, crc);
pCurr = END_MULTI_LST_NEXT(pCurr);
}
}
/*******************************************************************************
*
* rtl81x9PollReceive - 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 rtl81x9PollReceive
(
RTL81X9END_DEVICE *pDrvCtrl,
M_BLK_ID pMblk
)
{
int len, wrapSize;
char* pNewCluster;
CL_BLK_ID pClBlk;
RTL_RX_DATA *rxData;
USHORT cur_rx;
USHORT limit;
USHORT max_bytes = 0, rx_bytes = 0;
char *readPtr;
/*return OK; */ /* test only */
/* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9PollReceive\n",0,0,0,0,0,0);*/
/* Disable interrupts by clearing the interrupt mask. */
/* rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);vicadd*/
cur_rx = ((rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, NONE)
+ 16) % RTL_RXBUFLEN);
/* Enable interrupts by setting the interrupt mask. */
/* rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);vicadd*/
limit = (rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_ADDR, NONE) % RTL_RXBUFLEN);
if (limit < cur_rx)
max_bytes = (RTL_RXBUFLEN - cur_rx) + limit;
else
max_bytes = limit - cur_rx;
while ((rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) &
RTL_CMD_RX_BUF_EMPTY) == 0)
{
readPtr = (pDrvCtrl->ptrRxBufSpace + cur_rx);
rxData = (RTL_RX_DATA *) readPtr;
if ((rxData->rxPktLen >> 16) == RTL_RX_UNFINISHED)
break;
if (!(rxData->rxStatusFlags & RTL_RX_STATUS_OK))
{
if (rxData->rxStatusFlags & (RTL_RX_BAD_SYMBOL|
RTL_RX_RUNT|
RTL_RX_TOO_LONG|
RTL_RX_CRC_ERROR|
RTL_RX_BAD_ALIGN))
{
/*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);*/
/*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
RTL_CMD_RX_ENB, RTL_WIN_0);*/
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
RTL_CMD_RX_ENB, RTL_WIN_0);
rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, (ULONG) pDrvCtrl->ptrRxBufSpace, RTL_WIN_0);
rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_RX_BUF_PTR, cur_rx - 16, RTL_WIN_0);
cur_rx = 0;
}
break;
}
/* No errors; receive the packet. */
len = rxData->rxPktLen; /* get packet length */
rx_bytes += len + 4;
/*
*/
len -= RTL_CRC_SIZE;
/*
* Avoid trying to read more bytes than we know
* the chip has prepared for us.
*/
if (rx_bytes > max_bytes)
break;
/* If we cannot get a buffer to loan then bail out. */
pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
if (pNewCluster == NULL)
{
DRV_LOG (DRV_DEBUG_POLL_RX, "Cannot loan cluster!\n", 0, 0, 0, 0, 0, 0);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
{
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_POLL_RX, "Out of Cluster Blocks!\n", 0, 0, 0, 0, 0, 0);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/* Copy the data found into the new cluster, we have (+4) to get us past the */
/* data that the rtl chip places at the start of the message and we remove */
/* the CRC from the end of the message */
if ((readPtr + len) >= (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN))
{
wrapSize = (int) ((readPtr + len) - (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN));
/* Copy in first section of message as stored */
/* at the end of the ring buffer */
memcpy (pNewCluster, readPtr + 4, len - wrapSize);
/* Copy in end of message as stored */
/* at the start of the ring buffer */
memcpy (pNewCluster, pDrvCtrl->ptrRxBufSpace, wrapSize);
cur_rx = (wrapSize + RTL_CRC_SIZE + 4 + 3) & ~3;
}
else
{
memcpy (pNewCluster, readPtr + 4, len);
cur_rx = (cur_rx + len + RTL_CRC_SIZE + 4 + 3) & ~3;
}
/* Disable interrupts by clearing the interrupt mask. */
/*vicadd rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);*/
/* We then write the CAPR as the next ptr we will read minus 0x10 which */
/* give us a little leeway to ensure that there is no overflow */
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, (cur_rx - 16), RTL_WIN_0);
/*RV_LOG (DRV_DEBUG_ALL,"Capr=%X\n",(cur_rx - 16) , 0, 0, 0, 0, 0);*/
/* Enable interrupts by setting the interrupt mask. */
/* rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);vicadd*/
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pNewCluster, len, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
/* make the packet data coherent */
RTL_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
/* Call the upper layer's receive routine. */
END_RCV_RTN_C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -