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

📄 if_med.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
* configuration enables the NIC onto an active network.*/LOCAL void medConfigNIC    (    int unit    )    {    struct med_softc  *es   = med_softc [unit];    NIC_DEVICE        *pNIC = es->nicAddr;    /* get Ethernet address from ROM */    medEthAddrGet (unit);    /* stop/abort all NIC operations */    pNIC->Cr  = RPAGE0 | STP | ABORT;    pNIC->Dcr = FT2 | BMS | BOS | WTS;    /* clear remote DMA byte count registers */    pNIC->Rbcr0  = 0;    pNIC->Rbcr1  = 0;    /* accept broadcast, but not runt and multicast packets */    pNIC->Rcr = AB;    /* configure for internal loopback mode */    pNIC->Tcr = MODE1;    /* initialize receive buffer pointers */    pNIC->Bnry   = BNRY;    pNIC->Pstart = PSTART;    pNIC->Pstop  = PSTOP;    /* clear the interrupt status */    pNIC->Isr = RST | RDC | CNT | OVW | TXE | RXE | PTX | PRX;    /* enable selected interrupts */    pNIC->Imr = NIC_INTERRUPTS_HANDLED;    /* select NIC page 1 registers */    pNIC->Cr  = RPAGE1 | STP | ABORT;    /* initialize the physical address, e.g. the Ethernet address */    pNIC->Par0 = es->es_enaddr [0];    pNIC->Par1 = es->es_enaddr [1];    pNIC->Par2 = es->es_enaddr [2];    pNIC->Par3 = es->es_enaddr [3];    pNIC->Par4 = es->es_enaddr [4];    pNIC->Par5 = es->es_enaddr [5];    /*     * Initialize the multicast address registers.     *    CURRENTLY NOT SUPPORTED     */    /* initialize the next packet receive buffer pointer */    pNIC->Curr = CURR;    /* start NIC */    pNIC->Cr = RPAGE0 | STA | ABORT;    /* enable packet transmission */    pNIC->Tcr = nic_NORMAL_XMIT_CTRL;    }#ifdef BSD43_DRIVER/********************************************************************************* medOutput -** Ethernet output routine.* Encapsulate a packet of type family for the local net.* Use trailer local net encapsulation if enough data in first* packet leaves a multiple of 512 bytes of data in remainder.*/LOCAL int medOutput    (    FAST struct ifnet   *ifp,    FAST struct mbuf    *m0,    struct sockaddr     *dst    )    {    return (ether_output (ifp, m0, dst, (FUNCPTR) medStartOutput,			  &med_softc [ifp->if_unit]->es_ac));    }#endif/********************************************************************************* medStartOutput - start pending output** Start output to NIC.* Queue up all pending datagrams for which transmit buffers are available.* It is very important that this routine be executed with splimp set.* If this is not done, another task could allocate the same transmit buffer.*/#ifdef BSD43_DRIVERLOCAL void medStartOutput    (    int unit    )    {    FAST struct med_softc * 	es = med_softc [unit];#elseLOCAL void medStartOutput    (    struct med_softc * 	es    )    {#endif    FAST struct mbuf	  *m;    FAST char		  *buf;    int			   len;    FAST xmitBCB_s        *pXmitBCB;    int			   s = splimp ();    FAST xmitQCB_s  * pXmitQCB = &(es->xmitQCB);    FAST XBIdx_t      headPkt  = pXmitQCB->head;    while (es->es_if.if_snd.ifq_head != NULL)        {	/* there is something to send */        if ((pXmitBCB = medXmitBfrAlloc (es)) == (xmitBCB_s *) NULL)            {            med_Stats.noXmitBfrs++;            es->es_if.if_oerrors++;	    break;			/* no transmit buffers available */	    }        buf  = pXmitBCB->pPktBfr;	/* get message to send */	IF_DEQUEUE (&es->es_if.if_snd, m); /* get head of next mbuf chain */	copy_from_mbufs (buf, m, len);	len = max (ETHERSMALL, len);        pXmitBCB->pktLen  = (u_short)len;        pXmitBCB->bPktRdy = TRUE;	/* call output hook if any */	if (etherOutputHookRtn != NULL &&	     (* etherOutputHookRtn) (&es->es_if, buf, len))            continue;        if (medXmtrLock (&(pXmitQCB->lockNIC_Xmtr)) != ERROR)            {            /*             * Start transmission of the next packet on the xmitQ             * unless the transmit interrupt handler has already             * transmitted it.             *             * Lock mechanism  pXmitQCB->lockNIC_Xmtr is unlocked by             * the transmit interrupt handler when all packets on             * the xmitQ have been transmitted.             */            if (pXmitQCB->xmitBCB [headPkt].bPktRdy)                {                if (medXmitPacket (es, pXmitQCB->xmitBCB [headPkt].pPktBfr,                                   pXmitQCB->xmitBCB [headPkt].pktLen)                    == ERROR)                    {                    logMsg ("med%d: ERROR - NIC transmitter active, should \                             be off.\n", es->es_if.if_unit, 0, 0, 0, 0, 0);                    }                }            else                medXmtrUnlock (&(pXmitQCB->lockNIC_Xmtr));            }        /* opackets statistic is incremented elsewhere after interrupt */        }    splx (s);    }/********************************************************************************* medXmitBfrAlloc - allocate a NIC transmit buffer** RETURNS: address of the NIC transmit buffer or NULL if none available*/LOCAL xmitBCB_s   *medXmitBfrAlloc    (    struct med_softc  *es    )    {    FAST xmitQCB_s *pXmitQCB = &(es->xmitQCB);    FAST xmitBCB_s *pTailXBCB;    int             oldLevel;    if (pXmitQCB->bFull)        return (xmitBCB_s *)NULL;    /* block interrupt service routine access to xmitQCB */    oldLevel = intLock();    pXmitQCB->bEmpty = FALSE;    pTailXBCB        = &(pXmitQCB->xmitBCB [pXmitQCB->tail]);    pXmitQCB->tail   = pTailXBCB->next;    if (pXmitQCB->head == pXmitQCB->tail)        pXmitQCB->bFull = TRUE;    intUnlock (oldLevel);    return (pTailXBCB);    }/********************************************************************************* medXmitPacket - NIC packet transmission** RETURNS: ERROR if NIC transmitter busy, otherwise OK*/LOCAL STATUS   medXmitPacket    (    struct med_softc *es,    char *pPacket,    u_short packetLen    )    {    NIC_DEVICE *pNIC = es->nicAddr;#if	defined (med_SAVE_XMIT_PKTS)    static char *pXmitPktSaveBfr = (char *) 0xffd10000;    /* check for possible buffer overrun */    if (((u_long) pXmitPktSaveBfr + 1600) > 0xffd20000)	pXmitPktSaveBfr = (char *) 0xffd10000;    bcopy (pPacket, pXmitPktSaveBfr, (int) packetLen);    pXmitPktSaveBfr = pXmitPktSaveBfr + packetLen;    bcopy ("$$$$$$$$$$$$$$$$", pXmitPktSaveBfr, 16);    pXmitPktSaveBfr = pXmitPktSaveBfr + 16;#endif	/* med_SAVE_XMIT_PKTS */    if ((pNIC->Cr & TXP) == nic_XMTR_BUSY)        return (ERROR);    pNIC->Tpsr  = nic_CPU_TO_NIC_ADRS (pPacket);    pNIC->Tbcr1 = (u_char) (packetLen >> 8);    pNIC->Tbcr0 = (u_char) packetLen;    pNIC->Cr    = STA | TXP | ABORT;    return (OK);    }/********************************************************************************* medStatsGet - output to stdout the med statictics** NOMANUAL*/void medStatsGet    (    int unit    )    {    struct med_softc *es = med_softc [unit];    medReadTallyCntrs (es);    printf("med Statistics:\n");    printf("   packets received            : %ld\n", es->es_if.if_ipackets);    printf("   input errors                : %ld\n", es->es_if.if_ierrors);    printf("   packets transmitted         : %ld\n", es->es_if.if_opackets);    printf("   output errors               : %ld\n", es->es_if.if_oerrors);    printf("   packets on send queue       : %d\n", es->es_if.if_snd.ifq_len);    printf("   packets dropped (not xmit)  : %d\n", es->es_if.if_snd.ifq_drops);    printf("   xmit bufs full, xmit delayed: %ld\n", med_Stats.noXmitBfrs);    printf("   NIC total interrupts        : %ld\n", med_Stats.intrCount);    printf("   NIC PRX interrupts          : %ld\n", med_Stats.PRX_intrCount);    printf("   NIC PTX interrupts          : %ld\n", med_Stats.PTX_intrCount);    printf("   NIC RXE interrupts          : %ld\n", med_Stats.RXE_intrCount);    printf("   NIC TXE interrupts          : %ld\n", med_Stats.TXE_intrCount);    printf("   NIC OVW interrupts          : %ld\n", med_Stats.OVW_intrCount);    printf("   NIC CNT interrupts          : %ld\n", med_Stats.CNT_intrCount);    printf("   carrier lost on xmit        : %ld\n", med_Stats.carrierLost);    printf("   out of window collision     : %ld\n", med_Stats.outOfWndColl);    printf("   FIFO underrun               : %ld\n", med_Stats.FIFO_UdrRun);    printf("   excess collision            : %ld\n", med_Stats.excessColl);    printf("   frame alignment             : %ld\n", med_Stats.frameAlign);    printf("   CRC mismatch                : %ld\n", med_Stats.misMatchCRC);    printf("   missed packet               : %ld\n", med_Stats.missedPkt);    }/********************************************************************************* medReadTallyCntrs - update local counters from NIC tally counters**/LOCAL void medReadTallyCntrs    (    FAST struct med_softc *es    )    {    NIC_DEVICE *pNIC = es->nicAddr;    med_Stats.frameAlign  += pNIC->FaeErr;    med_Stats.misMatchCRC += pNIC->CrcErr;    med_Stats.missedPkt   += pNIC->MspErr;    }/********************************************************************************* medMoveWrappedPacket - move a wrapped packet in the NIC receive buffer**/LOCAL void medMoveWrappedPacket    (    FAST struct med_softc  *es, /* for END_OF_RECV_BFR, NIC_RECV_BFR_ADRS */    FAST nic_RecvHdr_s *pRecvPacket,    FAST u_long pktSize    )    {    FAST int    byteCount;    FAST char  *pOvfRecvBfrMiddle;    /* copy from start of packet to end of NIC receive buffer */    byteCount = (int) ((u_long) END_OF_RECV_BFR - (u_long) pRecvPacket);    bcopy ((char *) pRecvPacket, (char *) (es->pOvfRecvBfr), byteCount);    /*     * Copy remainder of packet from the base address of the NIC     * receive buffer to the current address in the buffer at     * es->pOvfRecvBfr.     */    pOvfRecvBfrMiddle = (char *) ((u_long) (es->pOvfRecvBfr)			+ (u_long) byteCount);    byteCount = (int) pktSize - byteCount;    bcopy ((char *) NIC_RECV_BFR_ADRS (0), pOvfRecvBfrMiddle, byteCount);    }/********************************************************************************* medSetNIC_IMR - mask/unmask interrupts in the NIC Interrupt Mask Register** INTERNAL* This NIC Interrupt Mask Register (IMR) is essentially write-only.* The IMR in register page 2 cannot be accessed during normal* operation.*/LOCAL void medSetNIC_IMR    (    FAST struct med_softc *es,    FAST u_char unmaskBits,    FAST u_char maskBits    )    {    FAST int          oldLevel;    FAST NIC_DEVICE  *pNIC       = es->nicAddr;    FAST u_char       currentIMR = es->currentIMR;    oldLevel = intLock ();    /*     * This kludge is to ensure that the PRX and RXE interrupts are not     * enabled (in task medRecvIntrHandler) after an OVW interrupt.     */    if (es->bRecvBfrOvfl)        unmaskBits &= ~(nic_PKT_RECV_NO_ERRORS | nic_PKT_RECV_ERROR);    currentIMR     = (currentIMR | unmaskBits) & (~maskBits);    es->currentIMR = currentIMR;    pNIC->Imr      = currentIMR;    intUnlock (oldLevel);    }/********************************************************************************* medNIC_AwaitStop - busy-wait 2ms or until the NIC stops*/LOCAL void medNIC_AwaitStop    (    FAST NIC_DEVICE *pNIC    )    {    FAST int   ticksIn2ms;    FAST ULONG tickStartCount = tickGet ();    /*     * Wait for NIC to complete current operation.     * Determine the number of clock ticks in 2ms...     * Divide the ticks/second value returned by sysClkRateGet ()     * by 512. (Note that 512 is approximately 500. Thus, shifting     * by 9 is as if multiplying by approximately 0.002)     */    ticksIn2ms = sysClkRateGet () >> 9;    if (ticksIn2ms == 0)        ticksIn2ms = 1;    while ((pNIC->Isr & RST) != nic_STOP_MODE)        if ((tickStartCount + ticksIn2ms) < tickGet ())            break;    }/********************************************************************************* medXmitBfrDealloc - deallocate emptied transmit buffer(s)** This routine must execute at interrupt level only.*/LOCAL void medXmitBfrDealloc    (    FAST xmitQCB_s  *pXmitQCB    )    {    if (pXmitQCB->bEmpty)        {        logMsg("med: ERROR - transmit buffer deallocation failed.\n",		0,0,0,0,0,0);        return;        }    pXmitQCB->bFull = FALSE;    pXmitQCB->head  = pXmitQCB->xmitBCB [pXmitQCB->head].next;    if (pXmitQCB->head == pXmitQCB->tail)        pXmitQCB->bEmpty = TRUE;    }/********************************************************************************* medXmtrLock - lock access to the NIC transmitter** This function must only be invoked by tasks executing with splimp.* Otherwise, a race condition is possible during the LOCKED test.** RETURNS: ERROR if already locked, OK otherwise*/LOCAL STATUS medXmtrLock    (    FAST lockID_t *pLock    )    {    FAST int oldLevel;    if (*pLock == LOCKED)        return ERROR;    oldLevel = intLock ();    *pLock = LOCKED;    intUnlock (oldLevel);    return (OK);    }/********************************************************************************* medXmtrUnlock - unlock access to the NIC transmitter**/LOCAL void medXmtrUnlock    (    FAST lockID_t *pLock    )    {    *pLock = UNLOCKED;    }

⌨️ 快捷键说明

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