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

📄 at91emacend.c

📁 VxWorks BSP for AT91RM92
💻 C
📖 第 1 页 / 共 5 页
字号:
        case EIOCGMIB2233:
        case EIOCGMIB2:     /* return MIB information */
            if (data == NULL)
                return(EINVAL);
            bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
                  sizeof(pDrvCtrl->end.mib2Tbl));
            break;

        case EIOCGFBUF:     /* return minimum First Buffer for chaining */
            if (data == NULL)
                return(EINVAL);
            *(int *)data = EMAC_MIN_FBUF;
            break;

        case EIOCGHDRLEN:
            if (data == NULL)
                return(EINVAL);
            *(int *)data = EH_SIZE;
            break;

        default:        /* unknown request */
            error = EINVAL;
        }

    return(error);
    }

/******************************************************************************
*
* at91EmacEndConfig - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode, and changing the
* multicast interface list.
*
* RETURNS: N/A.
*/

LOCAL void at91EmacEndConfig
    (
    EMAC_END_DEVICE *pDrvCtrl	/* device to be re-configured */
    )
    {
    /* Set promiscuous mode if it's asked for. */
    if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
    	{
        EMAC_REG(EMAC_CFG) |= EMAC_CFG_CAF;

    	EMAC_END_LOG (EMAC_END_DBG_IOCTL, "Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6);
    	}
    else
    	{
        EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_CAF;
    	
        EMAC_END_LOG (EMAC_END_DBG_IOCTL, "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6);
    	}

    /* Set up address filter for multicasting. */
    if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
    	{
    	at91EmacEndAddrFilterSet (pDrvCtrl);
    	}

    return;
    }

/*******************************************************************************
*
* at91EmacEndCrcGet - compute the cyclic redoundant code
*
* This routine computes the 32-bit cyclic redoundant code (CRC) for the
* 6-byte array pointed to by <pAddr>. 
*
* RETURNS: The 32-bit value representing the CRC.
*/

LOCAL UINT32 at91EmacEndCrcGet
    (
    UCHAR * pAddr
    )
    {
    UINT32 crc = INIT_REFLECTED;
    UINT32 len = 6;

    while (len--)
        {
        crc = crc32table[(crc ^ *pAddr++) & 0xFFL] ^ (crc >> 8);
        }

    return crc;
    }

/******************************************************************************
*
* at91EmacEndAddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list
* of addresses (added with the endAddrAdd() routine) and sets the
* device's filter correctly.
*
* RETURNS: N/A.
*/

LOCAL void at91EmacEndAddrFilterSet
    (
    EMAC_END_DEVICE *pDrvCtrl	/* device to be updated */
    )
    {
    ETHER_MULTI * 	pCurr;
    UINT32 		    crc;
    UINT32 		    index;
    int 		    count;
    UINT32          hashTbl[2];

    hashTbl[0] = 0;
    hashTbl[1] = 0;
    count      = 0;

    pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);

    while (pCurr != NULL)
    	{
        crc   = at91EmacEndCrcGet((UCHAR *) &pCurr->addr);
        index = EMAC_CRC_TO_FILTER_INDEX (crc);

        /* hash table is on 64 bits (6 bits indexed) */
        hashTbl[index >> 5] |= 1 << (index & 31);

        count++;
        
        EMAC_END_LOG (EMAC_END_DBG_HASH, "at91EmacEndAddrFilterSet: %02x:%02x:%02x:%02x:%02x:%02x\n",
                      pCurr->addr[0], pCurr->addr[1], pCurr->addr[2], pCurr->addr[3], pCurr->addr[4], pCurr->addr[5]);

        EMAC_END_LOG (EMAC_END_DBG_HASH, "at91EmacEndAddrFilterSet: crc = 0x%x, index = %i (%i)\n",
                      crc, index, count, 4, 5, 6);

    	pCurr = END_MULTI_LST_NEXT(pCurr);
    	}

    EMAC_REG(EMAC_HSH) = hashTbl[1];
    EMAC_REG(EMAC_HSL) = hashTbl[0];

    if (count > 0)
        {
        EMAC_REG(EMAC_CFG) |= EMAC_CFG_MTI;
        
        EMAC_END_LOG (EMAC_END_DBG_HASH, "Enable Multicast Hash (hsh = 0x%08x, hsl = 0x%08x)!\n",
                      hashTbl[1], hashTbl[0], 3, 4, 5, 6);
        }
    else
        {
        EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_MTI;
        
        EMAC_END_LOG (EMAC_END_DBG_HASH, "Disable Multicast Hash (hsh = 0x%08x, hsl = 0x%08x)!\n",
                      hashTbl[1], hashTbl[0], 3, 4, 5, 6);
        }
    }

/*******************************************************************************
*
* at91EmacEndPollRcv - routine to receive a packet in polled mode.
*
* Polled mode operation takes place without any kernel or other OS
* services available.  Use extreme care to insure that this code does not
* call any kernel services.  Polled mode is only for WDB system mode use.
* Kernel services, semaphores, tasks, etc, are not available during WDB
* system mode.
*
* The WDB agent polls the device constantly looking for new data.  Typically
* the device has a ring of RFDs to receive incoming packets.  This routine
* examines the ring for any new data and copies it to the provided mblk.
* The concern here is to keep the device supplied with empty buffers at all
* time.
*
* RETURNS: OK upon success.  EAGAIN is returned when no packet is available.
* A return of ERROR indicates a hardware fault or no support for polled mode
* at all.
*/

LOCAL STATUS at91EmacEndPollRcv
    (
    EMAC_END_DEVICE *   pDrvCtrl,	/* device to be polled */
    M_BLK_ID            pMblk		/* ptr to buffer */
    )
    {
    char *                  pPacket;
    int                     len = 0;
    int                     count;
    volatile RXBUF_HDR *    pRxHdr;

    /* check for an incoming packet */
    count = 0;

    while ((pDrvCtrl->rxHdrs[pDrvCtrl->rxIndex].adrs & RXBUF_ADD_OWNED) != RXBUF_ADD_OWNED
           && count < pDrvCtrl->rxNum)
        {
        count++;

        /* update index */
        if (pDrvCtrl->rxIndex == (pDrvCtrl->rxNum - 1))
            {
            pDrvCtrl->rxIndex = 0;
            }
        else
            {
            pDrvCtrl->rxIndex++;
            }
        }

    if (count >= pDrvCtrl->rxNum)
        {
        return(EAGAIN);
        }

    pRxHdr = (volatile RXBUF_HDR *) &pDrvCtrl->rxHdrs[pDrvCtrl->rxIndex];

    if ((pRxHdr->adrs & RXBUF_ADD_OWNED) != RXBUF_ADD_OWNED)
        {
        return(EAGAIN);
        }
    
    /* Get packet and  length from device buffer/descriptor */
    len     = pRxHdr->status & RXBUF_STAT_LEN_MASK;   /* size including FCS */
    pPacket = (char *) (pRxHdr->adrs & RXBUF_ADD_BASE_MASK);

    /* Upper layer must provide a valid buffer. */
    if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
    	{
    	return (EAGAIN);
    	}

    /* Invalidate cache */
    END_CACHE_INVALIDATE(pPacket,len);

    /* Process device packet into net buffer */
    pMblk->m_data += 2; /* ensure that IP header is word aligned */

    bcopy (pPacket, pMblk->m_data, len);
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;	/* set the packet header */
    pMblk->mBlkHdr.mLen   = len;		/* set the data len */
    pMblk->mBlkPktHdr.len = len;	    /* set the total len */

    /* give back buffer to EMAC (DMA) */
    pRxHdr->adrs &= ~RXBUF_ADD_OWNED;

    /* clear any status bits that may be set. */
	EMAC_REG(EMAC_RSR) = (EMAC_RSR_REC | EMAC_RSR_OVR | EMAC_RSR_BNA);

    at91EmacEndNumRecv++;

    return (OK);
    }

/*******************************************************************************
*
* at91EmacEndPollSend - routine to send a packet in polled mode.
*
* Polled mode operation takes place without any kernel or other OS
* services available.  Use extreme care to insure that this code does not
* call any kernel services.  Polled mode is only for WDB system mode use.
* Kernel services, semaphores, tasks, etc, are not available during WDB
* system mode.
*
* A typical implementation is to set aside a fixed buffer for polled send
* operation.  Copy the mblk data to the buffer and pass the fixed buffer
* to the device.  Performance is not a consideration for polled operations.
*
* An alternate implementation is a synchronous one.  The routine accepts
* user data but does not return until the data has actually been sent.  If an
* error occurs, the routine returns EAGAIN and the user will retry the request.
*
* If the device returns OK, then the data has been sent and the user may free
* the associated mblk.  The driver never frees the mblk in polled mode.
* The calling routine will free the mblk upon success.
*
* RETURNS: OK upon success.  EAGAIN if device is busy or no resources.
* A return of ERROR indicates a hardware fault or no support for polled mode
* at all.
*/

LOCAL STATUS at91EmacEndPollSend
    (
    EMAC_END_DEVICE* 	pDrvCtrl,	/* device to be polled */
    M_BLK_ID    pMblk	/* packet to send */
    )
    {
    int             len;
    UINT32	        stat;

    /* Check if TX is busy */
    stat = EMAC_REG(EMAC_TSR);
    
    if ((stat & EMAC_TSR_BNQ) != EMAC_TSR_BNQ)
        {
        return ((STATUS) EAGAIN);
        }

    /* Copy data from mblk */
    len = netMblkToBufCopy (pMblk, pDrvCtrl->pTxPollBuf, NULL);
    len = max (ETHERSMALL, len);

    /* Ensure data coherency */
    END_CACHE_FLUSH(pDrvCtrl->pTxPollBuf,len);
    
    /* Set the descriptor to send data */
    EMAC_REG(EMAC_TAR) = (UINT32) pDrvCtrl->pTxPollBuf;
    EMAC_REG(EMAC_TCR) = EMAC_TCR_LEN((UINT32) len);

    at91EmacEndNumSend++;

    return (OK);
    }

/*****************************************************************************
*
* at91EmacEndMCastAdd - 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 or ERROR.
*/

LOCAL STATUS at91EmacEndMCastAdd
    (
    EMAC_END_DEVICE *pDrvCtrl,		/* device pointer */
    char* pAddress	/* new address to add */
    )
    {
    int error;

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

    return (OK);
    }

/*****************************************************************************
*
* at91EmacEndMCastDel - 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 or ERROR.
*/

LOCAL STATUS at91EmacEndMCastDel
    (
    EMAC_END_DEVICE *pDrvCtrl,		/* device pointer */
    char* pAddress		/* address to be deleted */
    )
    {
    int error;

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

    return (OK);
    }

/*****************************************************************************
*
* at91EmacEndMCastGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS at91EmacEndMCastGet
    (
    EMAC_END_DEVICE *pDrvCtrl,			/* device pointer */
    MULTI_TABLE* pTable		/* address table to be filled in */
    )
    {
    return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
    }

/*******************************************************************************
*
* at91EmacEndStop - 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 at91EmacEndStop
    (
    EMAC_END_DEVICE *pDrvCtrl	/* device to be stopped */
    )
    {
    STATUS result = OK;

    END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);

    /* Disable TX/RX */
    EMAC_REG(EMAC_CTL)  &= ~(EMAC_CTL_TE | EMAC_CTL_RE);

    /* Disable interrupts */
	EMAC_REG(EMAC_IDR) = EMAC_INT_RCOM | EMAC_INT_RBNA
			| EMAC_INT_TUND | EMAC_INT_RTRY | EMAC_INT_TCOM
			| EMAC_I

⌨️ 快捷键说明

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