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

📄 if_pn.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    pn = mtod (m, struct pn_header *);    pn->vh_shost = in_lnaof ( ((struct arpcom *)ifp)->ac_ipaddr);     if (pn->vh_shost == 0)	{	panic ("pnoutput: interface not found in in_ifaddr\n");	error = EPERM;	goto bad;	}    /* map the destination address if it's a broadcast */    if ((pn->vh_dhost = dest) == INADDR_ANY)	pn->vh_dhost = PN_BROADCAST;    pn->vh_version = RING_VERSION;    pn->vh_type    = type;    pn->vh_info    = htons (info); /* this gets changed if testing packets */    /* queue packet, and if interface not active, send */    s = splimp ();    if (IF_QFULL(&ifp->if_snd)) 	{	IF_DROP(&ifp->if_snd);	error = ENOBUFS;	goto qfull;	}    IF_ENQUEUE(&ifp->if_snd, m);    if (vs->vs_oactive == 0)	pnstart (unit);    splx (s);    return (0);qfull :    m0 = m;    splx (s);bad :    m_freem (m0);    return (error);    }/********************************************************************************* pnioctl -*/LOCAL VOID pnioctl (ifp, cmd, data)    FAST struct ifnet *ifp;    int cmd;    caddr_t data;    {    FAST struct sockaddr *sin;    FAST struct ifaddr *ifa = (struct ifaddr *)data;    int error               = 0;    FAST int s              = splimp();    switch (cmd) 	{	case SIOCSIFADDR:	    sin = (struct sockaddr *)data;	    if (sin->sa_family != AF_INET)		{		error = EINVAL;		break;		}	    pnsetaddr(ifp, (struct sockaddr_in *)sin);	    /* store the internet address in arpcom */	    ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;	    if (!(ifp->if_flags & IFF_RUNNING))		{		pninit (ifp->if_unit);		if ((ifp->if_flags & IFF_UP) == 0)		    error = ENETDOWN;	/* self test failed, give error */		}	    break;	case SIOCSIFFLAGS:	    /* not implemented (set interface up/down) */	default:	    error = EINVAL;	    break;	}    splx (s);    return (error);    }/********************************************************************************* pnsetaddr - set pronet address** set up the address for this interface.  Uses the network number* from the passed address and an invalid host number.* pnidentify figures out and inserts real host address later.*/LOCAL VOID pnsetaddr (ifp, sin)    FAST struct ifnet *ifp;    FAST struct sockaddr_in *sin;    {    FAST struct pn_softc *vs  = &pn_softc[ifp->if_unit];    FAST struct pn_regs *addr = vs->pn_regs;     int lna = in_lnaof (((struct sockaddr_in *)sin)->sin_addr);    /* set the board's host number, overriding the hardware address */    if (IS_80)	addr->pn_ctl.rbufdmaptr = 0xc000 | lna;    }/********************************************************************************* pnrcsrintr - rcv csr intr handler*/LOCAL VOID pnrcsrintr (unit)    int unit;    {    int csr;    int rstatr;    int rcntr;    FAST struct pn_regs *addr = pn_softc[unit].pn_regs;    if ((addr->pn_ctl.rcsr & (PN_IRQ|PN_RDY)) != (PN_IRQ|PN_RDY))	logMsg ("proNET: rcv csr vector number clash!\n");    else	{	csr    = addr->pn_ctl.rcsr & 0xffff;	rstatr = addr->pn_ctl.rstatr & 0x7;	rcntr  = addr->pn_ctl.rcntr & 0x3fff; 	netJobAdd (pnrint, unit, csr, rstatr, rcntr);	}    addr->pn_ctl.rcsr =  PN_IEN | PN_MEN | PN_JNR | PN_RTI | PN_CEN;    addr->pn_ctl.rstcntr = 0;		/* get ready for next pkt */    }/********************************************************************************* pntcsrintr - xmt csr intr handler*/LOCAL VOID pntcsrintr (unit)    FAST 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;    FAST int rfsreg           = addr->pn_ctl.rfsreg & 0xffff;    sysBusIntAck (vs->pnIntLevel);    if ((tcsr & (PN_IRQ|PN_RDY)) != (PN_IRQ|PN_RDY))	{	pnprintf("proNET: xmt csr vector number clash!\n");	logMsg ("tcsr = %#x\n", addr->pn_ctl.tcsr );	if ((addr->pn_ctl.tcsr & (PN_IRQ)) != (PN_IRQ))	    logMsg ("PN_IRQ not on\n");	if ((addr->pn_ctl.tcsr & (PN_RDY)) != (PN_RDY))	    logMsg ("PN_RDY not on\n");	addr->pn_ctl.tcsr = PN_RTI;		/* clear/reset the interrupt */	}    else	{	/* should call pnxint() here, but duplicated here for speed */	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 & PNTERR)	    {	    if (vs->vs_tries++ < PNRETRY) 		{		/* re-order refused bits and cancel the "any":		 *  what's wrong here?		 *		 * rfsreg = ((rfsreg >> 9) & 0x7f) | ((rfsreg & 0xff) << 7);		 */		if (tcsr & PN_TMO)		    {		    vs->vs_otimeout++;		    pnprintf ("pntcsrintr: RESTART (TIMEOUT) %#x\n", rfsreg);		    }		if (tcsr & PN_REF)		    {		    vs->vs_if.if_collisions++;		    vs->vs_refused++;		    pnprintf ("pntcsrintr: RESTART (refused) %#x\n", rfsreg);		    }		if (tcsr & PN_BDF)		    {		    pnprintf ("pntcsrintr: RESTART (bad form) %#x\n", rfsreg);		    }		/* doesn't need to be at task level, 'cuz we're restarting */		pnstart (unit);		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*/);	    }	/* let's only call pnstart if there are messages in the output queue */	if (vs->vs_if.if_snd.ifq_len > 0)  	    netJobAdd (pnstart, unit);	}    }/********************************************************************************* filltbuf -** takes a chain of mbufs and copies the chain into a buffer.* returns the number of bytes put into the buffer.  if board is* not swabbing it also swabs the bytes. does not free mbuf chain.** RETURNS: number of bytes filled*/LOCAL int filltbuf (unit, buf, mchain)    int unit;    caddr_t buf;    struct mbuf *mchain;    {    FAST u_long *tbufda;    FAST struct mbuf *m;    BOOL odd             = FALSE;    int len              = 0;    struct pn_softc *vs  = &pn_softc[unit];    struct pn_regs *addr = vs->pn_regs;     /* sum mbuf chain, and check for odd length mbuf's */    for (m = mchain; m != NULL; m = m->m_next)	{	if (m->m_len & 0x1 || m->m_off & 0x1)	    odd = TRUE;	len += m->m_len;	}    tbufda = (u_long*)&addr->pn_ctl.tbufda;    vs->vs_ostrt = (TBUFSIZE - ((len + 3) >> 2)) & 0x3ff;    addr->pn_ctl.tbufad = vs->vs_ostrt;    m = mchain;    if (odd)	{	caddr_t bpend;	FAST caddr_t bp = buf;	/* double buffering! however this code probably never runs */	for (; m != NULL; m = m->m_next)	    {	    pncopy (mtod (m, caddr_t), bp, m->m_len);	    bp += m->m_len;	    }	bpend = bp;	for (bp = buf; bp < bpend; bp += 4)	    *tbufda = *(u_long *)bp;	}    else	{	int flag = 0;	for (; m != NULL; m = m->m_next)	    flag = movep (mtod (m, u_long *), tbufda, m->m_len, flag);	}    addr->pn_ctl.tbufad = vs->vs_ostrt;    return (len);    }/********************************************************************************* emptyrbuf - empty a buffer into a chain of mbufs** This routine is admitted to be hard to understand.  It is doing three* things at once: copying the buffer, moving IP trailers to the front of* the packet and skipping the ring header.** NOTE:* IP trailers part is not tested.** RETURNS: the start of the chain, or 0 if error** ARGSUSED*/LOCAL struct mbuf *emptyrbuf (unit, addr, pktad, totlen, off0, skip, ifp)    int unit;			/* unit number */    struct pn_regs *addr;	/* device address */    int pktad;			/* index of pkt in RBUFFER */    FAST int totlen;		/* bytes to copy */    int off0;			/* trailer offset */    int skip;			/* header length */    struct ifnet *ifp;    {    FAST int len;    FAST struct mbuf *m;    struct mbuf *top = (struct mbuf *) 0;    FAST struct mbuf **mp = &top;    int off          = off0;		/* assuming off = 0, ie. no trailers */    int index        = ((pktad + skip) >> 1) & 0x1fff;	/* word array index */    FAST caddr_t bp  = (caddr_t)&addr->pn_rbuffer[index];    pntracehdr ("input", (struct pn_header *)&(addr->pn_rbuffer[pktad>>1]), 1);    while (totlen > 0)	{	MGET(m,M_DONTWAIT,MT_DATA);	if (m == (struct mbuf *)0)	    {	    if (top != (struct mbuf *)0)	      m_freem (top);	    return ((struct mbuf *)0);	    }	if (off)	    {	    len = totlen - off;	    index = ((pktad + off + skip) >> 1) & 0x1fff;	    bp = (caddr_t)&(addr->pn_rbuffer[index]);	    }	else	    len = totlen;	m->m_off = MMINOFF;	if (ifp)	    {	    /* Leave room for ifp */	    m->m_len = MIN(MLEN - sizeof(ifp), len);	    m->m_off += sizeof(ifp);	    }	else 	    m->m_len = MIN(MLEN, len);	m->m_next = (struct mbuf *)0; 	if ((index << 1) + m->m_len >= RBUFSIZE)	    {	    caddr_t tp = mtod (m, caddr_t);	    int cut = RBUFSIZE - (index << 1);	    pncopy(bp,tp,cut);	    pncopy((caddr_t)addr->pn_rbuffer,tp+cut,m->m_len-cut);	    index = (m->m_len - cut) >> 1;	    bp = (caddr_t)&(addr->pn_rbuffer[index]);	    }	else	    {	    pncopy(bp, mtod (m,caddr_t), m->m_len);	    index += (m->m_len >> 1);	    bp += m->m_len;	    }	*mp = m;	mp = &m->m_next;	if (off)	    {	    off += m->m_len;	    if (off == totlen)		{		index = ((pktad + skip) >> 1) & 0x1fff;		bp = (caddr_t)&(addr->pn_rbuffer[index]);		off = 0;		totlen = off0;		}	    }	else	    totlen -= m->m_len;	if (ifp) 	    {	    /* prepend interface pointer to first mbuf */	    m->m_len += sizeof(ifp);	    m->m_off -= sizeof(ifp);	    *(mtod (m, struct ifnet **)) = ifp;	    ifp = (struct ifnet *)0;	    }      }    return (top);    }/* debugging aid printout routines *//********************************************************************************* pnprt_hdr - print the local net header in "v" with title "s"*/LOCAL VOID pnprt_hdr (s, v, nl)    char *s;    FAST struct pn_header *v;    int nl;    {    printf ("%10s @ %#10x: d=%#x s=%#x v=%#x t=%#x i=%#x",	s, v,	0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost),	0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type),	0xffff & (int)(v->vh_info));    if (nl)	printf("\n");    }/********************************************************************************* pn_errors - print error statistics and zero*/VOID pn_errors (unit)    {    FAST struct pn_softc *vs = &pn_softc[unit];    printf ("oerrors = %d", vs->vs_if.if_oerrors);    vs->vs_if.if_oerrors = 0;    printf ("otimeout = %d", vs->vs_otimeout);    vs->vs_otimeout = 0;    printf ("collisions = %d", vs->vs_if.if_collisions);    vs->vs_if.if_collisions = 0;    printf ("refused = %d", vs->vs_refused);    vs->vs_refused = 0;    }BOOL xmovep (from, to, len)    short *from;    short *to;    int len;    {    while (len -= 2)	*to = *from++;    }

⌨️ 快捷键说明

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