xref: /csrg-svn/sys/vax/if/if_dp.c (revision 45228)
145163Ssklower /*
245163Ssklower  * Copyright (c) 1990 Regents of the University of California.
345163Ssklower  * All rights reserved.
445163Ssklower  *
545163Ssklower  * %sccs.include.redist.c%
645163Ssklower  *
7*45228Ssklower  *	@(#)if_dp.c	7.3 (Berkeley) 09/12/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"
36*45228Ssklower #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 
50*45228Ssklower #define	dzdevice dpdevice
5145163Ssklower #include "../vaxuba/pdma.h"
5245166Ssklower #include "../vaxuba/ubavar.h"
5345163Ssklower 
54*45228Ssklower #include "../netccitt/x25.h"
55*45228Ssklower #include "../netccitt/pk.h"
56*45228Ssklower #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();
64*45228Ssklower 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 /*
73*45228Ssklower  * debug info
74*45228Ssklower  */
75*45228Ssklower struct	dpstat {
76*45228Ssklower 	long	start;
77*45228Ssklower 	long	nohdr;
78*45228Ssklower 	long	init;
79*45228Ssklower 	long	rint;
80*45228Ssklower 	long	xint;
81*45228Ssklower 	long	reset;
82*45228Ssklower 	long	ioctl;
83*45228Ssklower 	long	down;
84*45228Ssklower 	long	mchange;
85*45228Ssklower 	long	timeout;
86*45228Ssklower } dpstat;
87*45228Ssklower /*
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 */
108*45228Ssklower 	int	dp_ipl;
10945163Ssklower 	short	dp_iused;		/* input buffers given to DP */
11045163Ssklower 	short	dp_flags;		/* flags */
111*45228Ssklower #define DPF_RUNNING	0x01		/* device initialized */
112*45228Ssklower #define DPF_ONLINE	0x02		/* device running (had a RDYO) */
113*45228Ssklower #define DPF_RESTART	0x04		/* software restart in progress */
114*45228Ssklower #define DPF_FLUSH	0x08		/* had a ROVR, flush ipkt when done */
11545163Ssklower 	short	dp_ostate;		/* restarting, etc. */
11645163Ssklower 	short	dp_istate;		/* not sure this is necessary */
11745163Ssklower #define DPS_IDLE	0
11845163Ssklower #define DPS_RESTART	1
11945163Ssklower #define DPS_ACTIVE	2
12045163Ssklower #define DPS_XEM		3		/* transmitting CRC, etc. */
12145163Ssklower 	int	dp_errors[4];		/* non-fatal error counters */
12245163Ssklower #define dp_datck dp_errors[0]
12345163Ssklower #define dp_timeo dp_errors[1]
12445163Ssklower #define dp_nobuf dp_errors[2]
12545163Ssklower #define dp_disc  dp_errors[3]
126*45228Ssklower 	struct timeval	dp_xt;			/* start of last transmission */
12745163Ssklower 	char	dp_obuf[DP_MTU+8];
12845166Ssklower 	char	dp_ibuf[DP_MTU+8];
12945163Ssklower } dp_softc[NDP];
13045163Ssklower 
13145163Ssklower dpprobe(reg, ui)
13245163Ssklower 	caddr_t reg;
13345163Ssklower 	struct	uba_device *ui;
13445163Ssklower {
13545163Ssklower 	register int br, cvec;
13645163Ssklower 	register struct dpdevice *addr = (struct dpdevice *)reg;
13745163Ssklower 	register int i;
13845163Ssklower 
13945163Ssklower #ifdef lint
14045163Ssklower 	br = 0; cvec = br; br = cvec;
14145163Ssklower 	dprint(0); dpxint(0);
14245163Ssklower #endif
143*45228Ssklower 	(void) spl6();
14445163Ssklower 	addr->dpclr = DP_CLR;
14545163Ssklower 	addr->dpclr = DP_XIE|DP_XE;
14645163Ssklower 	DELAY(100000);
147*45228Ssklower 	dp_softc[ui->ui_unit].dp_ipl = br = qbgetpri();
14845163Ssklower 	addr->dpclr = 0;
149*45228Ssklower 	if (cvec && cvec != 0x200){
150*45228Ssklower 		cvec -= 4;
151*45228Ssklower 	}
15245163Ssklower 	return (1);
15345163Ssklower }
15445163Ssklower 
15545163Ssklower /*
15645163Ssklower  * Interface exists: make available by filling in network interface
15745163Ssklower  * record.  System will initialize the interface when it is ready
15845163Ssklower  * to accept packets.
15945163Ssklower  */
16045163Ssklower dpattach(ui)
16145163Ssklower 	register struct uba_device *ui;
16245163Ssklower {
16345163Ssklower 	register struct dp_softc *dp = &dp_softc[ui->ui_unit];
16445163Ssklower 
16545163Ssklower 	dp->dp_if.if_unit = ui->ui_unit;
16645163Ssklower 	dp->dp_if.if_name = "dp";
16745163Ssklower 	dp->dp_if.if_mtu = DP_MTU;
16845163Ssklower 	dp->dp_if.if_init = dpinit;
16945163Ssklower 	dp->dp_if.if_output = x25_ifoutput;
17045163Ssklower 	dp->dp_if.if_start = dpstart;
17145163Ssklower 	dp->dp_if.if_ioctl = dpioctl;
17245163Ssklower 	dp->dp_if.if_reset = dpreset;
17345163Ssklower 	dp->dp_if.if_watchdog = dptimeout;
174*45228Ssklower 	dp->dp_if.if_flags = 0;
17545163Ssklower 	if_attach(&dp->dp_if);
17645163Ssklower }
17745163Ssklower 
17845163Ssklower /*
17945163Ssklower  * Reset of interface after UNIBUS reset.
18045163Ssklower  * If interface is on specified UBA, reset its state.
18145163Ssklower  */
18245163Ssklower dpreset(unit, uban)
18345163Ssklower 	int unit, uban;
18445163Ssklower {
18545163Ssklower 	register struct uba_device *ui;
18645163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
18745163Ssklower 	register struct dpdevice *addr;
18845163Ssklower 
189*45228Ssklower 	dpstat.reset++;
19045163Ssklower 	if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
19145163Ssklower 	    ui->ui_ubanum != uban)
19245163Ssklower 		return;
19345163Ssklower 	printf(" dp%d", unit);
19445166Ssklower 	dp->dp_flags = 0;
19545163Ssklower 	dp->dp_if.if_flags &= ~IFF_RUNNING;
19645166Ssklower 	addr = (struct dpdevice *)ui->ui_addr;
19745163Ssklower 	addr->dpclr = DP_CLR;
198*45228Ssklower 	DELAY(1000);
19945163Ssklower 	addr->dpsar = 0;
20045163Ssklower 	addr->dprcsr = 0;
20145163Ssklower 	dpinit(unit);
20245163Ssklower }
20345163Ssklower 
20445163Ssklower /*
20545163Ssklower  * Initialization of interface.
20645163Ssklower  */
20745163Ssklower dpinit(unit)
20845163Ssklower 	int unit;
20945163Ssklower {
21045163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
21145163Ssklower 	register struct uba_device *ui = dpinfo[unit];
21245163Ssklower 	register struct dpdevice *addr;
213*45228Ssklower 	register struct ifaddr *ifa;
214*45228Ssklower 	register struct pdma *pdp = &dppdma[unit*2];
215*45228Ssklower 	int base, s;
21645163Ssklower 
217*45228Ssklower 	dpstat.init++;
21845163Ssklower 	/*
21945163Ssklower 	 * Check to see that an address has been set.
22045163Ssklower 	 */
221*45228Ssklower 	for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
22245163Ssklower 		if (ifa->ifa_addr->sa_family != AF_LINK)
22345163Ssklower 			break;
22445163Ssklower 	if (ifa == (struct ifaddr *) 0)
22545163Ssklower 		return;
22645163Ssklower 
227*45228Ssklower 	addr = (struct dpdevice *)ui->ui_addr;
228*45228Ssklower 	s = splimp();
22945163Ssklower 	dp->dp_iused = 0;
23045163Ssklower 	dp->dp_istate = dp->dp_ostate = DPS_IDLE;
231*45228Ssklower 	dp->dp_if.if_flags |= IFF_RUNNING;
232*45228Ssklower 	dp->dp_if.if_flags &= ~IFF_OACTIVE;
233*45228Ssklower 
234*45228Ssklower 	pdp->p_addr = addr;
235*45228Ssklower 	pdp->p_fcn = dpxint;
236*45228Ssklower 	pdp->p_mem = pdp->p_end = dp->dp_obuf;
237*45228Ssklower 	pdp++;
238*45228Ssklower 	pdp->p_addr = addr;
239*45228Ssklower 	pdp->p_fcn = dprint;
240*45228Ssklower 	/* force initial interrupt to come to dprint */
241*45228Ssklower 	pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
242*45228Ssklower 
243*45228Ssklower 	addr->dpclr = DP_CLR;
244*45228Ssklower 	DELAY(1000);
24545163Ssklower 	addr->dpclr = 0;
246*45228Ssklower 	DELAY(1000);
247*45228Ssklower 	/* DP_ATA = 0, DP_CHRM = 0,
248*45228Ssklower 			    CRC = CCIIT, initially all ones, 2nd addr = 0 */
249*45228Ssklower 	addr->dpsar = 0;
250*45228Ssklower 	/* enable receive interrupt */
251*45228Ssklower 	addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
252*45228Ssklower 	dpstart(&dp->dp_if);
25345163Ssklower 	splx(s);
25445163Ssklower }
25545163Ssklower 
256*45228Ssklower int dpMessy = 0;
25745163Ssklower /*
25845163Ssklower  * Start output on interface.  Get another datagram
25945163Ssklower  * to send from the interface queue and map it to
26045163Ssklower  * the interface before starting output.
26145163Ssklower  *
26245163Ssklower  */
26345163Ssklower dpstart(ifp)
26445163Ssklower 	struct ifnet *ifp;
26545163Ssklower {
266*45228Ssklower 	int s, unit = ifp->if_unit, error = 0, len;
26745163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
26845166Ssklower 	register struct dpdevice *addr =
26945166Ssklower 				(struct dpdevice *)(dpinfo[unit]->ui_addr);
27045163Ssklower 	register struct mbuf *m;
27145163Ssklower 	register char *cp;
27245163Ssklower 	char *cplim;
27345163Ssklower 
27445163Ssklower 	/*
27545163Ssklower 	 * If already doing output, go away and depend on transmit
27645163Ssklower 	 * complete or error.
27745163Ssklower 	 */
278*45228Ssklower 	dpstat.start++;
279*45228Ssklower 	if (dp->dp_if.if_flags & IFF_OACTIVE)
280*45228Ssklower 		goto out;
28145163Ssklower 	IF_DEQUEUE(&dp->dp_if.if_snd, m);
28245163Ssklower 	if (m == 0)
283*45228Ssklower 		goto out;
284*45228Ssklower 	dp->dp_if.if_collisions++;
285*45228Ssklower 	if (m->m_flags & M_PKTHDR)
286*45228Ssklower 		len = m->m_pkthdr.len;
287*45228Ssklower 	else {
288*45228Ssklower 		struct mbuf *m0 = m;
289*45228Ssklower 		for (len = 0; m; m = m->m_next)
290*45228Ssklower 			len += m->m_len;
291*45228Ssklower 		m = m0;
292*45228Ssklower 		dpstat.nohdr++;
293*45228Ssklower 	}
294*45228Ssklower 	if (len == 0)
295*45228Ssklower 		goto out;
296*45228Ssklower 	if (len > DP_MTU) {
297*45228Ssklower 		error = EINVAL;
298*45228Ssklower 		goto out;
299*45228Ssklower 	}
300*45228Ssklower 	cp = dp->dp_obuf;
301*45228Ssklower 	dppdma[2*unit].p_mem = cp + 1;
30245163Ssklower 	while (m) {
30345163Ssklower 		struct mbuf *n;
30445163Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len);
30545163Ssklower 		cp += m->m_len;
30645163Ssklower 		MFREE(m, n); m = n;
30745163Ssklower 	}
30845163Ssklower 	dppdma[2*unit].p_end = cp;
309*45228Ssklower 	if (dpMessy)
310*45228Ssklower 		printf("dp: len %d, start %x, end %x, first %x, next %x",
311*45228Ssklower 			len, dp->dp_obuf, cp, *(int *)dp->dp_obuf,
312*45228Ssklower 			1[(int *)dp->dp_obuf]);
31345163Ssklower 	dp->dp_if.if_flags |= IFF_OACTIVE;
31445163Ssklower 	dp->dp_ostate = DPS_ACTIVE;
315*45228Ssklower 	dp->dp_if.if_collisions--;
316*45228Ssklower dp->dp_xt = time;
317*45228Ssklower 	addr->dpclr = DP_XE | DP_XIE;
318*45228Ssklower 	addr->dptdsr = DP_XSM | (0xff & dp->dp_obuf[0]);
319*45228Ssklower out:
320*45228Ssklower 	return (error);
32145163Ssklower }
32245163Ssklower /*
32345163Ssklower  * Receive done or error interrupt
32445163Ssklower  */
32545163Ssklower dprint(unit, pdma, addr)
32645163Ssklower register struct pdma *pdma;
32745163Ssklower register struct dpdevice *addr;
32845163Ssklower {
32945166Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
330*45228Ssklower 	short rdsr = addr->dprdsr, rcsr;
33145163Ssklower 
332*45228Ssklower 	dpstat.rint++;
333*45228Ssklower 	splx(dp->dp_ipl);
33445166Ssklower 	if (rdsr & DP_RSM) { /* Received Start of Message */
33545166Ssklower 		dp->dp_ibuf[0] = rdsr & DP_RBUF;
33645163Ssklower 		pdma->p_mem = dp->dp_ibuf + 1;
33745166Ssklower 		dp->dp_flags &= ~DPF_FLUSH;
33845163Ssklower 		return;
33945163Ssklower 	}
34045166Ssklower 	if (rdsr & DP_REM) { /* Received End of Message */
34145166Ssklower 		if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
34245166Ssklower 			dp->dp_if.if_ierrors++;
343*45228Ssklower 		} else
344*45228Ssklower 			dpinput(&dp->dp_if,
345*45228Ssklower 				pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf);
346*45228Ssklower 		pdma->p_mem = pdma->p_end;
347*45228Ssklower 		dp->dp_flags &= ~ DPF_FLUSH;
348*45228Ssklower 		return;
349*45228Ssklower 	}
350*45228Ssklower 	if (rdsr & DP_ROVR) {
351*45228Ssklower 		dp->dp_flags |= DPF_FLUSH;
352*45228Ssklower 		return;
353*45228Ssklower 	}
354*45228Ssklower 	rcsr = pdma->p_arg;
355*45228Ssklower 	if (rcsr & DP_MSC) {
356*45228Ssklower 		dpstat.mchange++;
357*45228Ssklower 		if (0 == (rcsr & DP_DSR)) {
358*45228Ssklower 			log(LOG_DEBUG, "dp%d: lost modem\n", unit);
359*45228Ssklower 			dpdown(unit);
36045163Ssklower 		}
36145163Ssklower 		return;
36245163Ssklower 	}
36345163Ssklower 	dp->dp_flags |= DPF_FLUSH;
36445163Ssklower 	if (pdma->p_mem != pdma->p_end)
36545166Ssklower 		log("dp%d: unexplained receiver interrupt\n", unit);
36645163Ssklower }
367*45228Ssklower struct timeval dp_xt;
36845163Ssklower 
36945163Ssklower /*
37045163Ssklower  * Transmit complete or error interrupt
37145163Ssklower  */
37245163Ssklower dpxint(unit, pdma, addr)
37345163Ssklower register struct pdma *pdma;
37445163Ssklower register struct dpdevice *addr;
37545163Ssklower {
37645166Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
377*45228Ssklower 	int s;
37845163Ssklower 
379*45228Ssklower 	splx(dp->dp_ipl);
380*45228Ssklower 	dpstat.xint++;
38145163Ssklower 	if (addr->dptdsr & DP_XERR) {
38245163Ssklower 		log("if_dp%d: data late\n", unit);
38345163Ssklower 	restart:
38445163Ssklower 		pdma->p_mem = dp->dp_obuf;
38545163Ssklower 		addr->dptdsr = DP_XSM;
386*45228Ssklower 		dp->dp_if.if_oerrors++;
38745163Ssklower 		return;
38845163Ssklower 	}
38945163Ssklower 	switch (dp->dp_ostate) {
39045163Ssklower 
39145163Ssklower 	case DPS_ACTIVE:
39245163Ssklower 		if (pdma->p_mem != pdma->p_end) {
393*45228Ssklower 			log("if_dp%d: misc error in dpxint\n", unit);
39445163Ssklower 			goto restart;
39545163Ssklower 		}
39645163Ssklower 		addr->dptdsr = DP_XEM;
39745163Ssklower 		dp->dp_ostate = DPS_XEM;
39845163Ssklower 		break;
39945163Ssklower 
40045163Ssklower 	case DPS_XEM:
401*45228Ssklower 		dp->dp_if.if_opackets++;
40245163Ssklower 		dp->dp_if.if_flags &= ~IFF_OACTIVE;
403*45228Ssklower s = splclock();
404*45228Ssklower dp_xt = time;
405*45228Ssklower timevalsub(&dp_xt, &dp->dp_xt);
406*45228Ssklower splx(s);
40745163Ssklower 		if (dp->dp_if.if_snd.ifq_len)
40845163Ssklower 			dpstart(&dp->dp_if);
40945163Ssklower 		else {
41045163Ssklower 			addr->dpclr = 0;
41145163Ssklower 			dp->dp_ostate = DPS_IDLE;
41245163Ssklower 		}
41345163Ssklower 		break;
41445163Ssklower 
41545163Ssklower 	default:
41645163Ssklower 		log("if_dp%d: impossible state in dpxint\n");
41745163Ssklower 	}
41845163Ssklower }
41945163Ssklower /*
42045163Ssklower  * Routine to copy from device buffer into mbufs.
42145163Ssklower  *
42245163Ssklower  * Warning: This makes the fairly safe assumption that
42345163Ssklower  * mbufs have even lengths.
42445163Ssklower  */
42545163Ssklower struct mbuf *
42645163Ssklower dpget(rxbuf, totlen, off, ifp)
42745163Ssklower 	caddr_t rxbuf;
42845163Ssklower 	int totlen, off;
42945163Ssklower 	struct ifnet *ifp;
43045163Ssklower {
43145163Ssklower 	register caddr_t cp;
43245163Ssklower 	register struct mbuf *m;
43345163Ssklower 	struct mbuf *top = 0, **mp = ⊤
43445163Ssklower 	int len;
43545163Ssklower 	caddr_t packet_end;
43645163Ssklower 
43745163Ssklower 	cp = rxbuf;
43845163Ssklower 	packet_end = cp + totlen;
43945163Ssklower 	if (off) {
44045163Ssklower 		off += 2 * sizeof(u_short);
44145163Ssklower 		totlen -= 2 *sizeof(u_short);
44245163Ssklower 		cp = rxbuf + off;
44345163Ssklower 	}
44445163Ssklower 
44545163Ssklower 	MGETHDR(m, M_DONTWAIT, MT_DATA);
44645163Ssklower 	if (m == 0)
44745163Ssklower 		return (0);
44845163Ssklower 	m->m_pkthdr.rcvif = ifp;
44945163Ssklower 	m->m_pkthdr.len = totlen;
45045163Ssklower 	m->m_len = MHLEN;
45145163Ssklower 
45245163Ssklower 	while (totlen > 0) {
45345163Ssklower 		if (top) {
45445163Ssklower 			MGET(m, M_DONTWAIT, MT_DATA);
45545163Ssklower 			if (m == 0) {
45645163Ssklower 				m_freem(top);
45745163Ssklower 				return (0);
45845163Ssklower 			}
45945163Ssklower 			m->m_len = MLEN;
46045163Ssklower 		}
46145163Ssklower 		len = min(totlen, (packet_end - cp));
46245163Ssklower 		if (len >= MINCLSIZE) {
46345163Ssklower 			MCLGET(m, M_DONTWAIT);
46445163Ssklower 			if (m->m_flags & M_EXT)
46545163Ssklower 				m->m_len = len = min(len, MCLBYTES);
46645163Ssklower 			else
46745163Ssklower 				len = m->m_len;
46845163Ssklower 		} else {
46945163Ssklower 			/*
47045163Ssklower 			 * Place initial small packet/header at end of mbuf.
47145163Ssklower 			 */
47245163Ssklower 			if (len < m->m_len) {
47345163Ssklower 				if (top == 0 && len + max_linkhdr <= m->m_len)
47445163Ssklower 					m->m_data += max_linkhdr;
47545163Ssklower 				m->m_len = len;
47645163Ssklower 			} else
47745163Ssklower 				len = m->m_len;
47845163Ssklower 		}
47945163Ssklower 		bcopy(cp, mtod(m, caddr_t), (u_int)len);
48045163Ssklower 		*mp = m;
48145163Ssklower 		mp = &m->m_next;
48245163Ssklower 		totlen -= len;
48345163Ssklower 		cp += len;
48445163Ssklower 		if (cp == packet_end)
48545163Ssklower 			cp = rxbuf;
48645163Ssklower 	}
48745163Ssklower 	return (top);
48845163Ssklower }
48945163Ssklower 
490*45228Ssklower dpinput(ifp, len, buffer)
491*45228Ssklower register struct ifnet *ifp;
49245163Ssklower caddr_t buffer;
49345163Ssklower {
49445163Ssklower 	register struct ifqueue *inq;
49545163Ssklower 	register struct mbuf *m;
496*45228Ssklower 	extern struct ifqueue hdintrq, ipintrq;
497*45228Ssklower 	int netisr;
49845163Ssklower 
499*45228Ssklower 	ifp->if_ipackets++;
500*45228Ssklower     {
501*45228Ssklower 	register struct ifaddr *ifa = ifp->if_addrlist;
502*45228Ssklower 	register u_char *cp = (u_char *)buffer;
503*45228Ssklower 
504*45228Ssklower 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
505*45228Ssklower 		if (ifa->ifa_addr->sa_family != AF_LINK)
506*45228Ssklower 			break;
507*45228Ssklower 	if (cp[0] == 0xff && cp[1] == 0x3) {
508*45228Ssklower 		/* This is a UI HDLC Packet, so we'll assume PPP
509*45228Ssklower 		   protocol.  for now, IP only. */
510*45228Ssklower 		buffer += 4;
511*45228Ssklower 		len -= 4;
512*45228Ssklower 		inq = &ipintrq;
513*45228Ssklower 		netisr = NETISR_IP;
514*45228Ssklower 	} else {
515*45228Ssklower 		inq = &hdintrq;
516*45228Ssklower 		netisr = NETISR_CCITT;
517*45228Ssklower 	}
518*45228Ssklower     }
519*45228Ssklower 	if (len <= 0)
52045163Ssklower 		return;
52145163Ssklower 
52245163Ssklower 	m = dpget(buffer, len , 0, ifp);
52345163Ssklower 	if (m == 0)
52445163Ssklower 		return;
52545163Ssklower 
52645163Ssklower 	if(IF_QFULL(inq)) {
52745163Ssklower 		IF_DROP(inq);
52845163Ssklower 		m_freem(m);
52945163Ssklower 	} else {
53045163Ssklower 		IF_ENQUEUE(inq, m);
531*45228Ssklower 		schednetisr(netisr);
53245163Ssklower 	}
53345163Ssklower }
53445163Ssklower 
53545163Ssklower /*
53645163Ssklower  * Process an ioctl request.
53745163Ssklower  */
53845163Ssklower dpioctl(ifp, cmd, data)
53945163Ssklower 	register struct ifnet *ifp;
54045163Ssklower 	int cmd;
54145163Ssklower 	caddr_t data;
54245163Ssklower {
54345163Ssklower 	register struct ifaddr *ifa = (struct ifaddr *)data;
54445163Ssklower 	int s = splimp(), error = 0;
54545166Ssklower 	struct dp_softc *dp = &dp_softc[ifp->if_unit];
54645163Ssklower 
547*45228Ssklower 	dpstat.ioctl++;
54845163Ssklower 	switch (cmd) {
54945163Ssklower 
55045163Ssklower 	case SIOCSIFADDR:
55145163Ssklower 		ifp->if_flags |= IFF_UP;
55245163Ssklower 		switch (ifa->ifa_addr->sa_family) {
553*45228Ssklower 		case AF_INET:
554*45228Ssklower 			ifp->if_output = dptestoutput;
55545163Ssklower 		default:
55645163Ssklower 			dpinit(ifp->if_unit);
55745163Ssklower 			break;
55845163Ssklower 		}
55945163Ssklower 		break;
560*45228Ssklower #ifdef CCITT
561*45228Ssklower 	case SIOCSIFCONF_X25:
562*45228Ssklower 		ifp->if_flags |= IFF_UP;
563*45228Ssklower 		ifp->if_output = x25_ifoutput;
564*45228Ssklower 		error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
565*45228Ssklower 		if (error == 0)
566*45228Ssklower 			dpinit(ifp->if_unit);
567*45228Ssklower 		break;
568*45228Ssklower #endif
56945163Ssklower 
570*45228Ssklower 	case SIOCSIFFLAGS:
571*45228Ssklower 		if ((ifp->if_flags & IFF_UP) == 0 &&
572*45228Ssklower 		    (ifp->if_flags & IFF_RUNNING))
573*45228Ssklower 			dpdown(ifp->if_unit);
574*45228Ssklower 		else if (ifp->if_flags & IFF_UP &&
575*45228Ssklower 		    (ifp->if_flags & IFF_RUNNING) == 0)
576*45228Ssklower 			dpinit(ifp->if_unit);
577*45228Ssklower 		break;
57845163Ssklower 
579*45228Ssklower 
58045163Ssklower 	default:
58145163Ssklower 		error = EINVAL;
58245163Ssklower 	}
58345163Ssklower 	splx(s);
58445163Ssklower 	return (error);
58545163Ssklower }
58645163Ssklower /*
58745163Ssklower  * Reset a device and mark down.
58845163Ssklower  * Flush output queue and drop queue limit.
58945163Ssklower  */
59045163Ssklower dpdown(unit)
59145163Ssklower 	int unit;
59245163Ssklower {
59345163Ssklower 	register struct dp_softc *dp = &dp_softc[unit];
59445163Ssklower 
595*45228Ssklower 	dpstat.down++;
59645163Ssklower 	if_qflush(&dp->dp_if.if_snd);
597*45228Ssklower 	dpreset(unit);
59845163Ssklower }
59945163Ssklower 
60045163Ssklower /*
60145163Ssklower  * Watchdog timeout to see that transmitted packets don't
60245163Ssklower  * lose interrupts.  The device has to be online (the first
60345163Ssklower  * transmission may block until the other side comes up).
60445163Ssklower  */
60545163Ssklower dptimeout(unit)
60645163Ssklower 	int unit;
60745163Ssklower {
60845163Ssklower 	register struct dp_softc *dp;
60945163Ssklower 
610*45228Ssklower 	/* currently not armed */
611*45228Ssklower 	dpstat.timeout++;
61245163Ssklower 	dp = &dp_softc[unit];
613*45228Ssklower 	if (dp->dp_if.if_flags & IFF_OACTIVE) {
614*45228Ssklower 		dpstart(&dp->dp_if);
61545163Ssklower 	}
61645163Ssklower }
617*45228Ssklower /*
618*45228Ssklower  * For debugging loopback activity.
619*45228Ssklower  */
620*45228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 };
621*45228Ssklower int dp_louts;
622*45228Ssklower 
623*45228Ssklower dptestoutput(ifp, m, dst, rt)
624*45228Ssklower register struct ifnet *ifp;
625*45228Ssklower register struct mbuf *m;
626*45228Ssklower struct sockaddr *dst;
627*45228Ssklower struct rtentry *rt;
628*45228Ssklower {
629*45228Ssklower 	/*
630*45228Ssklower 	 * Queue message on interface, and start output if interface
631*45228Ssklower 	 * not yet active.
632*45228Ssklower 	 */
633*45228Ssklower 	int s = splimp(), error = 0;
634*45228Ssklower 	dp_louts++;
635*45228Ssklower 	M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
636*45228Ssklower 	if (m == 0) {
637*45228Ssklower 		splx(s);
638*45228Ssklower 		return ENOBUFS;
639*45228Ssklower 	}
640*45228Ssklower 	bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
641*45228Ssklower 	if (IF_QFULL(&ifp->if_snd)) {
642*45228Ssklower 		IF_DROP(&ifp->if_snd);
643*45228Ssklower 	    /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
644*45228Ssklower 			ifp->if_name, ifp->if_unit);*/
645*45228Ssklower 		m_freem(m);
646*45228Ssklower 		error = ENOBUFS;
647*45228Ssklower 	} else {
648*45228Ssklower 		IF_ENQUEUE(&ifp->if_snd, m);
649*45228Ssklower 		if ((ifp->if_flags & IFF_OACTIVE) == 0)
650*45228Ssklower 			(*ifp->if_start)(ifp);
651*45228Ssklower 	}
652*45228Ssklower 	splx(s);
653*45228Ssklower 	return (error);
654*45228Ssklower }
655*45228Ssklower 
65645163Ssklower #endif
657