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

📄 m8260sccend.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
* motSccEndPollSend - transmit a packet in polled mode** This routine is called by a user to try and send a packet on the* device. It sends a packet directly on the network from the caller without* going through the normal processes of queuing a pacet on an output queue* and the waiting for the device to decide to transmit it.** If it detects a transmission error, the restart command is issued.** These routine should not call any kernel functions.** RETURNS: OK or EAGAIN*/LOCAL STATUS motSccEndPollSend    (    END_CTRL *  pDrvCtrl,  /* pointer to END_CTRL structure */    M_BLK_ID    pMblk      /* data to send */    )    {    int         length;    SCC_BUF *   pTxBd;    u_char *    pad;    char *      pBuf;    MOTCPMLOGMSG(("motSccEndPollSend \n", 0, 0, 0, 0, 0, 0));    if (pDrvCtrl->txStop)        return(ERROR);    /* get a free transmit frame descriptor */    pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext];    /* check if a transmit buffer descriptor is available */    if ((pTxBd->statusMode & SCC_ETHER_TX_BD_R) ||        (((pDrvCtrl->ether.txBdNext + 1) % pDrvCtrl->ether.txBdNum)         == pDrvCtrl->txBdIndexC))        {        motSccCleanTxBdQueue (pDrvCtrl);        return(EAGAIN);        }    /* fill the transmit frame descriptor */    pBuf = netClusterGet (pDrvCtrl->endObject.pNetPool, pDrvCtrl->pClPoolId);    if (pBuf == NULL)        {        return(ERROR);        }    length = netMblkToBufCopy (pMblk, (char *)pBuf, NULL);    pTxBd->dataPointer = (u_char *) pBuf;    /* padding mechanism in Rev A is buggy - do in software */    if (length < FRAME_MIN)        {        pad = pTxBd->dataPointer + length;        for (; length != FRAME_MIN; length++, pad++)            *pad = 0x88;        }    pTxBd->dataLength = length;    if (pTxBd->statusMode & SCC_ETHER_TX_BD_W)        pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |                            SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC  |                            SCC_ETHER_TX_BD_W | SCC_ETHER_TX_BD_R;    else        pTxBd->statusMode = SCC_ETHER_TX_BD_I | SCC_ETHER_TX_BD_PAD |                            SCC_ETHER_TX_BD_L | SCC_ETHER_TX_BD_TC  |                            SCC_ETHER_TX_BD_R;    /* incr BD count */    pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %                               pDrvCtrl->ether.txBdNum;    /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1);    /*     * Spin until we've sent it.     */    while (pTxBd->statusMode & SCC_ETHER_TX_BD_R)        ;    if (pTxBd->statusMode & (SCC_ETHER_TX_BD_RL | SCC_ETHER_TX_BD_UN |                             SCC_ETHER_TX_BD_CSL | SCC_ETHER_TX_BD_LC))        {        /* An error has occured, restart the transmitter */        pDrvCtrl->txStop = TRUE;        motSccTxRestart (pDrvCtrl);        }    /*      * we are allow to do this because transmit queue is empty when we     * start polling mode.     */    netClFree (pDrvCtrl->endObject.pNetPool, pBuf);    pDrvCtrl->txBdIndexC = pDrvCtrl->ether.txBdNext;    return(OK);    }/********************************************************************************* motSccEndPollReceive - receive a packet in polled mode** This routine is called by a user to try and get a packet from the* device. It returns EAGAIN if no packet is available. The caller must* supply a M_BLK_ID with enough space to contain the receiving packet. If* enough buffer is not available then EAGAIN is returned.** These routine should not call any kernel functions.** RETURNS: OK or EAGAIN*/LOCAL STATUS motSccEndPollReceive    (    END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */    M_BLK_ID   pMblk    )    {    SCC_BUF *   pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];    int         length;    int         status = EAGAIN;    MOTCPMLOGMSG(("motSccEndPollReceive \n", 0, 0, 0, 0, 0, 0));    /* if we have not received packets, leave immediatly */    if (pRxBd->statusMode & SCC_ETHER_RX_BD_E)        return(EAGAIN);    /* check packets for errors */#ifdef REVA_M8260    if (((pRxBd->statusMode & (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))         == (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))        && !(pRxBd->statusMode & (SCC_ETHER_RX_BD_CL |                                  SCC_ETHER_RX_BD_OV | SCC_ETHER_RX_BD_CR |                                  SCC_ETHER_RX_BD_SH | SCC_ETHER_RX_BD_NO |                                  SCC_ETHER_RX_BD_LG)))        {#else        if (((pRxBd->statusMode & (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))         == (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))        && !(pRxBd->statusMode & (SCC_ETHER_RX_BD_CL |                                  SCC_ETHER_RX_BD_OV | SCC_ETHER_RX_BD_SH |                                   SCC_ETHER_RX_BD_NO | SCC_ETHER_RX_BD_LG)))        {        if (pRxBd->statusMode & SCC_ETHER_RX_BD_CR) /* CRC error ? */            {            /* On Pre-revA parts, a false CRC error may occur and if */            /* so the packet length will be 1 less than the correct  */            /* value. Adjust length and mask off false error         */             pRxBd->dataLength++;            pRxBd->statusMode &=  ~SCC_ETHER_RX_BD_CR;            }#endif        length = pRxBd->dataLength;        if ((length - SIZEOF_ETHERHEADER) <= 0)            {            /* bump input error packet counter */            END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1);            goto cleanRxBd;            }        /*          * Upper layer provides the buffer.             * If buffer is not large enough, we return.         */        /* copy data */        if ((pMblk->mBlkHdr.mLen < length) ||            (!(pMblk->mBlkHdr.mFlags & M_EXT)))            {            goto cleanRxBd;            }        bcopy ((char *) pRxBd->dataPointer, (char *)pMblk->mBlkHdr.mData,               length);        pMblk->mBlkHdr.mLen    = length;        pMblk->mBlkPktHdr.len  = length;        pMblk->mBlkHdr.mFlags |= M_PKTHDR;        /* bump input packet counter */        END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_UCAST, +1);        status = OK;        }    else        {        /* bump input error packet counter */        END_ERR_ADD (&pDrvCtrl->endObject, MIB2_IN_ERRS, +1);        }    cleanRxBd:    motSccCleanRxBd (pDrvCtrl, pRxBd);  /* reset buffer descriptor as empty */    return(status);    }/********************************************************************************* motSccIntr - network interface interrupt handler** This routine gets called at interrupt level. It handles work that * requires minimal processing. Interrupt processing that is more * extensive gets handled at task level. The network task, netTask(), is * provided for this function. Routines get added to the netTask() work * queue via the netJobAdd() command.** RETURNS: N/A*/LOCAL void motSccIntr    (    END_CTRL * pDrvCtrl /* pointer to END_CTRL structure */    )    {    BOOL rxHandle = FALSE;    BOOL txbHandle = FALSE;    /* check for spurious interrupt -> initialized ? */    if (!pDrvCtrl->endObject.attached)        {        pDrvCtrl->ether.pSccReg->scce = 0xffff;        *M8260_SIPNR_L(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;        return;        }    /* handle receive events */    if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_RXF) &&        (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_RXF))        {        (void) netJobAdd ((FUNCPTR) motSccHandleInt, (int) pDrvCtrl,                           0, 0, 0, 0);         /* turn off receive interrupts for now - motCpmHandleIt turns back on */        pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_RXF;        rxHandle = TRUE;        }    /* check for output errors */    if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXE)        {        /* clean the transmit buffer descriptor queue */        /* NOTE: HBC error not supported -> always RESTART Tx here */        (void) netJobAdd ((FUNCPTR) motSccTxRestart, (int) pDrvCtrl, 0, 0, 0, 0);        pDrvCtrl->txStop = TRUE;        }    /* handle transmitter events - BD full condition -> ever happen ? */    if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_TXB) &&        (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXB))        {        txbHandle = TRUE;        }    /* check for input busy condition */    if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_BSY)        {        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_BSY;         }    /* acknowledge all other interrupts - ignore events */    pDrvCtrl->ether.pSccReg->scce = (pDrvCtrl->ether.pSccReg->scce &                                     ~(SCC_ETHER_SCCX_RXF |                                       SCC_ETHER_SCCX_TXE |                                       SCC_ETHER_SCCX_TXB |                                       SCC_ETHER_SCCX_BSY));    /*      * clean the transmit buffer descriptor queue if we have      * received a transmit interrupt and if we are not already     * cleaning this transmit queue.     */    if ((pDrvCtrl->txStop || txbHandle) && !pDrvCtrl->txCleaning)        {        motSccCleanTxBdQueue (pDrvCtrl);        if (pDrvCtrl->txBlocked)            {            pDrvCtrl->txBlocked = FALSE;            (void) netJobAdd ((FUNCPTR) muxTxRestart,                              (int)&pDrvCtrl->endObject,                              0, 0, 0, 0);            }        }    /* acknowledge interrupts */    if (rxHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_RXF;    if (pDrvCtrl->txStop)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXE;    if (txbHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXB;    *M8260_SIPNR_L(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;    }/********************************************************************************* motSccMCastFilterSet - set the group addres filter for a multicast addresse.** To add an address in the processor group address hash filter, we use* the SET GROUP ADDRESS command. This command can be executed at any * time, regadless of whether the Ethernet channel is enabled.** RETURNS : N/A **/LOCAL void motSccMCastFilterSet    (    END_CTRL * pDrvCtrl,    /* pointer to END_CTRL structure */    char *     pAddress     /* Address to delete from the table. */    )    {    MOTCPMLOGMSG(("motSccMCastFilterSet \n", 0, 0, 0, 0, 0, 0));    /* add multicast address */    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_h =    (pAddress[5] << 8) + pAddress[4];    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_m =    (pAddress[3] << 8) + pAddress[2];    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_l =    (pAddress[1] << 8) + pAddress[0];    /* issue the set group address command to the CP */    while (*M8260_CPCR(pDrvCtrl->regBase) & M8260_CPCR_FLG);    *M8260_CPCR(pDrvCtrl->regBase) = (M8260_CPCR_PAGE(pDrvCtrl->ether.sccNum - 1) |                                      M8260_CPCR_SBC(pDrvCtrl->ether.sccNum + 3)  |                                      M8260_CPCR_OP(M8260_CPCR_SET_GROUP)         |                                       M8260_CPCR_FLG);    while (*M8260_CPCR(pDrvCtrl->regBase) & M8260_CPCR_FLG);    }/********************************************************************************* motSccMCastConfig - reconfigure the interface under us.** Reconfigure the interface changing the multicast interface list.** In order to delete an address from the hash tabke, the Ethernet channel* should be disabled, the hash table registers should be cleared, and * the SET GROUP ADDRESS command must be executed for the remaining * desired addresses. This is required because the hash table may have mapped* multiple addresses to the same hash table bit.** RETURNS : N/A */LOCAL void motSccMCastConfig    (    END_CTRL *  pDrvCtrl    /* pointer to END_CTRL structure */    )    {    ETHER_MULTI *   pCurr;   

⌨️ 快捷键说明

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