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

📄 if_qu.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    pDrvCtrl->ether.pSccReg = (SCC_REG *) ((UINT32) M360_CPM_GSMR_L1(quAddr) +                                           (scc * 0x20));    pDrvCtrl->ether.intMask = CPIC_CIXR_SCC4 << (3 - scc);        /* set up Rx and Tx buffers */    if (bufBase == NONE)	{        /* allocate memory pools */	txBuf = cacheDmaMalloc (txBdNum * pDrvCtrl->ether.txBufSize);        if (txBuf == NULL)	    return (ERROR);	rxBuf = cacheDmaMalloc (rxBdNum * pDrvCtrl->ether.rxBufSize);        if (rxBuf == NULL)	    {	    free (txBuf);	    return (ERROR);	    }        loanBuf = cacheDmaMalloc (loanNum * pDrvCtrl->ether.rxBufSize);	if (loanBuf == NULL)            pDrvCtrl->nLoanRxBd = 0;        }    else	{	/* use passed in address as memory pool - assume OK */	txBuf   = (u_char *) bufBase;	rxBuf   = (u_char *) (txBuf + (txBdNum * pDrvCtrl->ether.txBufSize));	loanBuf = (u_char *) (rxBuf + (rxBdNum * pDrvCtrl->ether.rxBufSize));	}    /* assign buffer addresses */    for (counter = 0; counter < txBdNum; counter++)        pDrvCtrl->ether.txBdBase[counter].dataPointer = (txBuf + (counter *	    pDrvCtrl->ether.txBufSize));    for (counter = 0; counter < rxBdNum; counter++)        pDrvCtrl->ether.rxBdBase[counter].dataPointer = (rxBuf + (counter *	    pDrvCtrl->ether.rxBufSize));    for (counter = 0; counter < pDrvCtrl->nLoanRxBd; counter++)        {        pDrvCtrl->lPool[counter] = (loanBuf + (counter *				    pDrvCtrl->ether.rxBufSize));        pDrvCtrl->refCnt[counter] = 0;	pDrvCtrl->pRefCnt[counter] = & pDrvCtrl->refCnt[counter];        }    /* reset the chip */    quReset (unit);    /* connect the interrupt handler quIntr() */    if (intConnect (INUM_TO_IVEC (ivec), (VOIDFUNCPTR) quIntr, unit) == ERROR)        return (ERROR);    quInit (unit);    /* mark driver as attached */    pDrvCtrl->attached = TRUE;    return (OK);    }/********************************************************************************* quInit - network interface initialization routine** 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 at boot time.** The complement of this rotuine is quReset().  Once a unit is reset by* quReset(), it may be re-initialized to a running state by this routine.** RETURNS: OK if successful, otherwise ERROR.*/LOCAL STATUS quInit    (    int		unit		/* unit number */    )    {    DRV_CTRL *	pDrvCtrl;    u_char	enetAddr[ENET_ADDR_SIZE];    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);    /* mark the device as down */     pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);    /* initialize flag(s) */    pDrvCtrl->txStop = FALSE;    /* set up transmit buffer descriptors */    pDrvCtrl->ether.pScc->param.tbase = (UINT16)	((UINT32) pDrvCtrl->ether.txBdBase & 0xfff);    pDrvCtrl->ether.pScc->param.tbptr = (UINT16)	((UINT32) pDrvCtrl->ether.txBdBase & 0xfff);    pDrvCtrl->ether.txBdNext  = 0;    /* initialize each transmit buffer descriptor */         for (counter = 0; counter < pDrvCtrl->ether.txBdNum; counter++)        pDrvCtrl->ether.txBdBase[counter].statusMode = SCC_ETHER_TX_BD_I |                                                       SCC_ETHER_TX_BD_PAD |                                                       SCC_ETHER_TX_BD_L |                                                       SCC_ETHER_TX_BD_TC;    /* set the last BD to wrap to the first */    pDrvCtrl->ether.txBdBase[(counter - 1)].statusMode |= SCC_ETHER_TX_BD_W;    /* set up receive buffer descriptors */    pDrvCtrl->ether.pScc->param.rbase = (UINT16)	((UINT32) pDrvCtrl->ether.rxBdBase & 0xfff);    pDrvCtrl->ether.pScc->param.rbptr = (UINT16)	((UINT32) pDrvCtrl->ether.rxBdBase & 0xfff);    pDrvCtrl->ether.rxBdNext  = 0;    /* initialize each receive buffer descriptor */    for (counter = 0; counter < pDrvCtrl->ether.rxBdNum; counter++)        pDrvCtrl->ether.rxBdBase[counter].statusMode = SCC_ETHER_RX_BD_I |        					       SCC_ETHER_RX_BD_E;    /* set the last BD to wrap to the first */    pDrvCtrl->ether.rxBdBase[(counter - 1)].statusMode |= SCC_ETHER_RX_BD_W;    /* set SCC attributes to Ethernet mode */     pDrvCtrl->ether.pSccReg->gsmrl    = SCC_GSMRL_ETHERNET | SCC_GSMRL_TPP_10 |                                        SCC_GSMRL_TPL_48   | SCC_GSMRL_TCI;    pDrvCtrl->ether.pSccReg->gsmrh    = 0x0;    pDrvCtrl->ether.pSccReg->psmr     = SCC_ETHER_PSMR_CRC |					SCC_ETHER_PSMR_NIB_22;     if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)        pDrvCtrl->ether.pSccReg->psmr |= SCC_ETHER_PSMR_PRO;     pDrvCtrl->ether.pSccReg->dsr      = 0xd555;    pDrvCtrl->ether.pScc->param.rfcr  = 0x18;      /* supervisor data access */    pDrvCtrl->ether.pScc->param.tfcr  = 0x18;      /* supervisor data access */    pDrvCtrl->ether.pScc->param.mrblr = FRAME_MAX_AL;  /* max rx buffer size */    /* initialize parameter the SCC RAM */     ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->c_pres	= 0xffffffff;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->c_mask	= 0xdebb20e3;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->crcec	= 0x00000000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->alec	= 0x00000000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->disfc	= 0x00000000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->pads	= 0x8888;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->ret_lim	= 0x000f;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->mflr	= FRAME_MAX;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->minflr	= FRAME_MIN;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->maxd1	= FRAME_MAX;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->maxd2	= FRAME_MAX;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr1	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr2	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr3	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->gaddr4	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->p_per	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->iaddr1	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->iaddr2	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->iaddr3	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->iaddr4	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_h	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_m	= 0x0000;    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->taddr_l	= 0x0000;    /* set the hardware Ethernet address of the board */    if (sys360EnetAddrGet (unit, (u_char *) & enetAddr) == ERROR)	return (ERROR);    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->paddr1_h =        (enetAddr[5] << 8) + enetAddr[4];    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->paddr1_m =        (enetAddr[3] << 8) + enetAddr[2];    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->paddr1_l =        (enetAddr[1] << 8) + enetAddr[0];    bcopy ((char *) enetAddr, (char *) pDrvCtrl->idr.ac_enaddr, ENET_ADDR_SIZE);    /* enable Ethernet interrupts */    pDrvCtrl->ether.pSccReg->scce = 0xffff;		/* clr events */    pDrvCtrl->ether.pSccReg->sccm = SCC_ETHER_SCCX_RXF | SCC_ETHER_SCCX_TXE;    *M360_CPM_CIMR(pDrvCtrl->regBase) |= pDrvCtrl->ether.intMask;    /* call the BSP to do any other initialization (e.g., connecting clocks) */    if (sys360EnetEnable (unit, pDrvCtrl->regBase) == ERROR)	return (ERROR);    /* raise the interface flags - mark the device as up */     pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    /* mark driver as initialized */    pDrvCtrl->initialized = TRUE;    /* enable the transmitter */    pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENT;    /* issue the restart transmitter command to the CP */    while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);    *M360_CPM_CR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) |                                      CPM_CR_SCC_RESTART | CPM_CR_FLG;    while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);    /* enable the receiver */    pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENR;    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* quOutput - network interface output routine** This routine simply calls ether_output(). ether_output() resolves * the hardware addresses and calls quStartOutput() with the unit number* passed as an argument.** RETURNS: OK if successful, otherwise errno.*/LOCAL int quOutput    (    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) quStartOutput,	    & pDrvCtrl->idr));    }/********************************************************************************* quStartOutput - output packet to network interface device** quStartOutput() 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 from several possible threads.  Each one will be* described below.** The first, and most common thread, is when a user task requests the* transmission of data. This will cause quOutput() to be called, which calls* ether_output(), which usually calls this routine. 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 (very rare case).** The second thread is when a transmitter error occurs that causes a* TXE event interrupt.  This happens for the following errors: transmitter* underrun, retry limit reached, late collision, and heartbeat error.* The ISR sets the txStop flag to stop the transmitter until the errors are* serviced. These events require a RESTART command of the transmitter, which* occurs in the quTxRestart() routine.  After the transmitter is restarted,* quTxRestart() does a netJobAdd of quStartOutput() to send any packets* left in the interface output queue.  Thus, the second thread executes* in the context of netTask().** The third, and most unlikely, thread occurs when this routine is executing* and it runs out of free Tx BDs.  In this case, this routine turns on* transmit interrupt and exits.  When the next BD is actually sent, an interrupt* occurs.  The ISR does a netJobAdd of quStartOutput() to continue sending* packets left in the interface output queue.  Once again, we find ourselves* executing in the context of netTask().** RETURNS: N/A*/LOCAL void quStartOutput    (    int		unit		/* unit number */    )    {    DRV_CTRL *	pDrvCtrl = & drvCtrl[unit];#else /* BSD43_DRIVER */LOCAL void quStartOutput    (    DRV_CTRL *	pDrvCtrl		/* unit number */    )    {#endif /* BSD43_DRIVER */    MBUF *	pMbuf;		/* mbuf pointer */    int		length;    SCC_BUF *	pTxBd;    u_char *	pad;    /*     * Loop until:     *     a) there are no more packets ready to send     *     b) we have insufficient resources left to send another one     *     c) a fatal transmitter error occurred, thus txStop was set     */    while (!pDrvCtrl->txStop && (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 & SCC_ETHER_TX_BD_R)	    {	    /* if no BD available, enable interrupt to see when one is free */            pDrvCtrl->ether.pSccReg->scce  = SCC_ETHER_SCCX_TXB;            pDrvCtrl->ether.pSccReg->sccm |= SCC_ETHER_SCCX_TXB;	    break;	    }        IF_DEQUEUE (& pDrvCtrl->idr.ac_if.if_snd, pMbuf); /* dequeue a packet */        copy_from_mbufs (pTxBd->dataPointer,pMbuf,length);        /* QUICC 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;            }        /* 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 &					          SCC_ETHER_TX_BD_RC) >> 2);	    /* if hook did not grab the frame, send packet */            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;            }        }    }/********************************************************************************* quIoctl - 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 quIoctl    (    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 functions */    switch (cmd)        {        case SIOCSIFADDR:       /* set interface address */            ((struct arpcom *)pIfNet)->ac_ipaddr = IA_SIN (data)->sin_addr;            arpwhohas ((struct arpcom *)pIfNet, &IA_SIN (data)->sin_addr);            break;            case SIOCSIFFLAGS:

⌨️ 快捷键说明

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