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

📄 if_pn.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * There is a problem with Proteon's software address		 * override so the address returned from the first		 * broadcast message after powerup may be wrong.		 */		ignorexmt = FALSE;		continue;		}	    /* copy out the rcv pkt from RBUFFER to rbuf */	    msg = msgStart;	    for (pktsz = 0;		 pktsz < PNBUFSIZE && pktsz < (addr->pn_ctl.rcntr >> 1);		 pktsz++)		{		*msg++ = addr->pn_rbuffer [pktsz];		}	    addr->pn_ctl.rstcntr = 0;	/* clear CNTR */	    v = (struct pn_header *) msgStart;	    /* proper message type */	    if ((v->vh_type & 0xff) == RING_DIAGNOSTICS)		{		if (shost == 0)		    {		    shost = v->vh_shost & 0xff;		    ((struct pn_header *)(vs->vs_tbuf))->vh_dhost = shost;		    }		  successes++;		}	    else	      failures++;	    v->vh_type = 0;	/* zap it out so we can check again */	    }	if (failures >= PNIDENTRETRY)	    {	    if (flg)		{		printf("pn%d: failed self-test after %d tries in %s mode\n",			unit, PNIDENTRETRY, ix == 0 ? "digital loopback" :			(ix == 1 ? "analog loopback" : "network"));		printf("pn%d: rstatr = %#x, rcsr = %#x, tcsr = %#x\n",			unit, 0x7 & addr->pn_ctl.rstatr, /*PN_SBITS,*/			0xffff & addr->pn_ctl.rcsr/*, PN_RBITS*/,			0xffff & addr->pn_ctl.tcsr/*, PN_TBITS*/);		}	    addr->pn_ctl.rcsr = PN_RST;	/* kill the sick board */	    addr->pn_ctl.tcsr = PN_RST;	    free ((char *) msgStart);	    return (0);	    }	}    free ((char *) msgStart);    return (shost);    }/********************************************************************************* pnstart - start or restart output on interface** If interface active, then a retransmit, just restuff registers and go.* If interface not already active, get another datagram off the interface* queue, copy to buffer and send it.*/LOCAL VOID pnstart (unit)    int unit;    {    int s;    FAST struct mbuf *m;    FAST struct pn_softc *vs  = &pn_softc[unit];    FAST struct pn_regs *addr = vs->pn_regs;     /* active? */    if (vs->vs_oactive)	{	addr->pn_ctl.tbufad = vs->vs_ostrt;	/* retransmit */	goto restart;	}    /* not active, try dequeueing a new message */    s = splimp();    IF_DEQUEUE(&vs->vs_if.if_snd, m);    splx (s);    /* any message? */    if (m == NULL) 	{	vs->vs_oactive = 0;	return;	}    /* prepare to send */    vs->vs_olen = filltbuf (unit, vs->vs_tbuf, m);    m_freem (m);restart :    /* make sure this packet will fit in the interface */    if (vs->vs_olen > PNBUFSIZE)	{	printf ("pn%d: vs_olen: %d > PNBUFSIZE\n", unit, vs->vs_olen);	panic ("pnstart: vs_olen botch");	}    vs->vs_if.if_timer = PNTIMEOUT;    vs->vs_oactive = 1;    /* supposed to setup for 82258 transmit dma here */    if (addr->pn_ctl.tcsr & PN_NOK) 	vs->vs_init++;				/* count ring inits */    addr->pn_ctl.tcsr = PN_IEN | PN_INI | PN_ORI;    }/********************************************************************************* pnwatchdog -** Transmit watchdog timer routine. This routine gets called when we lose* a transmit interrupt. The best we can do is try to restart output.*/LOCAL VOID pnwatchdog (unit)    int unit;    {    FAST int s;    FAST struct pn_softc *vs = &pn_softc[unit];    pnprintf("pn%d: lost a transmit interrupt.\n", unit);    vs->vs_timeouts++;    s = splimp ();    pnstart (unit);    splx (s);    }/********************************************************************************* pnxint - transmit interrupt** Start new output if more data available.*/LOCAL VOID pnxint (unit)    int unit;    {    FAST struct pn_softc *vs  = &pn_softc[unit];    FAST struct pn_regs *addr = vs->pn_regs;     FAST int tcsr             = addr->pn_ctl.tcsr & 0xffff;    vs->vs_if.if_timer = 0;    addr->pn_ctl.tcsr = PN_RTI;		/* clear/reset the interrupt */    if (vs->vs_oactive == 0) 	{	pnprintf("pn%d: stray interrupt tcsr = %#x\n", unit, tcsr/*,PN_TBITS*/);	return;	}    /* retransmit on soft error.     * TODO: sort retransmits to end of queue if possible     */    if (tcsr & (PN_TMO | PN_REF))	{	if (vs->vs_tries++ < PNRETRY) 	    {	    if (tcsr & PN_TMO)		vs->vs_otimeout++;	    if (tcsr & PN_REF)		{		vs->vs_if.if_collisions++;		vs->vs_refused++;		}	    pnstart (unit);	/* restart this message */	    return;	    }	}    vs->vs_if.if_opackets++;    vs->vs_oactive = 0;    vs->vs_tries   = 0;    if (tcsr & PNTERR)	{	vs->vs_if.if_oerrors++;	pnprintf ("pn%d: error tcsr = %#x\n", unit, tcsr/*, PN_TBITS*/);	}    pnstart (unit);    }/********************************************************************************* pnrint - receive interrupt** First, stash data on packet just received. Then* swap receive buffers and start a new receive. Now! Then check error* status of packet. Then undo trailers, examine the packet, and pass it* on the the appropriate higher protocol.*/LOCAL VOID pnrint (unit, rcsr, rstatr, rcntr)    int unit;    FAST int rcsr;		/* this is the current input CSR */    FAST int rstatr;		/* ditto here as status register */    int rcntr;    {    FAST struct pn_header *pn;    FAST struct mbuf *m;    struct ifqueue *inq;    int len;    int s;    FAST int off;    int type;    short resid;			/* this is the current residual */    int index;    FAST struct pn_softc *vs  = &pn_softc[unit];    FAST struct pn_regs *addr = vs->pn_regs;     vs->vs_if.if_ipackets++;    /* save device registers, as we are restarting     * (note rcsr saved it initial interrupt time)     */    if (rcntr < vs->rcvhd)	len = RBUFSIZE - vs->rcvhd + rcntr;    else        len = rcntr  - vs->rcvhd;	/* only 14 addr bits */    len -= sizeof (struct pn_header);	/* but remove local net hdr len */    /* get a pointer to packet in RBUFFER */    index = vs->rcvhd;    pn = (struct pn_header *)&(addr->pn_rbuffer[index >> 1]);    pntracehdr ("rint", pn, 1);    vs->rcvhd = (rcntr + 3) & 0x3ffc;   /* blk addr of next pkt */    if (! (vs->vs_if.if_flags & IFF_UP))      {      pnprintf ("pn%d: not up!\n", unit);      return;      }    /* Now that a new receive has been started, do the processing     * on the old packet (bufno)     */    if (rstatr & PNRERR) 	{	pnprintf("pn%d: receive error, rcsr = %#x, rstatr = %#x\n",                  unit, rcsr, rstatr);	if (rstatr & RBDF)	    vs->vs_ibadf++;	goto dropit;	}    if (rcsr & PN_PER)	{	/* don't have to clear it because the recieve command	 * above wrote 0 to the parity bit	 */	vs->vs_parity++;	/* Only on 10 megabit proNET is PN_PER an end-to-end parity	 * bit. On 80 megabit, it returns to the intended use of	 * node-to-node parity. End-to-end parity errors on 80 megabit	 * give PN_BDF.	 */	if (!IS_80)	    goto dropit;	}    /* fundamental length check */    if ((rstatr & ROVR) || (len > PNMRU) || (len <= 0))	{	pnprintf(	"pn%d: len too long or short, len = %d, rcsr = %#x, rstatr = %#x\n",	    unit, len, rcsr, /*PN_RBITS,*/ rstatr/*, PN_SBITS*/);	goto dropit;	}    /* check the protocol header version */    if (pn->vh_version != RING_VERSION)	{	pnprintf("pn%d: bad protocol header version %d\n",		 unit, pn->vh_version & 0xff);	goto dropit;	}    /* untested trailer handling -- taken straight from VAX code */    off = 0;#define	pndataaddr(pn, off, type)	((type)(((caddr_t)((pn)+1)+(off))))    if (pn->vh_type >= RING_IPTrailer &&	pn->vh_type < RING_IPTrailer+RING_IPNTrailer) 	{	off = (pn->vh_type - RING_IPTrailer) * 512;	if (off > PNMTU) 	{	    pnprintf("pn%d: off > PNMTU, off = %d, rcsr = %#x\n",		unit, off, rcsr/*, PN_RBITS*/);	    goto dropit;	}	pn->vh_type = ntohs(*pndataaddr(pn, off, u_short *));	resid = ntohs(*pndataaddr(pn, 2+off, u_short *));						    /* 2+off -> better code */	if (off + resid > len) 	    {	    pnprintf ("pn%d: trailer packet too short\n", unit);	    pnprintf ("pn%d: len=%d, off=%d, resid=%d, rcsr=%#x, rstatr=%#x\n",			unit, len, off, resid,			rcsr/*, PN_RBITS*/, rstatr/*, PN_SBITS*/);	    goto dropit;	    }	len = off + resid;	}    if (len == 0) 	{	pnprintf("pn%d: len is zero, rcsr = %#x, rstatr = %#x\n",                  unit, rcsr/*, PN_RBITS*/, rstatr/*, PN_SBITS*/);	goto dropit;	}    /* save packet type for later demux */    type = pn->vh_type & 0xff;    /* Copy buffer into mbuf chain, without net header.     * Could wait until type is o.k., but almost certainly is so why wait     * Note that this part of the code runs SLOW, which is why the     * multiple receive buffers are used. It still must be reckoned     * that the keyboard is still locked out...     */    m = emptyrbuf (unit, addr, index, len, off, sizeof(struct pn_header), 		  &vs->vs_if);    if (m == 0)			/* success? */	goto dropit;    /* remove trailer header length header */    if (off)	{    	struct ifnet *ifp;    	ifp = *(mtod (m, struct ifnet **));    	m->m_off += 2 * sizeof (u_short);    	m->m_len -= 2 * sizeof (u_short);    	*(mtod (m, struct ifnet **)) = ifp;	}    /* demultiplex on packet type */    switch (type)	{#ifdef INET	case RING_IP:	    inq = &ipintrq;	    s = splimp ();	    if (IF_QFULL(inq)) 		{		IF_DROP(inq);		m_freem (m);		}	    else		IF_ENQUEUE(inq, m);	    splx (s);	    netJobAdd (ipintr, 0);	    break;#endif	default:	    pnprintf ("pn%d: unknown pkt type %#x\n", unit, type);	    m_freem (m);	}    return;	/* next packet receive is already started */dropit :	/* drop packet on floor -- count them!! */    pnprintf ("pn%d: dropped it!\n", unit);    vs->vs_if.if_ierrors++;    }/********************************************************************************* pnoutput -** RETURNS: 0 if OK, otherwise UNIX errno*/LOCAL VOID pnoutput (ifp, m0, dst)    struct ifnet *ifp;    struct mbuf *m0;    struct sockaddr *dst;    {    FAST struct pn_header *pn;    FAST int s;    int type;    int dest;    int error;    u_short info              = 0;    FAST struct mbuf *m       = m0;    FAST int unit             = ifp->if_unit;    FAST struct pn_softc *vs  = &pn_softc[unit];    FAST struct pn_regs *addr = vs->pn_regs;     switch (dst->sa_family) 	{#ifdef INET	case AF_INET:	    dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;	    /*	     * Take the local net address part of the address,	     * and use it as node number. This is not exactly	     * kosher under some circumstances, but I'll let it fly.	     */	    if ((dest = in_lnaof(*((struct in_addr *)&dest))) >= 0x100) 		{		pnprintf("pn%d: can't do af%d\n", unit, dst->sa_family);		error = EPERM;		goto bad;		}	    type = RING_IP;		/* NO TRAILERS OUTBOUND */	    break;#endif	default:	    pnprintf("pn%d: can't handle af%d\n", unit, dst->sa_family);	    error = EAFNOSUPPORT;	    goto bad;	}    /* add local net header.  If no space in first mbuf, allocate another */    if (m->m_off > MMAXOFF || MMINOFF + sizeof (struct pn_header) > m->m_off) 	{	m = m_get(M_DONTWAIT, MT_HEADER);	if (m == (struct mbuf *)0) 	    {	    error = ENOBUFS;	    goto bad;	    }	m->m_next = m0;	m->m_off = MMINOFF;	m->m_len = sizeof (struct pn_header);	}    else 	{	m->m_off -= sizeof (struct pn_header);	m->m_len += sizeof (struct pn_header);	}

⌨️ 快捷键说明

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