⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl81x9.c

📁 VxWorks系统realtek8139网卡驱动(源码).zip
💻 C
📖 第 1 页 / 共 5 页
字号:
*
* 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 (RTL_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 (RTL_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;

    DRV_LOG (RTL_DRV_DEBUG_POLL_RX, "rtl81x9PollReceive\n",0,0,0,0,0,0);

	/* Disable interrupts by clearing the interrupt mask. */
    rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);

	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);

	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;


		/*
		 * Here's a totally undocumented fact for you. When the
		 * RealTek chip is in the process of copying a packet into
		 * RAM for you, the length will be 0xfff0. If you spot a
		 * packet header with this value, you need to stop. The
		 * datasheet makes absolutely no mention of this and
		 * RealTek should be shot for this.
		 */

		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);

				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;

		/*
		 * XXX The RealTek chip includes the CRC with every
		 * received frame, and there's no way to turn this
		 * behavior off (at least, I can't find anything in
	 	 * the manual that explains how to do it) so we have
		 * to trim off the CRC manually.
		 */
		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 (RTL_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 (RTL_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. */
    	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);

		/* Enable interrupts by setting the interrupt mask. */
    	rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
    	
    	/* 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_CALL (&pDrvCtrl->end, pMblk);

		return OK;
		}

cleanRXD:
	return ERROR;


    }

/*******************************************************************************
*
* rtl81x9PollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*/

LOCAL STATUS rtl81x9PollSend
    (
    RTL81X9END_DEVICE* pDrvCtrl,
    M_BLK_ID pMblk
    )
    {
	int 		   txDesc;


    DRV_LOG (RTL_DRV_DEBUG_POLL_TX, "rtl81x9PollSend\n",0,0,0,0,0,0);

	for (txDesc=0; txDesc < RTL_NUM_TX_DESC; txDesc++) 
		{
		u_long txstatus;
    	
    	txstatus = rtl81x9CsrReadLong (pDrvCtrl, 
    				RTL_REGS_TX_STATUS0 + (txDesc*4), NONE);

		if (txstatus & RTL_TX_STATUS_OK)
			{
			/* Has the packet been sent previously */
			if ((txstatus & RTL_TX_HOST_OWNS) && (pDrvCtrl->pDescMem[txDesc] != NULL))
				{
				/* Clear the buffer that was registered to the Descriptor */
				netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]);
				pDrvCtrl->pDescMem[txDesc] = NULL;
				pDrvCtrl->freeDesc++;
				if (pDrvCtrl->freeDesc > RTL_NUM_TX_DESC)
						pDrvCtrl->freeDesc = RTL_NUM_TX_DESC;
				}
			}
		else if (txstatus & (RTL_TX_UNDERRUN | 
							RTL_TX_OUT_OF_WINDOW | 
							RTL_TX_ABORTED ))
			{
			/* Clear the buffer that was registered to the Descriptor */

			netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]);
			pDrvCtrl->pDescMem[txDesc] = NULL;
				
    		rtl81x9CsrWriteLong (pDrvCtrl, 
					RTL_REGS_TX_STATUS0 + (txDesc*4), RTL_TX_HOST_OWNS, NONE);
			}
		}

    return (OK);
    }

/*****************************************************************************
*
* rtl81x9MCastAddrAdd - 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.
*/

LOCAL STATUS rtl81x9MCastAddrAdd
    (
    RTL81X9END_DEVICE *pDrvCtrl,
    char* pAddress
    )
    {

    int error;

    if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
		pAddress)) == ENETRESET)
	    rtl81x9Config (pDrvCtrl);

    return (OK);
    }

/*****************************************************************************
*
* rtl81x9MCastAddrDel - 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.
*/

LOCAL STATUS rtl81x9MCastAddrDel
    (
    RTL81X9END_DEVICE* pDrvCtrl,
    char* pAddress
    )
    {

    int error;

    if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
	     (char *)pAddress)) == ENETRESET)
	    rtl81x9Config (pDrvCtrl);

    return (OK);
    }

/*****************************************************************************
*
* rtl81x9MCastAddrGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*/

LOCAL STATUS rtl81x9MCastAddrGet
    (
    RTL81X9END_DEVICE* pDrvCtrl,
    MULTI_TABLE* pTable
    )
    {

    int error;

    error = etherMultiGet (&pDrvCtrl->end.multiList, pTable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -