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

📄 if_cpm.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        loanBuf = cacheDmaMalloc (loanNum * pDrvCtrl->ether.rxBufSize);	if (loanBuf == NULL)            pDrvCtrl->nLoanRxBd = 0;        }    else	{	/* use passed in address as memory pool - assume OK */	txBuf   = bufBase;	rxBuf   = (UINT8 *) (txBuf + (txBdNum * pDrvCtrl->ether.txBufSize));	loanBuf = (UINT8 *) (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 */    if (cpmReset (unit) == ERROR)        return (ERROR);    /* connect the interrupt handler cpmIntr() */    if (intConnect (ivec, (VOIDFUNCPTR) cpmIntr, unit) == ERROR)        return (ERROR);    /* Initialize and start controller */    cpmInit (unit);    /* mark driver as attached */    pDrvCtrl->attached = TRUE;    return (OK);    }/********************************************************************************* cpmInit - 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.** The complement of this routine is cpmReset().  Once a unit is reset by* cpmReset(), it may be re-initialized to a running state by this routine.** RETURNS: OK if successful, otherwise ERROR.*/LOCAL STATUS cpmInit    (    int		unit		/* unit number */    )    {    DRV_CTRL *	pDrvCtrl;    UINT8	enetAddr[ENET_ADDR_SIZE];    int		counter;    /* sanity check the unit number */    if (unit < 0 || unit >= MAX_UNITS)	 return (ERROR);    pDrvCtrl = & drvCtrl[unit];    /* 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 (sysCpmEnetAddrGet (unit, (UINT8 *) & 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;    sysCpmEnetIntEnable (unit);				/* unmask interrupts */    /* call the BSP to do any other initialization (e.g., connecting clocks) */    if (sysCpmEnetEnable (unit) == ERROR)	return (ERROR);    /* raise the interface flags - mark the device as up */     pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    /* enable the transmitter */    pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENT;    /* issue the restart transmitter command to the CP */    (void) sysCpmEnetCommand (unit, CPM_CR_SCC_RESTART);    /* enable the receiver */    pDrvCtrl->ether.pSccReg->gsmrl |= SCC_GSMRL_ENR;    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* cpmOutput - network interface output routine** This routine simply calls ether_output(). ether_output() resolves * the hardware addresses and calls cpmStartOutput() with the unit number* passed as an argument.** RETURNS: OK if successful, otherwise errno.*/LOCAL int cpmOutput    (    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) cpmStartOutput,	    & pDrvCtrl->idr));    }#endif/********************************************************************************* cpmStartOutput - output packet to network interface device** cpmStartOutput() 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. Under BSD 4.3, this will cause cpmOutput() 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 very rare case, the outgoing data will be * thrown out. 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 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 cpmTxRestart() routine.  After the transmitter is restarted,* cpmTxRestart() does a netJobAdd of cpmStartOutput() 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 cpmStartOutput() to continue sending* packets left in the interface output queue.  Once again, we find ourselves* executing in the context of netTask().** RETURNS: N/A*/#ifdef BSD43_DRIVERLOCAL void cpmStartOutput    (    int		unit		/* unit number */    )    {    DRV_CTRL *	pDrvCtrl = & drvCtrl[unit];#elseLOCAL void cpmStartOutput    (    DRV_CTRL * 	pDrvCtrl	/* driver control structure */    )    {#endif    MBUF *	pMbuf;		/* mbuf pointer */    int		length;    SCC_BUF *	pTxBd;    UINT8 *	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);        /* 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;#ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */            pDrvCtrl->idr.ac_if.if_opackets++;#endif            }        }    }/********************************************************************************* cpmIoctl - 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 cpmIoctl    (    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 (pIfNet, &IA_SIN (data)->sin_addr);            break;            case SIOCSIFFLAGS:	    /* set promiscuous bit according to flags */	    if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)                pDrvCtrl->ether.pSccReg->psmr |= SCC_ETHER_PSMR_PRO;            else                pDrvCtrl->ether.pSccReg->psmr &= ~SCC_ETHER_PSMR_PRO;            break;

⌨️ 快捷键说明

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