xref: /original-bsd/sys/vax/if/if_dp.c (revision fc06d0d2)
1 /*
2  * Copyright (c) 1990 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)if_dp.c	7.5 (Berkeley) 09/17/90
8  */
9 
10 #include "dp.h"
11 #if NDP > 0
12 
13 /*
14  * DPV-11 device driver, X.25 version
15  *
16  * Derived from dmc-11 driver:
17  *
18  *	Bill Nesheim
19  *	Cornell University
20  *
21  *	Lou Salkind
22  *	New York University
23  */
24 
25 /* #define DEBUG	/* for base table dump on fatal error */
26 
27 #include "machine/pte.h"
28 
29 #include "param.h"
30 #include "systm.h"
31 #include "mbuf.h"
32 #include "buf.h"
33 #include "ioctl.h"		/* must precede tty.h */
34 #include "protosw.h"
35 #include "socket.h"
36 #include "socketvar.h"
37 #include "syslog.h"
38 #include "vmmac.h"
39 #include "errno.h"
40 #include "time.h"
41 #include "kernel.h"
42 
43 #include "../net/if.h"
44 #include "../net/netisr.h"
45 #include "../net/route.h"
46 
47 #include "../vax/cpu.h"
48 #include "../vax/mtpr.h"
49 
50 #define	dzdevice dpdevice
51 #include "../vaxuba/pdma.h"
52 #include "../vaxuba/ubavar.h"
53 
54 #include "../netccitt/x25.h"
55 #include "../netccitt/pk.h"
56 #include "../netccitt/pk_var.h"
57 
58 #include "if_dpreg.h"
59 
60 /*
61  * Driver information for auto-configuration stuff.
62  */
63 int	dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
64 int	dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(), dptestoutput();
65 
66 struct	uba_device *dpinfo[NDP];
67 
68 u_short	dpstd[] = { 0 };
69 struct	uba_driver dpdriver =
70 	{ dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo };
71 
72 /*
73  * debug info
74  */
75 struct	dpstat {
76 	long	start;
77 	long	nohdr;
78 	long	init;
79 	long	rint;
80 	long	xint;
81 	long	reset;
82 	long	ioctl;
83 	long	down;
84 	long	mchange;
85 	long	timeout;
86 	long	rsm;
87 	long	rem;
88 	long	rsmchr;
89 	long	rga;
90 } dpstat;
91 /*
92  * Pdma structures for fast interrupts.
93  */
94 struct	pdma dppdma[2*NDP];
95 
96 /* error reporting intervals */
97 #define DPI_RPNBFS	50
98 #define DPI_RPDSC	1
99 #define DPI_RPTMO	10
100 #define DPI_RPDCK	10
101 
102 
103 /*
104  * DP software status per interface.
105  *
106  * Each interface is referenced by a network interface structure,
107  * dp_if, which the routing code uses to locate the interface.
108  * This structure contains the output queue for the interface, its address, ...
109  */
110 struct dp_softc {
111 	struct	ifnet dp_if;		/* network-visible interface */
112 	int	dp_ipl;
113 	struct	dpdevice *dp_addr;	/* dpcsr address */
114 	short	dp_iused;		/* input buffers given to DP */
115 	short	dp_flags;		/* flags */
116 #define DPF_RUNNING	0x01		/* device initialized */
117 #define DPF_ONLINE	0x02		/* device running (had a RDYO) */
118 #define DPF_RESTART	0x04		/* software restart in progress */
119 #define DPF_FLUSH	0x08		/* had a ROVR, flush ipkt when done */
120 	short	dp_ostate;		/* restarting, etc. */
121 	short	dp_istate;		/* not sure this is necessary */
122 #define DPS_IDLE	0
123 #define DPS_RESTART	1
124 #define DPS_ACTIVE	2
125 #define DPS_XEM		3		/* transmitting CRC, etc. */
126 	int	dp_errors[4];		/* non-fatal error counters */
127 #define dp_datck dp_errors[0]
128 #define dp_timeo dp_errors[1]
129 #define dp_nobuf dp_errors[2]
130 #define dp_disc  dp_errors[3]
131 	char	dp_obuf[DP_MTU+8];
132 	char	dp_ibuf[DP_MTU+8];
133 } dp_softc[NDP];
134 
135 dpprobe(reg, ui)
136 	caddr_t reg;
137 	struct	uba_device *ui;
138 {
139 	register int br, cvec;
140 	register struct dpdevice *addr = (struct dpdevice *)reg;
141 	register int unit = ui->ui_unit;
142 
143 #ifdef lint
144 	br = 0; cvec = br; br = cvec;
145 	dprint(0); dpxint(0);
146 #endif
147 	(void) spl6();
148 	addr->dpclr = DP_CLR;
149 	addr->dpclr = DP_XIE|DP_XE;
150 	DELAY(100000);
151 	dp_softc[unit].dp_ipl = br = qbgetpri();
152 	dp_softc[unit].dp_addr = addr;
153 	addr->dpclr = 0;
154 	if (cvec && cvec != 0x200){
155 		cvec -= 4;
156 	}
157 	return (1);
158 }
159 
160 /*
161  * Interface exists: make available by filling in network interface
162  * record.  System will initialize the interface when it is ready
163  * to accept packets.
164  */
165 dpattach(ui)
166 	register struct uba_device *ui;
167 {
168 	register struct dp_softc *dp = &dp_softc[ui->ui_unit];
169 
170 	dp->dp_if.if_unit = ui->ui_unit;
171 	dp->dp_if.if_name = "dp";
172 	dp->dp_if.if_mtu = DP_MTU;
173 	dp->dp_if.if_init = dpinit;
174 	dp->dp_if.if_output = x25_ifoutput;
175 	dp->dp_if.if_start = dpstart;
176 	dp->dp_if.if_ioctl = dpioctl;
177 	dp->dp_if.if_reset = dpreset;
178 	dp->dp_if.if_watchdog = dptimeout;
179 	dp->dp_if.if_flags = 0;
180 	if_attach(&dp->dp_if);
181 }
182 
183 /*
184  * Reset of interface after UNIBUS reset.
185  * If interface is on specified UBA, reset its state.
186  */
187 dpreset(unit, uban)
188 	int unit, uban;
189 {
190 	register struct uba_device *ui;
191 	register struct dp_softc *dp = &dp_softc[unit];
192 	register struct dpdevice *addr;
193 
194 	dpstat.reset++;
195 	if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
196 	    ui->ui_ubanum != uban)
197 		return;
198 	dpdown(unit);
199 	dpinit(unit);
200 	printf(" dp%d", unit);
201 }
202 
203 /*
204  * Initialization of interface.
205  */
206 dpinit(unit)
207 	int unit;
208 {
209 	register struct dp_softc *dp = &dp_softc[unit];
210 	register struct dpdevice *addr;
211 	register struct ifaddr *ifa;
212 	register struct pdma *pdp = &dppdma[unit*2];
213 	int base, s;
214 
215 	dpstat.init++;
216 	/*
217 	 * Check to see that an address has been set.
218 	 */
219 	for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
220 		if (ifa->ifa_addr->sa_family != AF_LINK)
221 			break;
222 	if (ifa == (struct ifaddr *) 0)
223 		return;
224 
225 	addr = dp->dp_addr;
226 	s = splimp();
227 	dp->dp_iused = 0;
228 	dp->dp_istate = dp->dp_ostate = DPS_IDLE;
229 	dp->dp_if.if_flags |= IFF_RUNNING;
230 	dp->dp_if.if_flags &= ~IFF_OACTIVE;
231 
232 	pdp->p_addr = addr;
233 	pdp->p_fcn = dpxint;
234 	pdp->p_mem = pdp->p_end = dp->dp_obuf;
235 	pdp++;
236 	pdp->p_addr = addr;
237 	pdp->p_fcn = dprint;
238 	/* force initial interrupt to come to dprint */
239 	pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
240 
241 	addr->dpclr = DP_CLR;
242 	DELAY(1000);
243 	/* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
244 			    CRC = CCIIT, initially all ones, 2nd addr = 0 */
245 	addr->dpsar = DP_SSLM | DP_IDLE;
246 	addr->dpclr = 0;
247 	/* enable receiver, receive interrupt, DTR, RTS */
248 	addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
249 	dpstart(&dp->dp_if);
250 	splx(s);
251 }
252 
253 /*
254  * Start output on interface.  Get another datagram
255  * to send from the interface queue and map it to
256  * the interface before starting output.
257  *
258  */
259 dpstart(ifp)
260 	struct ifnet *ifp;
261 {
262 	int s, unit = ifp->if_unit, error = 0, len;
263 	register struct dp_softc *dp = &dp_softc[unit];
264 	register struct dpdevice *addr = dp->dp_addr;
265 	register struct mbuf *m;
266 	register char *cp;
267 	char *cplim;
268 
269 	/*
270 	 * If already doing output, go away and depend on transmit
271 	 * complete or error.
272 	 */
273 	dpstat.start++;
274 	if ((dp->dp_if.if_flags & IFF_OACTIVE) ||
275 	    ! (dp->dp_if.if_flags & IFF_RUNNING))
276 		goto out;
277 	IF_DEQUEUE(&dp->dp_if.if_snd, m);
278 	if (m == 0)
279 		goto out;
280 	dp->dp_if.if_collisions++;
281 	if (m->m_flags & M_PKTHDR)
282 		len = m->m_pkthdr.len;
283 	else {
284 		struct mbuf *m0 = m;
285 		for (len = 0; m; m = m->m_next)
286 			len += m->m_len;
287 		m = m0;
288 		dpstat.nohdr++;
289 	}
290 	if (len == 0)
291 		goto out;
292 	if (len > DP_MTU) {
293 		error = EINVAL;
294 		goto out;
295 	}
296 	dppdma[2*unit].p_mem = 1 + (cp = dp->dp_obuf);
297 	while (m) {
298 		struct mbuf *n;
299 		bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len);
300 		cp += m->m_len;
301 		MFREE(m, n); m = n;
302 	}
303 	dppdma[2*unit].p_end = cp;
304 	dp->dp_if.if_flags |= IFF_OACTIVE;
305 	dp->dp_ostate = DPS_ACTIVE;
306 	dp->dp_if.if_collisions--;
307 	addr->dpsar = DP_SSLM | DP_IDLE;
308 	addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
309 	addr->dpclr = DP_XIE | DP_XE;
310 	addr->dptdsr = DP_XSM | (0xff & *cp);
311 out:
312 	return (error);
313 }
314 long dp_rdsr;
315 /*
316  * Receive done or error interrupt
317  */
318 dprint(unit, pdma, addr)
319 register struct pdma *pdma;
320 register struct dpdevice *addr;
321 {
322 	register struct dp_softc *dp = &dp_softc[unit];
323 	short rdsr = addr->dprdsr, rcsr = pdma->p_arg;
324 
325 	dpstat.rint++;
326 dp_rdsr = rdsr;
327 	splx(dp->dp_ipl);
328 	if (rdsr & DP_RGA) {
329 		/* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
330 			    CRC = CCIIT, initially all ones, 2nd addr = 0 */
331 		addr->dpsar = DP_SSLM | DP_IDLE;
332 		addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
333 		dpstat.rga++;
334 		return;
335 	}
336 	if (rdsr & DP_RSM) { /* Received Start of Message */
337 		dpstat.rsm++;
338 		pdma->p_mem = dp->dp_ibuf;
339 		if (rcsr & DP_RDR) {
340 		    dp->dp_ibuf[0] = rdsr & DP_RBUF;
341 		    pdma->p_mem++;
342 		    dpstat.rsmchr++;
343 		}
344 		dp->dp_flags &= ~DPF_FLUSH;
345 		return;
346 	}
347 	if (rdsr & DP_REM) { /* Received End of Message */
348 		dpstat.rem++;
349 		if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
350 			dp->dp_if.if_ierrors++;
351 		} else
352 			dpinput(&dp->dp_if,
353 				pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf);
354 		pdma->p_mem = pdma->p_end;
355 		dp->dp_flags &= ~ DPF_FLUSH;
356 		return;
357 	}
358 	if (rdsr & DP_ROVR) {
359 		dp->dp_flags |= DPF_FLUSH;
360 		return;
361 	}
362 	if (rcsr & DP_MSC) {
363 		dpstat.mchange++;
364 		if (0 == (rcsr & DP_DSR)) {
365 			log(LOG_DEBUG, "dp%d: lost modem\n", unit);
366 			/*dpdown(unit);*/
367 		}
368 		return;
369 	}
370 	dp->dp_flags |= DPF_FLUSH;
371 	if (pdma->p_mem != pdma->p_end)
372 		log("dp%d: unexplained receiver interrupt\n", unit);
373 }
374 int dp_fill;
375 
376 /*
377  * Transmit complete or error interrupt
378  */
379 dpxint(unit, pdma, addr)
380 register struct pdma *pdma;
381 register struct dpdevice *addr;
382 {
383 	register struct dp_softc *dp = &dp_softc[unit];
384 	int s;
385 
386 	splx(dp->dp_ipl);
387 	dpstat.xint++;
388 	if (addr->dptdsr & DP_XERR) {
389 		log("if_dp%d: data late\n", unit);
390 	restart:
391 		pdma->p_mem = dp->dp_obuf;
392 		addr->dptdsr = DP_XSM;
393 		dp->dp_if.if_oerrors++;
394 		return;
395 	}
396 	switch (dp->dp_ostate) {
397 
398 	case DPS_ACTIVE:
399 		if (pdma->p_mem != pdma->p_end) {
400 			log("if_dp%d: misc error in dpxint\n", unit);
401 			goto restart;
402 		}
403 		addr->dpclr = DP_XIE; /* &= ~DP_XE */
404 		addr->dptdsr = DP_XEM;
405 		dp->dp_ostate = DPS_XEM;
406 		break;
407 
408 	case DPS_XEM:
409 		dp->dp_if.if_opackets++;
410 		dp->dp_if.if_flags &= ~IFF_OACTIVE;
411 		if (dp->dp_if.if_snd.ifq_len)
412 			dpstart(&dp->dp_if);
413 		else {
414 			if (dp_fill) {
415 				addr->dpsar = DP_IDLE|DP_SSLM;
416 				addr->dptdsr = DP_XABO;
417 			} else {
418 				addr->dptdsr = 0;
419 			}
420 			addr->dpclr = 0;
421 			dp->dp_ostate = DPS_IDLE;
422 		}
423 		break;
424 
425 	default:
426 		log("if_dp%d: impossible state in dpxint\n");
427 	}
428 }
429 /*
430  * Routine to copy from device buffer into mbufs.
431  *
432  * Warning: This makes the fairly safe assumption that
433  * mbufs have even lengths.
434  */
435 struct mbuf *
436 dpget(rxbuf, totlen, off, ifp)
437 	caddr_t rxbuf;
438 	int totlen, off;
439 	struct ifnet *ifp;
440 {
441 	register caddr_t cp;
442 	register struct mbuf *m;
443 	struct mbuf *top = 0, **mp = ⊤
444 	int len;
445 	caddr_t packet_end;
446 
447 	cp = rxbuf;
448 	packet_end = cp + totlen;
449 	if (off) {
450 		off += 2 * sizeof(u_short);
451 		totlen -= 2 *sizeof(u_short);
452 		cp = rxbuf + off;
453 	}
454 
455 	MGETHDR(m, M_DONTWAIT, MT_DATA);
456 	if (m == 0)
457 		return (0);
458 	m->m_pkthdr.rcvif = ifp;
459 	m->m_pkthdr.len = totlen;
460 	m->m_len = MHLEN;
461 
462 	while (totlen > 0) {
463 		if (top) {
464 			MGET(m, M_DONTWAIT, MT_DATA);
465 			if (m == 0) {
466 				m_freem(top);
467 				return (0);
468 			}
469 			m->m_len = MLEN;
470 		}
471 		len = min(totlen, (packet_end - cp));
472 		if (len >= MINCLSIZE) {
473 			MCLGET(m, M_DONTWAIT);
474 			if (m->m_flags & M_EXT)
475 				m->m_len = len = min(len, MCLBYTES);
476 			else
477 				len = m->m_len;
478 		} else {
479 			/*
480 			 * Place initial small packet/header at end of mbuf.
481 			 */
482 			if (len < m->m_len) {
483 				if (top == 0 && len + max_linkhdr <= m->m_len)
484 					m->m_data += max_linkhdr;
485 				m->m_len = len;
486 			} else
487 				len = m->m_len;
488 		}
489 		bcopy(cp, mtod(m, caddr_t), (u_int)len);
490 		*mp = m;
491 		mp = &m->m_next;
492 		totlen -= len;
493 		cp += len;
494 		if (cp == packet_end)
495 			cp = rxbuf;
496 	}
497 	return (top);
498 }
499 
500 dpinput(ifp, len, buffer)
501 register struct ifnet *ifp;
502 caddr_t buffer;
503 {
504 	register struct ifqueue *inq;
505 	register struct mbuf *m;
506 	extern struct ifqueue hdintrq, ipintrq;
507 	int netisr;
508 
509 	ifp->if_ipackets++;
510     {
511 	register struct ifaddr *ifa = ifp->if_addrlist;
512 	register u_char *cp = (u_char *)buffer;
513 
514 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
515 		if (ifa->ifa_addr->sa_family != AF_LINK)
516 			break;
517 	if (cp[0] == 0xff && cp[1] == 0x3) {
518 		/* This is a UI HDLC Packet, so we'll assume PPP
519 		   protocol.  for now, IP only. */
520 		buffer += 4;
521 		len -= 4;
522 		inq = &ipintrq;
523 		netisr = NETISR_IP;
524 	} else {
525 		inq = &hdintrq;
526 		netisr = NETISR_CCITT;
527 	}
528     }
529 	if (len <= 0)
530 		return;
531 
532 	m = dpget(buffer, len , 0, ifp);
533 	if (m == 0)
534 		return;
535 
536 	if(IF_QFULL(inq)) {
537 		IF_DROP(inq);
538 		m_freem(m);
539 	} else {
540 		IF_ENQUEUE(inq, m);
541 		schednetisr(netisr);
542 	}
543 }
544 
545 /*
546  * Process an ioctl request.
547  */
548 dpioctl(ifp, cmd, data)
549 	register struct ifnet *ifp;
550 	int cmd;
551 	caddr_t data;
552 {
553 	register struct ifaddr *ifa = (struct ifaddr *)data;
554 	int s = splimp(), error = 0;
555 	struct dp_softc *dp = &dp_softc[ifp->if_unit];
556 
557 	dpstat.ioctl++;
558 	switch (cmd) {
559 
560 	case SIOCSIFADDR:
561 		ifp->if_flags |= IFF_UP;
562 		switch (ifa->ifa_addr->sa_family) {
563 		case AF_INET:
564 			ifp->if_output = dptestoutput;
565 		default:
566 			dpinit(ifp->if_unit);
567 			break;
568 		}
569 		break;
570 #ifdef CCITT
571 	case SIOCSIFCONF_X25:
572 		ifp->if_flags |= IFF_UP;
573 		ifp->if_output = x25_ifoutput;
574 		error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
575 		if (error == 0)
576 			dpinit(ifp->if_unit);
577 		break;
578 #endif
579 
580 	case SIOCSIFFLAGS:
581 		if ((ifp->if_flags & IFF_UP) == 0 &&
582 		    (ifp->if_flags & IFF_RUNNING))
583 			dpdown(ifp->if_unit);
584 		else if (ifp->if_flags & IFF_UP &&
585 		    (ifp->if_flags & IFF_RUNNING) == 0)
586 			dpinit(ifp->if_unit);
587 		break;
588 
589 
590 	default:
591 		error = EINVAL;
592 	}
593 	splx(s);
594 	return (error);
595 }
596 /*
597  * Reset a device and mark down.
598  * Flush output queue and drop queue limit.
599  */
600 dpdown(unit)
601 int unit;
602 {
603 
604 	register struct dp_softc *dp = &dp_softc[unit];
605 	register struct dpdevice *addr = dp->dp_addr;
606 
607 	dpstat.down++;
608 	if_qflush(&dp->dp_if.if_snd);
609 	dp->dp_flags = 0;
610 	dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
611 
612 	addr->dpclr = DP_CLR;
613 	DELAY(1000);
614 	addr->dpsar = 0;
615 	addr->dprcsr = 0;
616 }
617 
618 /*
619  * Watchdog timeout to see that transmitted packets don't
620  * lose interrupts.  The device has to be online (the first
621  * transmission may block until the other side comes up).
622  */
623 dptimeout(unit)
624 	int unit;
625 {
626 	register struct dp_softc *dp;
627 
628 	/* currently not armed */
629 	dpstat.timeout++;
630 	dp = &dp_softc[unit];
631 	if (dp->dp_if.if_flags & IFF_OACTIVE) {
632 		dpstart(&dp->dp_if);
633 	}
634 }
635 /*
636  * For debugging loopback activity.
637  */
638 static char pppheader[4] = { -1, 3, 0, 0x21 };
639 int dp_louts;
640 
641 dptestoutput(ifp, m, dst, rt)
642 register struct ifnet *ifp;
643 register struct mbuf *m;
644 struct sockaddr *dst;
645 struct rtentry *rt;
646 {
647 	/*
648 	 * Queue message on interface, and start output if interface
649 	 * not yet active.
650 	 */
651 	int s = splimp(), error = 0;
652 	dp_louts++;
653 	M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
654 	if (m == 0) {
655 		splx(s);
656 		return ENOBUFS;
657 	}
658 	bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
659 	if (IF_QFULL(&ifp->if_snd)) {
660 		IF_DROP(&ifp->if_snd);
661 	    /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
662 			ifp->if_name, ifp->if_unit);*/
663 		m_freem(m);
664 		error = ENOBUFS;
665 	} else {
666 		IF_ENQUEUE(&ifp->if_snd, m);
667 		if ((ifp->if_flags & IFF_OACTIVE) == 0)
668 			(*ifp->if_start)(ifp);
669 	}
670 	splx(s);
671 	return (error);
672 }
673 
674 #endif
675