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

📄 templatenetif.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
* templateOutput - interface output routine.** This is the entry point for packets arriving from protocols above.  This* routine merely calls our specific output routines that eventually lead* to a transmit to the network.** RETURNS: 0 or appropriate errno (see ether_output)** SEE ALSO:* ether_output*/LOCAL int templateOutput    (    IDR *    pIDR,    MBUF *     pMbuf,    SOCK * pDestAddr    )    {    return (ether_output (&pIDR->ac_if, pMbuf, pDestAddr,            (FUNCPTR) templateTxStart, pIDR));    }/********************************************************************************* templateTxStart - start output on the chip** Looks for any action on the queue, and begins output if there is anything* there.  This routine is called from several possible threads.  Each will be* described below.** The first, and most common thread, is when a user task requests the* transmission of data.  This will cause templateOutput() to be called,* which will cause ether_output() to be called, which will cause this routine* to be called (usually).  This routine will not be called if ether_output()* finds that our interface output queue is full.  In this case, the outgoing* data will be thrown out.** The second, and most obscure thread, is when the reception of certain* packets causes an immediate (attempted) response.  For example, ICMP echo* packets (ping), and ICMP "no listener on that port" notifications.  All* functions in this driver that handle the reception side are executed in the* context of netTask().  Always.  So, in the case being discussed, netTask() * will receive these certain packets, cause IP to be stimulated, and cause the* generation of a response to be sent.  We then find ourselves following the* thread explained in the second example, with the important distinction that* the context is that of netTask().** The third thread occurs when this routine runs out of TFDs and returns.  If* this occurs when our output queue is not empty, this routine would typically* not get called again until new output was requested.  Even worse, if the* output queue was also full, this routine would never get called again and* we would have a lock state.  It DOES happen.  To guard against this, the* transmit clean-up handler detects the out-of-TFDs state and calls this* function.  The clean-up handler also runs from netTask.** Note that this function is ALWAYS called between an splnet() and an splx().* This is true because netTask(), and ether_output() take care of* this when calling this function.  Therefore, no calls to these spl functions* are needed anywhere in this output thread.** RETURNS: N/A.*/LOCAL void templateTxStart    (    int unit    )    {    MBUF * pMbuf;    int length;    TFD * pTfd = NULL;    DRV_CTRL * pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    /*     * Loop until there are no more packets ready to send or we     * have insufficient resources left to send another one.     */    while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)        {	/* TODO - get a free Tx packet buffer */        if (pTfd == NULL)            break;                              /* out of TFD's */        IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);  /* dequeue a packet */        copy_from_mbufs (pTfd->pEnetHdr, pMbuf, length);        length = max (ETHERSMALL, length);        length = min (0x3fff, length);        if ((etherOutputHookRtn != NULL) &&            (* etherOutputHookRtn)            (&pDrvCtrl->idr, pTfd->pEnetHdr, length))	    {	    /* TODO - release the TFD */            continue;	    }	/* TODO - update TFD data fields: length, etc */        pTfd->count = length;	templateTfdSend (pDrvCtrl, pTfd);	/* txmit the TFD */        }    }/********************************************************************************* templateInt - entry point for handling interrupts** The interrupting events are acknowledged to the device, so that the device* will deassert its interrupt signal.  The amount of work done here is kept* to a minimum; the bulk of the work is defered to the netTask.  Several flags* are used here to synchronize with task level code and eliminate races.** RETURNS: N/A.*/void templateInt    (    int unit    )    {    UINT16  devStatus;    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    /* TODO - read device status */    TEMPLATE_NETIF_READ (pDrvCtrl, pCsr, devStatus);    /* Quick exit if device did not generate interrupt */    if (devStatus == 0)	return;    /* Acknowledge interrupt to reset it, either here or at end of routine. */    TEMPLATE_INT_ACK (pDrvCtrl);    /* Handle transmitter interrupt */    if (devStatus & TEMPLATE_CSR_TX_PEND)        {	/* TODO - reclaim tx buffers */        if (1) /* TODO - if tx queue is not empty */            templateTfdStart (pDrvCtrl);         else            pDrvCtrl->txIdle = TRUE;                    /* transmitter idle */        }    /* Handle receiver interrupt */    if (devStatus & TEMPLATE_CSR_RX_PEND)	{	if (!(pDrvCtrl->rcvHandling))            {            pDrvCtrl->rcvHandling = TRUE;            netJobAdd ((FUNCPTR) templateHandleRecv, (int) pDrvCtrl,0, 0, 0, 0);	    }        }    }/********************************************************************************* templateHandleRecv - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void templateHandleRecv    (    DRV_CTRL *pDrvCtrl    )    {    RFD *pRfd;    do        {        pDrvCtrl->rcvHandling = TRUE;	/* interlock with templateInt() */        while ((pRfd = templateRfdGet (pDrvCtrl)) != NULL)	    {            if (templateReceive (pDrvCtrl, pRfd) == OK)                templateRfdReturn (pDrvCtrl, pRfd);	    }        pDrvCtrl->rcvHandling = FALSE;	/* interlock with templateInt() */	templateRxStart (pDrvCtrl);	/* restart Rcvr */        }    while (templateRfdReady (pDrvCtrl));	/* make sure rx q still empty */    }/********************************************************************************* templateReceive - pass a received frame to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol.  The return value indicates if buffer loaning was used to hold* the data.  A return value of OK means that loaning was not done, and it* is therefore 'ok' to return the RFD to the Rx queue.  A return value of ERROR* means that buffer loaning was employed, and so the RFD is still in use and* should not be returned to the Rx queue.  In this latter case, the RFD will* eventually be returned by the protocol, via a call to our templateLoanFree().** RETURNS: OK if RFD was not loaned, ERROR if it was loaned.*/LOCAL STATUS templateReceive    (    DRV_CTRL *pDrvCtrl,    RFD *pRfd    )    {    ETH_HDR     *pEh;    u_char      *pData;    int         len;    UINT16      etherType;    MBUF        *m = NULL;    BOOL        rfdLoaned = FALSE;    if  (0)	/* TODO - check RFD for errors */        {        ++pDrvCtrl->idr.ac_if.if_ierrors;	/* bump error counter */        templateRfdReturn (pDrvCtrl, pRfd);	/* free the RFD */        return (ERROR);        }    /* Bump input packet counter. */    ++pDrvCtrl->idr.ac_if.if_ipackets;    len = pRfd->actualCnt;		/* get frame length */    pEh = pRfd->pEnetHdr;	/* get ptr to ethernet header */    /* Service input hook */    if (etherInputHookRtn != NULL)        {        if ((* etherInputHookRtn) (&pDrvCtrl->idr, (char *)pEh, len))            {            templateRfdReturn (pDrvCtrl, pRfd); /* free the RFD */            return (OK);            }        }    len -= EH_SIZE;    pData = (u_char *) pRfd->enetData;    etherType = ntohs (pEh->ether_type);    /*     * we can loan out receive frames from receive queue if:     *     * 1) the threshold of loanable frames has not been exceeded     * 2) size of the input ethernet frame is large enough to be used with     *    clustering.     */    if ((pDrvCtrl->nLoanRfds > 0) && (USE_CLUSTER (len)) &&        ((m = build_cluster (pData, len, &pDrvCtrl->idr, MC_EI, &pRfd->refCnt,                 templateLoanFree, (int) pDrvCtrl, (int) pRfd, NULL)) != NULL))        {        pDrvCtrl->nLoanRfds--;		/* one less to loan */        rfdLoaned = TRUE;               /* we loaned a frame */        }    else	{        m = copy_to_mbufs (pData, len, 0, &pDrvCtrl->idr);	}    if (m != NULL)        do_protocol_with_type (etherType, m, &pDrvCtrl->idr, len);    return ((rfdLoaned) ? ERROR : OK);    }/********************************************************************************* templateLoanFree - return a loaned receive frame descriptor** This routine is called by the protocol code when it has completed use of* an RFD that we loaned to it.** RETURNS: N/A.*/LOCAL void templateLoanFree    (    DRV_CTRL *pDrvCtrl,    RFD *pRfd    )    {    templateRfdReturn (pDrvCtrl, pRfd);    pDrvCtrl->nLoanRfds ++;    }/********************************************************************************* templateDeviceStart - reset and start the device** This routine assumes interrupts from the device have been disabled, and* that the driver control structure has been initialized.** RETURNS: OK upon success, or ERROR for a hardware failure.*/LOCAL STATUS templateDeviceStart    (    int unit                              /* physical unit number */    )    {    DRV_CTRL *pDrvCtrl;    /* Get pointers */    pDrvCtrl = & drvCtrl [unit];    /* Issue the reset operation to the device */    TEMPLATE_NETIF_WRITE(pDrvCtrl, pCsr, TEMPLATE_CMD_RESET);    /* TODO - initialize the device */    /* TODO - generate error message if needed */    templateRxStart (pDrvCtrl);    return (OK);    }/********************************************************************************* templateTfdSend - place a transmit frame on the transmit queue** The TFD has been filled in with the network pertinent data.  This* routine will enqueue the TFD for transmission.** RETURNS: N/A.*/LOCAL void templateTfdSend    (    DRV_CTRL *pDrvCtrl,    TFD *pTfd    )    {    int unit;    unit = pDrvCtrl->idr.ac_if.if_unit;    /* TODO - setup the TFD data fields */    pTfd->status    = 0;                    /* fill in TFD fields */    pTfd->reserved  = 0;                    /* must be zero */    TEMPLATE_INT_DISABLE (pDrvCtrl);    /* TODO - queue the TFD */    if (pDrvCtrl->txIdle)               /* transmitter idle */        templateTfdStart (pDrvCtrl);	/* flush txQueue */    TEMPLATE_INT_ENABLE (pDrvCtrl);    }/********************************************************************************* templateTfdStart - start/restart the xmit list** This routine is the device level xmit routine.  The packet is given to the* device for transmission.** RETURNS: N/A.*/LOCAL void templateTfdStart    (    DRV_CTRL *pDrvCtrl		/* device pointer */    )    {    /* TODO - setup tx queues */    pDrvCtrl->txIdle = FALSE;                   /* transmitter busy */    /* TODO - send start command */    TEMPLATE_NETIF_WRITE (pDrvCtrl, pCsr, TEMPLATE_CMD_TX_START);    }/********************************************************************************* templateRxStart - start up the Receive Unit** Starts up the Receive Unit.  Assumes that the receive structures are set up.** RETURNS: N/A.*/LOCAL void templateRxStart    (    DRV_CTRL *pDrvCtrl    )    {    /* TODO - send start command */    TEMPLATE_NETIF_WRITE(pDrvCtrl, pCsr, TEMPLATE_CMD_RX_START);    }/********************************************************************************* templateRfdReturn - return a RFD to the receive queue for use by the device** This routine is used by the protocol layer to return a loaned receive buffer* back to the driver.** RETURNS: N/A.*/LOCAL void templateRfdReturn    (    DRV_CTRL* pDrvCtrl,		/* device pointer */    RFD* pRfd			/* buffer being returned */    )    {    int unit;    unit = pDrvCtrl->idr.ac_if.if_unit;    /* TODO - update RFD data */    pRfd->status    = 0;                    /* clear status */    pRfd->actualCnt  = 0;                   /* clear actual count */    pRfd->bufSize   = ETHERMTU + EH_SIZE;   /* fill in size */    pRfd->refCnt    = 0;                    /* initialize ref cnt */    /* TODO - link RFD back into queue */    }/********************************************************************************* templateRfdGet - get a received frame from the receive queue** This routine returns a received frame descriptor (incoming packet) to* the caller.  If no RFD is available, the NULL pointer is returned.** RETURNS:* A pointer to a valid RFD, or NULL if none available*/LOCAL RFD *templateRfdGet    (    DRV_CTRL *pDrvCtrl		/* device pointer */    )    {    RFD *pRfd = NULL;    if (templateRfdReady (pDrvCtrl))	{        /* TODO - get RFD from device queue */	}    return (pRfd);    }/********************************************************************************* templateRfdReady - determine if a RFD is ready for processing** This routine is used to determine if a received frame descriptor (incoming* packet) is ready for processing.** RETURNS:* TRUE if complete received frame is available, FALSE otherwise.*/LOCAL BOOL templateRfdReady    (    DRV_CTRL *pDrvCtrl    )    {    UCHAR devStatus;    TEMPLATE_NETIF_READ(pDrvCtrl, pCsr, devStatus);    if (devStatus & TEMPLATE_CSR_RFD_READY)	return TRUE;    return FALSE;    }

⌨️ 快捷键说明

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