xref: /csrg-svn/sys/vax/if/if_dp.c (revision 45236)
145163Ssklower /*
245163Ssklower  * Copyright (c) 1990 Regents of the University of California.
345163Ssklower  * All rights reserved.
445163Ssklower  *
545163Ssklower  * %sccs.include.redist.c%
645163Ssklower  *
7*45236Ssklower  *	@(#)if_dp.c	7.4 (Berkeley) 09/14/90
845163Ssklower  */
945163Ssklower 
1045163Ssklower #include "dp.h"
1145163Ssklower #if NDP > 0
1245163Ssklower 
1345163Ssklower /*
1445163Ssklower  * DPV-11 device driver, X.25 version
1545163Ssklower  *
1645163Ssklower  * Derived from dmc-11 driver:
1745163Ssklower  *
1845163Ssklower  *	Bill Nesheim
1945163Ssklower  *	Cornell University
2045163Ssklower  *
2145163Ssklower  *	Lou Salkind
2245163Ssklower  *	New York University
2345163Ssklower  */
2445163Ssklower 
2545163Ssklower /* #define DEBUG	/* for base table dump on fatal error */
2645163Ssklower 
2745163Ssklower #include "machine/pte.h"
2845163Ssklower 
2945163Ssklower #include "param.h"
3045163Ssklower #include "systm.h"
3145163Ssklower #include "mbuf.h"
3245163Ssklower #include "buf.h"
3345163Ssklower #include "ioctl.h"		/* must precede tty.h */
3445163Ssklower #include "protosw.h"
3545163Ssklower #include "socket.h"
3645228Ssklower #include "socketvar.h"
3745163Ssklower #include "syslog.h"
3845163Ssklower #include "vmmac.h"
3945163Ssklower #include "errno.h"
4045163Ssklower #include "time.h"
4145163Ssklower #include "kernel.h"
4245163Ssklower 
4345163Ssklower #include "../net/if.h"
4445163Ssklower #include "../net/netisr.h"
4545163Ssklower #include "../net/route.h"
4645163Ssklower 
4745163Ssklower #include "../vax/cpu.h"
4845163Ssklower #include "../vax/mtpr.h"
4945166Ssklower 
5045228Ssklower #define	dzdevice dpdevice
5145163Ssklower #include "../vaxuba/pdma.h"
5245166Ssklower #include "../vaxuba/ubavar.h"
5345163Ssklower 
5445228Ssklower #include "../netccitt/x25.h"
5545228Ssklower #include "../netccitt/pk.h"
5645228Ssklower #include "../netccitt/pk_var.h"
5745166Ssklower 
5845163Ssklower #include "if_dpreg.h"
5945163Ssklower 
6045163Ssklower /*
6145163Ssklower  * Driver information for auto-configuration stuff.
6245163Ssklower  */
6345163Ssklower int	dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
6445228Ssklower int	dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(), dptestoutput();
6545163Ssklower 
6645163Ssklower struct	uba_device *dpinfo[NDP];
6745163Ssklower 
6845163Ssklower u_short	dpstd[] = { 0 };
6945163Ssklower struct	uba_driver dpdriver =
7045163Ssklower 	{ dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo };
7145163Ssklower 
7245163Ssklower /*
7345228Ssklower  * debug info
7445228Ssklower  */
7545228Ssklower struct	dpstat {
7645228Ssklower 	long	start;
7745228Ssklower 	long	nohdr;
7845228Ssklower 	long	init;
7945228Ssklower 	long	rint;
8045228Ssklower 	long	xint;
8145228Ssklower 	long	reset;
8245228Ssklower 	long	ioctl;
8345228Ssklower 	long	down;
8445228Ssklower 	long	mchange;
8545228Ssklower 	long	timeout;
8645228Ssklower } dpstat;
8745228Ssklower /*
8845163Ssklower  * Pdma structures for fast interrupts.
8945163Ssklower  */
9045163Ssklower struct	pdma dppdma[2*NDP];
9145163Ssklower 
9245163Ssklower /* error reporting intervals */
9345163Ssklower #define DPI_RPNBFS	50
9445163Ssklower #define DPI_RPDSC	1
9545163Ssklower #define DPI_RPTMO	10
9645163Ssklower #define DPI_RPDCK	10
9745163Ssklower 
9845163Ssklower 
9945163Ssklower /*
10045163Ssklower  * DP software status per interface.
10145163Ssklower  *
10245163Ssklower  * Each interface is referenced by a network interface structure,
10345163Ssklower  * dp_if, which the routing code uses to locate the interface.
10445163Ssklower  * This structure contains the output queue for the interface, its address, ...
10545163Ssklower  */
10645163Ssklower struct dp_softc {
10745163Ssklower 	struct	ifnet dp_if;		/* network-visible interface */
10845228Ssklower 	int	dp_ipl;
109*45236Ssklower 	struct	dpdevice *dp_addr;	/* dpcsr address */
11045163Ssklower 	short	dp_iused;		/* input buffers given to DP */
11145163Ssklower 	short	dp_flags;		/* flags */
11245228Ssklower #define DPF_RUNNING	0x01		/* device initialized */
11345228Ssklower #define DPF_ONLINE	0x02		/* device running (had a RDYO) */
11445228Ssklower #define DPF_RESTART	0x04		/* software restart in progress */
11545228Ssklower #define DPF_FLUSH	0x08		/* had a ROVR, flush ipkt when done */
11645163Ssklower 	short	dp_ostate;		/* restarting, etc. */
11745163Ssklower 	short	dp_istate;		/* not sure this is necessary */
11845163Ssklower #define DPS_IDLE	0
11945163Ssklower #define DPS_RESTART	1
12045163Ssklower #define DPS_ACTIVE	2
12145163Ssklower #define DPS_XEM		3		/* transmitting CRC, etc. */
12245163Ssklower 	int	dp_errors[4];		/* non-fatal error counters */
12345163Ssklower #define dp_datck dp_errors[0]
12445163Ssklower #define dp_timeo dp_errors[1]
12545163Ssklower #define dp_nobuf dp_errors[2]
12645163Ssklower #define dp_disc  dp_errors[3]
12745228Ssklower 	struct timeval	dp_xt;			/* start of last transmission */
12845163Ssklower 	char	dp_obuf[DP_MTU+8];
12945166Ssklower 	char	dp_ibuf[DP_MTU+8];
13045163Ssklower } dp_softc[NDP];
13145163Ssklower 
13245163Ssklower dpprobe(reg, ui)
13345163Ssklower 	caddr_t reg;
13445163Ssklower 	struct	uba_device *ui;
13545163Ssklower {
13645163Ssklower 	register int br, cvec;
13745163Ssklower 	register struct dpdevice *addr = (struct dpdevice *)reg;
138*45236Ssklower 	register int unit = ui->ui_unit;
13945163Ssklower 
14045163Ssklower #ifdef lint
14145163Ssklower 	br = 0; cvec = br; br = cvec;
14245163Ssklower 	dprint(0); dpxint(0);
14345163Ssklower #endif
14445228Ssklower 	(void) spl6();
14545163Ssklower 	addr->dpclr = DP_CLR;
14645163Ssklower 	addr->dpclr = DP_XIE|DP_XE;
14745163Ssklower 	DELAY(100000);
148*45236Ssklower 	dp_softc[unit].dp_ipl = br = qbgetpri();
149*45236Ssklower 	dp_softc[unit].dp_addr = addr;
15045163Ssklower 	addr->dpclr = 0;
15145228Ssklower 	if (cvec && cvec != 0x200){
15245228Ssklower 		cvec -= 4;
15345228Ssklower 	}
15445163Ssklower 	return (1);
15545163Ssklower }
15645163Ssklower 
15745163Ssklower /*
15845163Ssklower  * Interface exists: make available by filling in network interface
15945163Ssklower  * record.  System will initialize the interface when it is ready
16045163Ssklower  * to accept packets.
16145163Ssklower  */
16245163Ssklower dpattach(ui)
16345163Ssklower 	register struct uba_device *ui;
16445163Ssklower {
16545163Ssklower 	register struct dp_softc *dp = &dp_softc[ui->ui_unit];
16645163Ssklower 
16745163Ssklower 	dp->dp_if.if_unit = ui->ui_unit;
16845163Ssklower 	dp->dp_if.if_name = "dp";
16945163Ssklower 	dp->dp_if.if_mtu = DP_MTU;
17045163Ssklower 	dp->dp_if.if_init = dpinit;
17145163Ssklower 	dp->dp_if.if_output = x25_ifoutput;
17245163Ssklower 	dp->dp_if.if_start = dpstart;
17345163Ssklower 	dp->dp_if.if_ioctl = dpioctl;
17445163Ssklower 	dp->dp_if.if_reset = dpreset;
17545163Ssklower 	dp->dp_if.if_watchdog = dptimeout;
17645228Ssklower 	dp->dp_if.if_flags = 0;
17745163Ssklower 	if_attach(&dp->dp_if);
17845163Ssklower }
17945163Ssklower 
18045163Ssklower /*
18145163Ssklower  * Reset of interface after UNIBUS reset.
18245163Ssklower  * If interface is on specified UBA, reset its state.
18345163Ssklower  */
18445163Ssklower dpreset(unit, uban)
18545163Ssklower 	int unit, uban;
18645163Ssklower {
18745163Ssklower 	register struct uba_device *ui;
18845163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
18945163Ssklower 	register struct dpdevice *addr;
19045163Ssklower 
19145228Ssklower 	dpstat.reset++;
19245163Ssklower 	if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
19345163Ssklower 	    ui->ui_ubanum != uban)
19445163Ssklower 		return;
195*45236Ssklower 	dpdown(unit);
196*45236Ssklower 	dpinit(unit);
19745163Ssklower 	printf(" dp%d", unit);
19845163Ssklower }
19945163Ssklower 
20045163Ssklower /*
20145163Ssklower  * Initialization of interface.
20245163Ssklower  */
20345163Ssklower dpinit(unit)
20445163Ssklower 	int unit;
20545163Ssklower {
20645163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
20745163Ssklower 	register struct dpdevice *addr;
20845228Ssklower 	register struct ifaddr *ifa;
20945228Ssklower 	register struct pdma *pdp = &dppdma[unit*2];
21045228Ssklower 	int base, s;
21145163Ssklower 
21245228Ssklower 	dpstat.init++;
21345163Ssklower 	/*
21445163Ssklower 	 * Check to see that an address has been set.
21545163Ssklower 	 */
21645228Ssklower 	for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
21745163Ssklower 		if (ifa->ifa_addr->sa_family != AF_LINK)
21845163Ssklower 			break;
21945163Ssklower 	if (ifa == (struct ifaddr *) 0)
22045163Ssklower 		return;
22145163Ssklower 
222*45236Ssklower 	addr = dp->dp_addr;
22345228Ssklower 	s = splimp();
22445163Ssklower 	dp->dp_iused = 0;
22545163Ssklower 	dp->dp_istate = dp->dp_ostate = DPS_IDLE;
22645228Ssklower 	dp->dp_if.if_flags |= IFF_RUNNING;
22745228Ssklower 	dp->dp_if.if_flags &= ~IFF_OACTIVE;
22845228Ssklower 
22945228Ssklower 	pdp->p_addr = addr;
23045228Ssklower 	pdp->p_fcn = dpxint;
23145228Ssklower 	pdp->p_mem = pdp->p_end = dp->dp_obuf;
23245228Ssklower 	pdp++;
23345228Ssklower 	pdp->p_addr = addr;
23445228Ssklower 	pdp->p_fcn = dprint;
23545228Ssklower 	/* force initial interrupt to come to dprint */
23645228Ssklower 	pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
23745228Ssklower 
23845228Ssklower 	addr->dpclr = DP_CLR;
23945228Ssklower 	DELAY(1000);
24045163Ssklower 	addr->dpclr = 0;
24145228Ssklower 	DELAY(1000);
24245228Ssklower 	/* DP_ATA = 0, DP_CHRM = 0,
24345228Ssklower 			    CRC = CCIIT, initially all ones, 2nd addr = 0 */
24445228Ssklower 	addr->dpsar = 0;
24545228Ssklower 	/* enable receive interrupt */
24645228Ssklower 	addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
24745228Ssklower 	dpstart(&dp->dp_if);
24845163Ssklower 	splx(s);
24945163Ssklower }
25045163Ssklower 
25145228Ssklower int dpMessy = 0;
25245163Ssklower /*
25345163Ssklower  * Start output on interface.  Get another datagram
25445163Ssklower  * to send from the interface queue and map it to
25545163Ssklower  * the interface before starting output.
25645163Ssklower  *
25745163Ssklower  */
25845163Ssklower dpstart(ifp)
25945163Ssklower 	struct ifnet *ifp;
26045163Ssklower {
26145228Ssklower 	int s, unit = ifp->if_unit, error = 0, len;
26245163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
263*45236Ssklower 	register struct dpdevice *addr = dp_addr;
26445163Ssklower 	register struct mbuf *m;
26545163Ssklower 	register char *cp;
26645163Ssklower 	char *cplim;
26745163Ssklower 
26845163Ssklower 	/*
26945163Ssklower 	 * If already doing output, go away and depend on transmit
27045163Ssklower 	 * complete or error.
27145163Ssklower 	 */
27245228Ssklower 	dpstat.start++;
273*45236Ssklower 	if ((dp->dp_if.if_flags & IFF_OACTIVE) ||
274*45236Ssklower 	    ! (dp->dp_if.if_flags & IFF_RUNNING))
27545228Ssklower 		goto out;
27645163Ssklower 	IF_DEQUEUE(&dp->dp_if.if_snd, m);
27745163Ssklower 	if (m == 0)
27845228Ssklower 		goto out;
27945228Ssklower 	dp->dp_if.if_collisions++;
28045228Ssklower 	if (m->m_flags & M_PKTHDR)
28145228Ssklower 		len = m->m_pkthdr.len;
28245228Ssklower 	else {
28345228Ssklower 		struct mbuf *m0 = m;
28445228Ssklower 		for (len = 0; m; m = m->m_next)
28545228Ssklower 			len += m->m_len;
28645228Ssklower 		m = m0;
28745228Ssklower 		dpstat.nohdr++;
28845228Ssklower 	}
28945228Ssklower 	if (len == 0)
29045228Ssklower 		goto out;
29145228Ssklower 	if (len > DP_MTU) {
29245228Ssklower 		error = EINVAL;
29345228Ssklower 		goto out;
29445228Ssklower 	}
29545228Ssklower 	cp = dp->dp_obuf;
29645228Ssklower 	dppdma[2*unit].p_mem = cp + 1;
29745163Ssklower 	while (m) {
29845163Ssklower 		struct mbuf *n;
29945163Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len);
30045163Ssklower 		cp += m->m_len;
30145163Ssklower 		MFREE(m, n); m = n;
30245163Ssklower 	}
30345163Ssklower 	dppdma[2*unit].p_end = cp;
30445228Ssklower 	if (dpMessy)
30545228Ssklower 		printf("dp: len %d, start %x, end %x, first %x, next %x",
30645228Ssklower 			len, dp->dp_obuf, cp, *(int *)dp->dp_obuf,
30745228Ssklower 			1[(int *)dp->dp_obuf]);
30845163Ssklower 	dp->dp_if.if_flags |= IFF_OACTIVE;
30945163Ssklower 	dp->dp_ostate = DPS_ACTIVE;
31045228Ssklower 	dp->dp_if.if_collisions--;
31145228Ssklower dp->dp_xt = time;
31245228Ssklower 	addr->dpclr = DP_XE | DP_XIE;
31345228Ssklower 	addr->dptdsr = DP_XSM | (0xff & dp->dp_obuf[0]);
31445228Ssklower out:
31545228Ssklower 	return (error);
31645163Ssklower }
31745163Ssklower /*
31845163Ssklower  * Receive done or error interrupt
31945163Ssklower  */
32045163Ssklower dprint(unit, pdma, addr)
32145163Ssklower register struct pdma *pdma;
32245163Ssklower register struct dpdevice *addr;
32345163Ssklower {
32445166Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
32545228Ssklower 	short rdsr = addr->dprdsr, rcsr;
32645163Ssklower 
32745228Ssklower 	dpstat.rint++;
32845228Ssklower 	splx(dp->dp_ipl);
32945166Ssklower 	if (rdsr & DP_RSM) { /* Received Start of Message */
33045166Ssklower 		dp->dp_ibuf[0] = rdsr & DP_RBUF;
33145163Ssklower 		pdma->p_mem = dp->dp_ibuf + 1;
33245166Ssklower 		dp->dp_flags &= ~DPF_FLUSH;
33345163Ssklower 		return;
33445163Ssklower 	}
33545166Ssklower 	if (rdsr & DP_REM) { /* Received End of Message */
33645166Ssklower 		if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
33745166Ssklower 			dp->dp_if.if_ierrors++;
33845228Ssklower 		} else
33945228Ssklower 			dpinput(&dp->dp_if,
34045228Ssklower 				pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf);
34145228Ssklower 		pdma->p_mem = pdma->p_end;
34245228Ssklower 		dp->dp_flags &= ~ DPF_FLUSH;
34345228Ssklower 		return;
34445228Ssklower 	}
34545228Ssklower 	if (rdsr & DP_ROVR) {
34645228Ssklower 		dp->dp_flags |= DPF_FLUSH;
34745228Ssklower 		return;
34845228Ssklower 	}
34945228Ssklower 	rcsr = pdma->p_arg;
35045228Ssklower 	if (rcsr & DP_MSC) {
35145228Ssklower 		dpstat.mchange++;
35245228Ssklower 		if (0 == (rcsr & DP_DSR)) {
35345228Ssklower 			log(LOG_DEBUG, "dp%d: lost modem\n", unit);
35445228Ssklower 			dpdown(unit);
35545163Ssklower 		}
35645163Ssklower 		return;
35745163Ssklower 	}
35845163Ssklower 	dp->dp_flags |= DPF_FLUSH;
35945163Ssklower 	if (pdma->p_mem != pdma->p_end)
36045166Ssklower 		log("dp%d: unexplained receiver interrupt\n", unit);
36145163Ssklower }
36245228Ssklower struct timeval dp_xt;
36345163Ssklower 
36445163Ssklower /*
36545163Ssklower  * Transmit complete or error interrupt
36645163Ssklower  */
36745163Ssklower dpxint(unit, pdma, addr)
36845163Ssklower register struct pdma *pdma;
36945163Ssklower register struct dpdevice *addr;
37045163Ssklower {
37145166Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
37245228Ssklower 	int s;
37345163Ssklower 
37445228Ssklower 	splx(dp->dp_ipl);
37545228Ssklower 	dpstat.xint++;
37645163Ssklower 	if (addr->dptdsr & DP_XERR) {
37745163Ssklower 		log("if_dp%d: data late\n", unit);
37845163Ssklower 	restart:
37945163Ssklower 		pdma->p_mem = dp->dp_obuf;
38045163Ssklower 		addr->dptdsr = DP_XSM;
38145228Ssklower 		dp->dp_if.if_oerrors++;
38245163Ssklower 		return;
38345163Ssklower 	}
38445163Ssklower 	switch (dp->dp_ostate) {
38545163Ssklower 
38645163Ssklower 	case DPS_ACTIVE:
38745163Ssklower 		if (pdma->p_mem != pdma->p_end) {
38845228Ssklower 			log("if_dp%d: misc error in dpxint\n", unit);
38945163Ssklower 			goto restart;
39045163Ssklower 		}
39145163Ssklower 		addr->dptdsr = DP_XEM;
39245163Ssklower 		dp->dp_ostate = DPS_XEM;
39345163Ssklower 		break;
39445163Ssklower 
39545163Ssklower 	case DPS_XEM:
39645228Ssklower 		dp->dp_if.if_opackets++;
39745163Ssklower 		dp->dp_if.if_flags &= ~IFF_OACTIVE;
39845228Ssklower s = splclock();
39945228Ssklower dp_xt = time;
40045228Ssklower timevalsub(&dp_xt, &dp->dp_xt);
40145228Ssklower splx(s);
40245163Ssklower 		if (dp->dp_if.if_snd.ifq_len)
40345163Ssklower 			dpstart(&dp->dp_if);
40445163Ssklower 		else {
40545163Ssklower 			addr->dpclr = 0;
40645163Ssklower 			dp->dp_ostate = DPS_IDLE;
40745163Ssklower 		}
40845163Ssklower 		break;
40945163Ssklower 
41045163Ssklower 	default:
41145163Ssklower 		log("if_dp%d: impossible state in dpxint\n");
41245163Ssklower 	}
41345163Ssklower }
41445163Ssklower /*
41545163Ssklower  * Routine to copy from device buffer into mbufs.
41645163Ssklower  *
41745163Ssklower  * Warning: This makes the fairly safe assumption that
41845163Ssklower  * mbufs have even lengths.
41945163Ssklower  */
42045163Ssklower struct mbuf *
42145163Ssklower dpget(rxbuf, totlen, off, ifp)
42245163Ssklower 	caddr_t rxbuf;
42345163Ssklower 	int totlen, off;
42445163Ssklower 	struct ifnet *ifp;
42545163Ssklower {
42645163Ssklower 	register caddr_t cp;
42745163Ssklower 	register struct mbuf *m;
42845163Ssklower 	struct mbuf *top = 0, **mp = ⊤
42945163Ssklower 	int len;
43045163Ssklower 	caddr_t packet_end;
43145163Ssklower 
43245163Ssklower 	cp = rxbuf;
43345163Ssklower 	packet_end = cp + totlen;
43445163Ssklower 	if (off) {
43545163Ssklower 		off += 2 * sizeof(u_short);
43645163Ssklower 		totlen -= 2 *sizeof(u_short);
43745163Ssklower 		cp = rxbuf + off;
43845163Ssklower 	}
43945163Ssklower 
44045163Ssklower 	MGETHDR(m, M_DONTWAIT, MT_DATA);
44145163Ssklower 	if (m == 0)
44245163Ssklower 		return (0);
44345163Ssklower 	m->m_pkthdr.rcvif = ifp;
44445163Ssklower 	m->m_pkthdr.len = totlen;
44545163Ssklower 	m->m_len = MHLEN;
44645163Ssklower 
44745163Ssklower 	while (totlen > 0) {
44845163Ssklower 		if (top) {
44945163Ssklower 			MGET(m, M_DONTWAIT, MT_DATA);
45045163Ssklower 			if (m == 0) {
45145163Ssklower 				m_freem(top);
45245163Ssklower 				return (0);
45345163Ssklower 			}
45445163Ssklower 			m->m_len = MLEN;
45545163Ssklower 		}
45645163Ssklower 		len = min(totlen, (packet_end - cp));
45745163Ssklower 		if (len >= MINCLSIZE) {
45845163Ssklower 			MCLGET(m, M_DONTWAIT);
45945163Ssklower 			if (m->m_flags & M_EXT)
46045163Ssklower 				m->m_len = len = min(len, MCLBYTES);
46145163Ssklower 			else
46245163Ssklower 				len = m->m_len;
46345163Ssklower 		} else {
46445163Ssklower 			/*
46545163Ssklower 			 * Place initial small packet/header at end of mbuf.
46645163Ssklower 			 */
46745163Ssklower 			if (len < m->m_len) {
46845163Ssklower 				if (top == 0 && len + max_linkhdr <= m->m_len)
46945163Ssklower 					m->m_data += max_linkhdr;
47045163Ssklower 				m->m_len = len;
47145163Ssklower 			} else
47245163Ssklower 				len = m->m_len;
47345163Ssklower 		}
47445163Ssklower 		bcopy(cp, mtod(m, caddr_t), (u_int)len);
47545163Ssklower 		*mp = m;
47645163Ssklower 		mp = &m->m_next;
47745163Ssklower 		totlen -= len;
47845163Ssklower 		cp += len;
47945163Ssklower 		if (cp == packet_end)
48045163Ssklower 			cp = rxbuf;
48145163Ssklower 	}
48245163Ssklower 	return (top);
48345163Ssklower }
48445163Ssklower 
48545228Ssklower dpinput(ifp, len, buffer)
48645228Ssklower register struct ifnet *ifp;
48745163Ssklower caddr_t buffer;
48845163Ssklower {
48945163Ssklower 	register struct ifqueue *inq;
49045163Ssklower 	register struct mbuf *m;
49145228Ssklower 	extern struct ifqueue hdintrq, ipintrq;
49245228Ssklower 	int netisr;
49345163Ssklower 
49445228Ssklower 	ifp->if_ipackets++;
49545228Ssklower     {
49645228Ssklower 	register struct ifaddr *ifa = ifp->if_addrlist;
49745228Ssklower 	register u_char *cp = (u_char *)buffer;
49845228Ssklower 
49945228Ssklower 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
50045228Ssklower 		if (ifa->ifa_addr->sa_family != AF_LINK)
50145228Ssklower 			break;
50245228Ssklower 	if (cp[0] == 0xff && cp[1] == 0x3) {
50345228Ssklower 		/* This is a UI HDLC Packet, so we'll assume PPP
50445228Ssklower 		   protocol.  for now, IP only. */
50545228Ssklower 		buffer += 4;
50645228Ssklower 		len -= 4;
50745228Ssklower 		inq = &ipintrq;
50845228Ssklower 		netisr = NETISR_IP;
50945228Ssklower 	} else {
51045228Ssklower 		inq = &hdintrq;
51145228Ssklower 		netisr = NETISR_CCITT;
51245228Ssklower 	}
51345228Ssklower     }
51445228Ssklower 	if (len <= 0)
51545163Ssklower 		return;
51645163Ssklower 
51745163Ssklower 	m = dpget(buffer, len , 0, ifp);
51845163Ssklower 	if (m == 0)
51945163Ssklower 		return;
52045163Ssklower 
52145163Ssklower 	if(IF_QFULL(inq)) {
52245163Ssklower 		IF_DROP(inq);
52345163Ssklower 		m_freem(m);
52445163Ssklower 	} else {
52545163Ssklower 		IF_ENQUEUE(inq, m);
52645228Ssklower 		schednetisr(netisr);
52745163Ssklower 	}
52845163Ssklower }
52945163Ssklower 
53045163Ssklower /*
53145163Ssklower  * Process an ioctl request.
53245163Ssklower  */
53345163Ssklower dpioctl(ifp, cmd, data)
53445163Ssklower 	register struct ifnet *ifp;
53545163Ssklower 	int cmd;
53645163Ssklower 	caddr_t data;
53745163Ssklower {
53845163Ssklower 	register struct ifaddr *ifa = (struct ifaddr *)data;
53945163Ssklower 	int s = splimp(), error = 0;
54045166Ssklower 	struct dp_softc *dp = &dp_softc[ifp->if_unit];
54145163Ssklower 
54245228Ssklower 	dpstat.ioctl++;
54345163Ssklower 	switch (cmd) {
54445163Ssklower 
54545163Ssklower 	case SIOCSIFADDR:
54645163Ssklower 		ifp->if_flags |= IFF_UP;
54745163Ssklower 		switch (ifa->ifa_addr->sa_family) {
54845228Ssklower 		case AF_INET:
54945228Ssklower 			ifp->if_output = dptestoutput;
55045163Ssklower 		default:
55145163Ssklower 			dpinit(ifp->if_unit);
55245163Ssklower 			break;
55345163Ssklower 		}
55445163Ssklower 		break;
55545228Ssklower #ifdef CCITT
55645228Ssklower 	case SIOCSIFCONF_X25:
55745228Ssklower 		ifp->if_flags |= IFF_UP;
55845228Ssklower 		ifp->if_output = x25_ifoutput;
55945228Ssklower 		error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
56045228Ssklower 		if (error == 0)
56145228Ssklower 			dpinit(ifp->if_unit);
56245228Ssklower 		break;
56345228Ssklower #endif
56445163Ssklower 
56545228Ssklower 	case SIOCSIFFLAGS:
56645228Ssklower 		if ((ifp->if_flags & IFF_UP) == 0 &&
56745228Ssklower 		    (ifp->if_flags & IFF_RUNNING))
56845228Ssklower 			dpdown(ifp->if_unit);
56945228Ssklower 		else if (ifp->if_flags & IFF_UP &&
57045228Ssklower 		    (ifp->if_flags & IFF_RUNNING) == 0)
57145228Ssklower 			dpinit(ifp->if_unit);
57245228Ssklower 		break;
57345163Ssklower 
57445228Ssklower 
57545163Ssklower 	default:
57645163Ssklower 		error = EINVAL;
57745163Ssklower 	}
57845163Ssklower 	splx(s);
57945163Ssklower 	return (error);
58045163Ssklower }
58145163Ssklower /*
58245163Ssklower  * Reset a device and mark down.
58345163Ssklower  * Flush output queue and drop queue limit.
58445163Ssklower  */
58545163Ssklower dpdown(unit)
586*45236Ssklower int unit;
58745163Ssklower {
588*45236Ssklower 
58945163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
590*45236Ssklower 	register struct dpdevice *addr = dp->dp_addr;
59145163Ssklower 
59245228Ssklower 	dpstat.down++;
59345163Ssklower 	if_qflush(&dp->dp_if.if_snd);
594*45236Ssklower 	dp->dp_flags = 0;
595*45236Ssklower 	dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
596*45236Ssklower 
597*45236Ssklower 	addr->dpclr = DP_CLR;
598*45236Ssklower 	DELAY(1000);
599*45236Ssklower 	addr->dpsar = 0;
600*45236Ssklower 	addr->dprcsr = 0;
60145163Ssklower }
60245163Ssklower 
60345163Ssklower /*
60445163Ssklower  * Watchdog timeout to see that transmitted packets don't
60545163Ssklower  * lose interrupts.  The device has to be online (the first
60645163Ssklower  * transmission may block until the other side comes up).
60745163Ssklower  */
60845163Ssklower dptimeout(unit)
60945163Ssklower 	int unit;
61045163Ssklower {
61145163Ssklower 	register struct dp_softc *dp;
61245163Ssklower 
61345228Ssklower 	/* currently not armed */
61445228Ssklower 	dpstat.timeout++;
61545163Ssklower 	dp = &dp_softc[unit];
61645228Ssklower 	if (dp->dp_if.if_flags & IFF_OACTIVE) {
61745228Ssklower 		dpstart(&dp->dp_if);
61845163Ssklower 	}
61945163Ssklower }
62045228Ssklower /*
62145228Ssklower  * For debugging loopback activity.
62245228Ssklower  */
62345228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 };
62445228Ssklower int dp_louts;
62545228Ssklower 
62645228Ssklower dptestoutput(ifp, m, dst, rt)
62745228Ssklower register struct ifnet *ifp;
62845228Ssklower register struct mbuf *m;
62945228Ssklower struct sockaddr *dst;
63045228Ssklower struct rtentry *rt;
63145228Ssklower {
63245228Ssklower 	/*
63345228Ssklower 	 * Queue message on interface, and start output if interface
63445228Ssklower 	 * not yet active.
63545228Ssklower 	 */
63645228Ssklower 	int s = splimp(), error = 0;
63745228Ssklower 	dp_louts++;
63845228Ssklower 	M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
63945228Ssklower 	if (m == 0) {
64045228Ssklower 		splx(s);
64145228Ssklower 		return ENOBUFS;
64245228Ssklower 	}
64345228Ssklower 	bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
64445228Ssklower 	if (IF_QFULL(&ifp->if_snd)) {
64545228Ssklower 		IF_DROP(&ifp->if_snd);
64645228Ssklower 	    /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
64745228Ssklower 			ifp->if_name, ifp->if_unit);*/
64845228Ssklower 		m_freem(m);
64945228Ssklower 		error = ENOBUFS;
65045228Ssklower 	} else {
65145228Ssklower 		IF_ENQUEUE(&ifp->if_snd, m);
65245228Ssklower 		if ((ifp->if_flags & IFF_OACTIVE) == 0)
65345228Ssklower 			(*ifp->if_start)(ifp);
65445228Ssklower 	}
65545228Ssklower 	splx(s);
65645228Ssklower 	return (error);
65745228Ssklower }
65845228Ssklower 
65945163Ssklower #endif
660