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

📄 if_mbc.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        {        pDrvCtrl->lPool[counter] = loanBuf + (counter * RX_BUF_SIZE);        pDrvCtrl->refCnt[counter] = 0;        pDrvCtrl->pRefCnt[counter] = & pDrvCtrl->refCnt[counter];        }    /* reset the chip */        mbcReset (unit);    /* publish the Interface Data Record */#ifdef BSD43_DRIVER        ether_attach (& pDrvCtrl->idr.ac_if, unit, MBC_IFNAME,                  (FUNCPTR) mbcInit, (FUNCPTR) mbcIoctl,                  (FUNCPTR) mbcOutput, (FUNCPTR) mbcReset);#else    ether_attach (                 &pDrvCtrl->idr.ac_if,                  unit,                 MBC_IFNAME,                 (FUNCPTR) mbcInit,                  (FUNCPTR) mbcIoctl,                 (FUNCPTR) ether_output,                  (FUNCPTR) mbcReset                 );    pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)mbcStartOutput;#endif    mbcInit (unit);    return (OK);    }/********************************************************************************* mbcInit - initialize the MBC network device** This routine marks the interface as down, then configures and initializes* the chip.  It sets up the transmit and receive buffer descriptor (BD)* rings, initializes registers, and enables interrupts.  Finally, it marks* the interface as up and running.  It does not touch the receive loaner* buffer stack.** This routine is called from the driver attach routine.** The complement of this routine is mbcReset().  Once a unit is reset by* mbcReset(), it may be re-initialized to a running state by this routine.** RETURNS: OK if successful, otherwise ERROR.** SEE ALSO: mbcIoctl(), mbcReset()**/LOCAL STATUS mbcInit    (    int			unit           /* unit number */    )    {    DRV_CTRL *		pDrvCtrl;    MBC_BD *		pBd;    volatile char *	pDevBase;    UINT8		enetAddr[ENET_ADDR_SIZE];    UINT16		regValue;    int			counter;        /* sanity check the unit number */        if (unit < 0 || unit >= MAX_UNITS)        return (ERROR);    pDrvCtrl = & drvCtrl[unit];    /* ensure single invocation */        if (pDrvCtrl->initialized)        return (OK);    pDevBase = pDrvCtrl->ether.pDevBase;    /* mark the device as down */    pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);    /* take the device out of reset state */    MBC_REG_WRITE (pDevBase, MBC_ECNTL, MBC_ECNTL_RES_OFF);    /* set up transmit buffer descriptors */        pDrvCtrl->ether.txBdNext = 0;    pBd = pDrvCtrl->ether.txBdBase;    for (counter = pDrvCtrl->ether.txBdNum; counter; counter--, pBd++)        pBd->statusMode = (MBC_TXBD_I | MBC_TXBD_L | MBC_TXBD_TC);    /* turn on the `wrap' bit on the last buffer descriptor */    pBd--;    pBd->statusMode |= MBC_TXBD_W;    /* set up the receive buffer descriptors */    pDrvCtrl->ether.rxBdNext = 0;    pBd = pDrvCtrl->ether.rxBdBase;    for (counter = pDrvCtrl->ether.rxBdNum; counter; counter--, pBd++)        pBd->statusMode = (MBC_RXBD_E | MBC_RXBD_I);    /* turn on the `wrap' bit on the last buffer descriptor */        pBd--;    pBd->statusMode |= MBC_RXBD_W;    /* set the interrupt vector number */    MBC_REG_WRITE (pDevBase, MBC_IVEC, pDrvCtrl->inum);    /* set BD size and other DMA parameters */    regValue = pDrvCtrl->dmaParms;    regValue |= (pDrvCtrl->ether.bdSize << MBC_EDMA_BDS_SHFT);    MBC_REG_WRITE (pDevBase, MBC_EDMA, regValue);    /*     * set the operating mode to, no internal loopback, no full duplex, and     * no hearbeat control.     */        MBC_REG_WRITE (pDevBase, MBC_ECFG, 0);    /*     * set address control to, no hash enable, no index enable, no multicast,     * no physical address rejection, and promiscuous mode, if needed.     */        regValue = 0;    if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)        regValue |= MBC_AR_PROM;        MBC_REG_WRITE (pDevBase, MBC_AR, regValue);    /* set max receive frame size */    MBC_REG_WRITE (pDevBase, MBC_EMRBLR, FRAME_MAX);            /* get ethernet address for this device */        if (sysEnetAddrGet (unit, (UINT8 *) enetAddr) == ERROR)        return (ERROR);    /* copy in correct byte sequence */        for (counter=0; counter < ENET_ADDR_SIZE; counter++)        pDrvCtrl->idr.ac_enaddr[ENET_ADDR_SIZE - counter - 1] =            enetAddr[counter];    /* install the ethernet address */        bcopy ((char *) pDrvCtrl->idr.ac_enaddr,           (char *) (pDrvCtrl->ether.pDevBase + MBC_ARTAB),           ENET_ADDR_SIZE);        /* set rest of the AR entries to broadcast address */    regValue=0xffff;    for (counter = 1; counter < MBC_ARTAB_SIZE; counter++)        {        MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8), regValue);        MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8) + 2, regValue);        MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8) + 4, regValue);        }        /* enable interrupts - clear events and set mask */    MBC_REG_WRITE (pDevBase, MBC_IEVNT, 0xffff);    MBC_REG_WRITE (pDevBase, MBC_IMASK, MBC_IMASK_RXF | MBC_IMASK_EBE);    /* set interface flags - mark device as `up' */    pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;        /* mark device as initialized */    pDrvCtrl->initialized = TRUE;    /* enable the device */    MBC_REG_UPDATE (pDevBase, MBC_ECNTL, MBC_ECNTL_ENBL);        /* start sending enqueued packets */#ifdef BSD43_DRIVER    (void) netJobAdd ((FUNCPTR) mbcStartOutput, unit, 0, 0, 0, 0); #else    (void) netJobAdd ((FUNCPTR) mbcStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* mbcOutput - network interface output routine** This routine simply calls ether_output(). ether_output() resolves * the hardware addresses and calls mbcStartOutput() with the unit number* passed as an argument.** RETURNS: OK if successful, otherwise errno.*/LOCAL int mbcOutput    (    IFNET *	pIfNet,		/* pointer to IFNET structure */    MBUF *	pMbuf,		/* mbuf chain for output */    SOCK *	pSock		/* sock ptr for destination */      )    {    DRV_CTRL * pDrvCtrl = & drvCtrl[pIfNet->if_unit];    return (ether_output (pIfNet, pMbuf, pSock, (FUNCPTR) mbcStartOutput,	    & pDrvCtrl->idr));    }#endif/********************************************************************************* mbcStartOutput - output packet to network interface device** mbcStartOutput() takes a packet from the network interface output queue,* copies the mbuf chain into an interface buffer, and sends the packet over* the interface.  etherOutputHookRtns are supported.** Collision stats are collected in this routine from previously sent BDs.* These BDs will not be examined until after the transmitter has cycled the* ring, coming upon the BD after it has been sent. Thus, collision stat* collection will be delayed a full cycle through the Tx ring.** This routine is called under several possible scenarios.  Each one will be* described below.** The first, and most common, is when a user task requests the transmission of* data. Under BSD 4.3, this results in a call to mbcOutput(), which in turn* calls ether_output(). The routine, ether_output(), will make a call to* mbcStartOutput() if our interface output queue is not full, otherwise, the* outgoing data is discarded. BSD 4.4 uses a slightly different model, in* which the generic ether_output() routine is called directly, followed by* a call to this routine.** The second scenario is when this routine, while executing runs out of free* Tx BDs, turns on transmit interrupts and exits.  When the next BD is* transmitted, an interrupt occurs and the ISR does a netJobAdd of the routine* which executes in the context of netTask() and continues sending packets* from the interface output queue.  ** The third scenario is when the device is reset, typically when the * promiscuous mode is altered; which results in a call to mbcInit().  This * resets the device, does a netJobAdd() of this routine to enable transmitting * queued packets.** RETURNS: N/A*/#ifdef BSD43_DRIVERLOCAL void mbcStartOutput    (    int		unit		/* unit number */    )    {    DRV_CTRL *		pDrvCtrl = & drvCtrl[unit];#elseLOCAL void mbcStartOutput    (    DRV_CTRL * 	pDrvCtrl 	/* driver control structure */    )    {    int unit = pDrvCtrl->idr.ac_if.if_unit;#endif    volatile char *	pDevBase = pDrvCtrl->ether.pDevBase;    MBUF *		pMbuf;		/* mbuf pointer */    int			length;    MBC_BD *		pTxBd;    UINT8 *		pad;    UINT8		txBdMax = pDrvCtrl->ether.txBdNum - 2;    if (txBdMax == 0)        txBdMax++;    /*     * Loop until:     *     a) there are no more packets ready to send     *     b) we have insufficient resources left to send another one     *     c) txBdMax packets have been sent, so that the     *        transmitter on the rev 0.1 chip is not choked.     */    while (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)        {	pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext];        	/* check if a transmit buffer descriptor is available */                if ((pTxBd->statusMode & MBC_TXBD_R) || (txBdMax == 0))	    {	    /* if no BD available, enable interrupt to see when one is free */            wdStart (pDrvCtrl->wdId, WD_TIMEOUT, (FUNCPTR) mbcDeviceRestart,                     unit);            MBC_INTR_ENABLE (pDevBase, MBC_IEVNT_TXF);	    break;	    }        IF_DEQUEUE (& pDrvCtrl->idr.ac_if.if_snd, pMbuf);         copy_from_mbufs (pTxBd->dataPointer, pMbuf, length);        /* initial hardware version does not support padding */        if (length < FRAME_MIN)            {            pad = pTxBd->dataPointer + length;            for (; length != FRAME_MIN; length++, pad++)                *pad = 0x88;            }        /* call hook if one is connected */        if ((etherOutputHookRtn == NULL) || ((* etherOutputHookRtn)	    (& pDrvCtrl->idr.ac_if, pTxBd->dataPointer, length) == 0))            {	    /* add in collision stats from previously sent BDs */            pDrvCtrl->idr.ac_if.if_collisions += ((pTxBd->statusMode &                                                   MBC_TXBD_RC) >>                                                  MBC_TXBD_RC_SHFT);            /* add in transmission failures */                        if (pTxBd->statusMode & MBC_TXBD_ERRS)                {                pDrvCtrl->idr.ac_if.if_oerrors++;                pDrvCtrl->idr.ac_if.if_opackets--;                }	    /* since hook did not grab the frame, send packet */            pTxBd->dataLength = length;            pTxBd->statusMode &= ~(MBC_TXBD_ERRS|MBC_TXBD_RC);            pTxBd->statusMode |= MBC_TXBD_R;            /* incr BD count */	    pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %				        pDrvCtrl->ether.txBdNum;#ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */            pDrvCtrl->idr.ac_if.if_opackets++;#endif            }        txBdMax --;        }    }/********************************************************************************* mbcIoctl - network interface control routine** This routine implements the network interface control functions.* It handles SIOCSIFADDR and SIOCSIFFLAGS commands.** RETURNS: OK if successful, otherwise EINVAL.*/LOCAL int mbcIoctl    (    IFNET *	pIfNet,		/* pointer to IFNET structure */    int		cmd,		/* command to process */    caddr_t	data		/* pointer to data */     )    {    DRV_CTRL *	pDrvCtrl = & drvCtrl[pIfNet->if_unit];    int         error   = 0;            /* error value */    int         s       = splimp ();    /* sem not taken in calling routines */    BOOL	promiscReq;		/* requested promisc state */    BOOL	promiscCur;     	/* current promisc state */    switch (cmd)        {        case SIOCSIFADDR:       /* set interface address */            ((struct arpcom *)pIfNet)->ac_ipaddr = IA_SIN (data)->sin_addr;            arpwhohas (pIfNet, &IA_SIN (data)->sin_addr);            break;            case SIOCSIFFLAGS:            /* process request, if promisc mode needs change */            promiscReq = ((pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC) ?                          TRUE : FALSE);            promiscCur = ((MBC_REG_READ (pDrvCtrl->ether.pDevBase, MBC_AR) &                           MBC_AR_PROM) ? TRUE : FALSE);            if ((promiscReq && (!promiscCur)) || ((!promiscReq) && promiscCur))                {                mbcDeviceRestart (pIfNet->if_unit);                }            break;        default:            error = EINVAL;        }    splx (s);    return (error);    }/********************************************************************************* mbcReset - network interface reset routine** This routine marks the interface as down and resets the device.  This* includes disabling interrupts, stopping the transmitter and receiver.** The complement of this rotuine is mbcInit().  Once a unit is reset by this* routine, it can be re-initialized to a  running state by mbcInit().** RETURNS: N/A*/LOCAL void mbcReset    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl;    int counter = 0xffff;    if (unit < 0 || unit >= MAX_UNITS)	/* sanity check the unit number */        return;		      pDrvCtrl = & drvCtrl[unit];    /* Disable interrupts */        MBC_REG_WRITE (pDrvCtrl->ether.pDevBase, MBC_IMASK, 0x0);    /* clear pending `graceful stop complete' event, and start one */

⌨️ 快捷键说明

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