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

📄 if_bp.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef	UNIX    int unit = minor (dev);#endif	/* UNIX */#if defined (BSD43_DRIVER) || defined (UNIX)    FAST BP_SOFTC *bs = BP_SOFTC_P [unit];#endif    FAST struct mbuf *m;    while (bs->bs_if.if_snd.ifq_head)               /* while queue not empty */        {        IF_DEQUEUE(&bs->bs_if.if_snd, m);           /* get next from queue */        if (bpPut (bs, m) == ERROR)                 /* if couldn't send */            {#if defined (BSD43_DRIVER) || defined (UNIX)                 /* vxWorks BSD 4.4 ether_output() doesn't bump statistic. */            bs->bs_if.if_opackets--;                /* it wasn't sent! */#endif            bs->bs_if.if_oerrors++;                 /* it was an error */            m_freem (m);                            /* free the mbufs */            }#if !defined (BSD43_DRIVER) && !defined (UNIX)        else            /* bump statistic for BSD 4.4 vxWorks driver. */            bs->bs_if.if_opackets++;   #endif        }    }#if defined (BSD43_DRIVER) || defined (UNIX)/********************************************************************************* bpOutput - net 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.** RETURNS: 0 if successful, errno otherwise (as per network requirements)*/LOCAL int bpOutput    (    struct ifnet *ifp,    struct mbuf *m0,    struct sockaddr *dst    )    {#ifdef	UNIX    return (ether_output (ifp, m0, dst, bpStart,	    &(BP_SOFTC_P [ifp->if_unit])->bs_ac));#else	/* UNIX */    return (ether_output (ifp, m0, dst, (FUNCPTR)bpStart,	    &BP_SOFTC_P [ifp->if_unit]->bs_ac));#endif	/* UNIX */    }#endif/********************************************************************************* bpPut - copy from mbuf chain to shared memory buffer** RETURNS: OK or ERROR if no room left in free ring*/LOCAL STATUS bpPut    (    FAST BP_SOFTC       *bs,    FAST struct mbuf    *m    )    {    FAST BUF_NODE 	*pBufNode;    u_char 		*bufStart;    int			len;    if ((pBufNode = (BUF_NODE *) ringget ((RING *) bs->bs_pFreeRing)) == NULL)	return (ERROR);    pBufNode = ItoKval (pBufNode, BUF_NODE *, bs->bs_pAnchor);    bufStart = ItoKval (pBufNode->b_addr, u_char *, bs->bs_pAnchor);#ifdef	UNIX    len = copy_from_mbufs (bufStart, m, len);#else	/* UNIX */    copy_from_mbufs (bufStart, m, len);#endif	/* UNIX */    len = max (MINPKTSIZE, len);    pBufNode->b_len = BP_HTONS (len);#ifndef	UNIX    /* call output hook if any */    if ((etherOutputHookRtn != NULL) &&	(* etherOutputHookRtn) (&bs->bs_if, bufStart, pBufNode->b_len))	return (OK);	/* output hook has already processed packet */#endif	/* UNIX */    /* send to specified processor:     * proc number is in last byte of Ethernet address     */    bpXmit (bs, pBufNode, (int) ((struct ether_header *)#ifdef	UNIX	       (bufStart))->ether_dhost.ether_addr_octet[5], bs->bs_procNum);#else	/* UNIX */	       (bufStart))->ether_dhost[5], bs->bs_procNum);#endif	/* UNIX */    return (OK);    }/********************************************************************************* bpXmit - transmit buffer*/LOCAL void bpXmit    (    FAST BP_SOFTC *bs,    BUF_NODE *pBufNode,    int destProcNum,    /* destination CPU */    int srcProcNum      /* originator */    )    {    BP_ANCHOR *pAnchor = bs->bs_pAnchor;    u_char *buf;    FAST CPU_DESC *pCpu;    FAST BUF_NODE *pBufNode0;    if (destProcNum < 0 || destProcNum >= MAXCPU)	{	/* broadcast to all CPUs on network */	buf = ItoKval (pBufNode->b_addr, u_char *, pAnchor);	for (destProcNum = MAXCPU - 1; destProcNum >= 0; --destProcNum)	    {	    pCpu = &bs->bs_pHdr->hdr_cpuDesc[destProcNum];	    if (DEBUG_OPTION_3)		dbgprintf ("bp: broadcast packet from %d\n", srcProcNum, 0, 0, 0, 0, 0);	    if (!pCpu->cd_active)		continue;	    if ((pBufNode0 = (BUF_NODE *) ringget ((RING *) bs->bs_pFreeRing))            == NULL)		break;	    pBufNode0 = ItoKval (pBufNode0, BUF_NODE *, pAnchor);            pBufNode0->b_len = pBufNode->b_len;	    bcopy ((caddr_t) buf,		   (caddr_t) ItoKval (pBufNode0->b_addr, u_char *, pAnchor),                   BP_NTOHS (pBufNode->b_len));	    if (ringput (ItoKval (pCpu->cd_pInputRing, RING *, pAnchor),			     KtoIval (pBufNode0, int, pAnchor)) == 0)		{		/* if input ring was full, then put bufNode back on free ring */		if (DEBUG_OPTION_2)		    dbgprintf ("bp: dropped packet\n", 0,0,0,0,0,0);		(void)ringput ((RING *) bs->bs_pFreeRing,			       KtoIval (pBufNode0, int, pAnchor));		}	    else		{		/* if input ring was empty, then interrupt destination CPU */		bpIntGen (pCpu, srcProcNum);		}	    }	(void) ringput ((RING *) bs->bs_pFreeRing,                    KtoIval (pBufNode, int, pAnchor));	}    else	{	pCpu = &bs->bs_pHdr->hdr_cpuDesc [destProcNum];	if (DEBUG_OPTION_3)	    dbgprintf ("bp: packet from %d for %d\n", srcProcNum, destProcNum, 0, 0, 0, 0);	if (!pCpu->cd_active)	    (void) ringput ((RING *) bs->bs_pFreeRing,                        KtoIval (pBufNode, int, pAnchor));	else if (ringput (ItoKval (pCpu->cd_pInputRing, RING *, pAnchor),	    		     KtoIval (pBufNode, int, pAnchor)) == 0)	    {	    /* input ring was full, then put bufNode back on free ring */	    if (DEBUG_OPTION_2)		dbgprintf ("bp: dropped packet\n", 0,0,0,0,0,0);	    (void) ringput ((RING *) bs->bs_pFreeRing,			    KtoIval (pBufNode, int, pAnchor));	    }	else	    {	    /* input ring had room, then interrupt destination CPU */	    bpIntGen (pCpu, srcProcNum);	    }	}    }#ifdef	UNIX/********************************************************************************* bpPollUnix - UNIX backplane poll** This routine is called by UNIX's timeout routine to poll the* backplane input rings for this CPU.*/LOCAL void bpPollUnix ()    {    FAST int unit;    for (unit = 0; unit < NBP; unit++)	{	/* if header structure non-zero then unit is initialized */	if (bp_softc[unit].bs_pHdr)	    bpintr (unit);	}    /* loop forever, with a delay of 1 */    timeout (bpPollUnix, (caddr_t)0, 1);    }#else	/* UNIX *//********************************************************************************* bpPollTask - backplane poll task** This routine is spawned as task to poll the backplane input rings for* this CPU.  It is only used if no backplane interrupt mechanism is* used.** NOMANUAL*/void bpPollTask (void)    {    FAST int unit;    FAST BP_SOFTC *bs;    FOREVER	{	for (unit = 0; unit < NBP; unit++)	    {	    bs = BP_SOFTC_P [unit];	    if (bs != NULL && !bs->bs_readPending)		{		bs->bs_readPending = TRUE;		if (bs->bs_pInputRing != NULL)		    (void) netJobAdd ((FUNCPTR)bpReadAll, unit,0,0,0,0);		}	    }	}    }/********************************************************************************* bpIntAck - acknowledge our backplane interrupt*/LOCAL void bpIntAck    (    FAST BP_SOFTC *bs    )    {    switch (bs->bs_intType)	{	case BP_INT_NONE:	case BP_INT_MAILBOX_1:	case BP_INT_MAILBOX_2:	case BP_INT_MAILBOX_4:	case BP_INT_MAILBOX_R1:	case BP_INT_MAILBOX_R2:	case BP_INT_MAILBOX_R4:	    break;	/* bus interrupt:	 *   arg1 = level	 *   arg2 = vector	 */	case BP_INT_BUS:	    sysBusIntAck (bs->bs_intArg1);	    break;	}    }#endif	/* UNIX *//********************************************************************************* bpConnect - connect to our backplane using the requested interrupt type** RETURNS: OK or ERROR if interrupt type not supported*/LOCAL STATUS bpConnect    (    FAST BP_SOFTC *bs,    FAST int unit    )    {    STATUS status;    switch (bs->bs_intType)	{	case BP_INT_NONE:	/* no interprocessor interrupt - spawn background polling task */#ifdef	UNIX	    {	    static BOOL bpIsPolling = FALSE;	    if (!bpIsPolling)		{		bpIsPolling = TRUE;		timeout (bpPollUnix, (caddr_t)0, 1);		}	    status = OK;	    }#else	/* UNIX */	    bpPollTaskId = taskSpawn ("bpPollTask", bpPollTaskPriority,				      bpPollTaskOptions, bpPollTaskStackSize,				      (FUNCPTR) bpPollTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);	    status = bpPollTaskId == ERROR ? ERROR : OK;#endif	/* UNIX */	    break;	case BP_INT_MAILBOX_1:	case BP_INT_MAILBOX_2:	case BP_INT_MAILBOX_4:	case BP_INT_MAILBOX_R1:	case BP_INT_MAILBOX_R2:	case BP_INT_MAILBOX_R4:	/* interrupt by mailbox (write to bus address):	 *   arg1 = bus address space	 *   arg2 = address	 *   arg3 = value	 */#ifdef	UNIX	    printf ("bp%d: bpConnect interrupt type not implemented\n", unit);	    status = ERROR;#else	/* UNIX */	    status = sysMailboxConnect ((FUNCPTR)bpintr, unit);#endif	/* UNIX */	    break;	case BP_INT_BUS:	/* bus interrupt:	 *   arg1 = level	 *   arg2 = vector	 */#ifdef	UNIX	    status = OK;  /* nothing to do, done in kernel configuration */#else	/* UNIX */	    status = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (bs->bs_intArg2), bpintr, unit);#endif	/* UNIX */	    break;	default:	    printf ("bp%d: bpConnect bad interrupt type: %d\n",		    unit, bs->bs_intType);	    status = ERROR;	    break;	}    return (status);    }/********************************************************************************* bpIntEnable - enable our backplane interrupt** RETURNS: OK or ERROR*/LOCAL STATUS bpIntEnable    (    FAST BP_SOFTC *bs    )    {    STATUS status;    int unit = bs->bs_if.if_unit;    switch (bs->bs_intType)	{	case BP_INT_NONE:	    status = OK;	/* no interrupt (polling) */	    break;	case BP_INT_MAILBOX_1:	case BP_INT_MAILBOX_2:	case BP_INT_MAILBOX_4:	case BP_INT_MAILBOX_R1:	case BP_INT_MAILBOX_R2:	case BP_INT_MAILBOX_R4:	/* interrupt by mailbox (write to bus address):	 *   arg1 = bus address space	 *   arg2 = address	 *   arg3 = value	 */#ifdef	UNIX	    status = ERROR;	    printf ("bp%d: bpIntEnable interrupt type 0x%x not implemented\n",		    unit, bs->bs_intType);#else	/* UNIX */	    status = sysMailboxEnable ((char *) bs->bs_intArg2);	    if (status == ERROR)		printf ("bp%d: error enabling mailbox interrupt addr 0x%x.\n",			  unit, bs->bs_intArg2);#endif	/* UNIX */	    break;	case BP_INT_BUS:	/* bus interrupt:	 *   arg1 = level	 *   arg2 = vector	 */#ifdef	UNIX	    status = OK;  /* nothing to do */#else	/* UNIX */	    status = sysIntEnable (bs->bs_intArg1);	    if (status == ERROR)		printf ("bp%d: error enabling bus interrupt level %d.\n",			  unit, bs->bs_intArg1);#endif	/* UNIX */	    break;	default:	    printf ("bp%d: bpIntEnable bad interrupt type: %d\n",		    unit, bs->bs_intType);	    status = ERROR;	    break;	}    return (status);    }/********************************************************************************* bpIntGen - interrupt another CPU*/LOCAL void bpIntGen    (    FAST CPU_DESC *pCpu,        /* ptr to descriptor of CPU to interrupt */    int srcProcNum              /* our procNum on this network */    )    {    char *pMailbox;    int intType;    /* if we're trying to interrupt ourself (a bad idea on some CPUs (is20))     * simply invoke the interrupt handler */    if (BP_NTOHL(pCpu->cd_cpuNum) == srcProcNum)	{	/* read input ring */#ifdef	UNIX	bpReadAll (pCpu->cd_unit);#else	/* UNIX */	(void) netJobAdd ((FUNCPTR)bpReadAll, pCpu->cd_unit, 0,0,0,0);#endif	/* UNIX */	return;	}    switch (intType = BP_NTOHL(pCpu->cd_intType))	{	case BP_INT_NONE:	    /* no interrupt (CPU is polling) */	    break;	case BP_INT_MAILBOX_1:	case BP_INT_MAILBOX_R1:	/* interrupt by mailbox (read/write to bus address):

⌨️ 快捷键说明

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