xref: /csrg-svn/sys/vax/if/if_vv.c (revision 21779)
1 /*	if_vv.c	6.8	85/06/03	*/
2 
3 #include "vv.h"
4 
5 /*
6  * Proteon proNET-10 and proNET-80 token ring driver.
7  * The name of this device driver derives from the old MIT
8  * name of V2LNI for the proNET hardware, would would abbreviate
9  * to "v2", but this won't work right. Thus the name is "vv".
10  *
11  * This driver is compatible with the proNET 10 meagbit and
12  * 80 megabit token ring interfaces (models p1000 and p1080).
13  *
14  * TRAILERS: You must turn off trailers via ifconfig if you want to share
15  * a ring with software using the following protocol types:
16  *  3: Address Resolution Protocol
17  *  4: HDLC (old Proteon drivers)
18  *  5: VAX Debugging Protocol (never used)
19  * This is because the protocol type values chosen for trailers
20  * conflict with these protocols. It's too late to change either now.
21  *
22  * HARDWARE COMPATABILITY: This driver requires that the HSBU (p1001)
23  * have a serial number >= 040, which is about March, 1982. Older
24  * HSBUs do not carry across 64kbyte boundaries. The old warning
25  * about use without Wire Centers applies only to CTL (p1002) cards with
26  * serial <= 057, which have not received ECO 176-743, which was
27  * implemented in March, 1982. Most such CTLs have received this ECO,
28  * but they are only compatible with the old HSBUs (<=039) anyways.
29  */
30 #include "../machine/pte.h"
31 
32 #include "param.h"
33 #include "systm.h"
34 #include "mbuf.h"
35 #include "buf.h"
36 #include "protosw.h"
37 #include "socket.h"
38 #include "vmmac.h"
39 #include "errno.h"
40 #include "ioctl.h"
41 
42 #include "../net/if.h"
43 #include "../net/netisr.h"
44 #include "../net/route.h"
45 #include "../netinet/in.h"
46 #include "../netinet/in_systm.h"
47 #include "../netinet/in_var.h"
48 #include "../netinet/ip.h"
49 #include "../netinet/ip_var.h"
50 
51 #include "../vax/cpu.h"
52 #include "../vax/mtpr.h"
53 #include "if_vv.h"
54 #include "if_uba.h"
55 #include "../vaxuba/ubareg.h"
56 #include "../vaxuba/ubavar.h"
57 
58 /*
59  * 80 megabit configuration
60  * Uncomment the next line if you are using the 80 megabit system. The
61  * only change is the disposition of packets with parity/link_data_error
62  * indication.
63  */
64 /* #define PRONET80 */
65 
66 /*
67  *    maximum transmission unit definition --
68  *        you can set VVMTU at anything from 576 to 2024.
69  *        1536 is a popular "large" value, because it is a multiple
70  *	  of 512, which the trailer scheme likes.
71  *        The absolute maximum size is 2024, which is enforced.
72  */
73 
74 #define VVMTU (1024)
75 
76 #define VVMRU (VVMTU + 16)
77 #define VVBUFSIZE (VVMRU + sizeof(struct vv_header))
78 #if VVMTU>2024
79 #undef VVMTU
80 #undef VVMRU
81 #undef VVBUFSIZE
82 #define VVBUFSIZE (2046)
83 #define VVMRU (VVBUFSIZE - sizeof (struct vv_header))
84 #define VVMTU (VVMRU - 16)
85 #endif
86 
87 /*
88  *   debugging and tracing stuff
89  */
90 int	vv_tracehdr = 0;	/* 1 => trace headers (slowly!!) */
91 
92 #define vvtracehdr  if (vv_tracehdr) vvprt_hdr
93 #define vvprintf    if (vs->vs_if.if_flags & IFF_DEBUG) printf
94 
95 /*
96  * externals, types, etc.
97  */
98 int	vvprobe(), vvattach(), vvreset(), vvinit();
99 int	vvidentify(), vvstart(), vvxint(), vvwatchdog();
100 int	vvrint(), vvoutput(), vvioctl(), vvsetaddr();
101 struct	uba_device *vvinfo[NVV];
102 u_short vvstd[] = { 0 };
103 struct	uba_driver vvdriver =
104 	{ vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo };
105 #define	VVUNIT(x)	minor(x)
106 
107 #define LOOPBACK		/* use loopback for packets meant for us */
108 #ifdef	LOOPBACK
109 extern struct ifnet loif;
110 #endif
111 
112 /*
113  * Software status of each interface.
114  *
115  * Each interface is referenced by a network interface structure,
116  * vs_if, which the routing code uses to locate the interface.
117  * This structure contains the output queue for the interface, its address, ...
118  * We also have, for each interface, a UBA interface structure, which
119  * contains information about the UNIBUS resources held by the interface:
120  * map registers, buffered data paths, etc.  Information is cached in this
121  * structure for use by the if_uba.c routines in running the interface
122  * efficiently.
123  */
124 struct	vv_softc {
125 	struct	ifnet vs_if;		/* network-visible interface */
126 	struct	ifuba vs_ifuba;		/* UNIBUS resources */
127 	int	vs_host;
128 	short	vs_oactive;		/* is output active */
129 	short	vs_olen;		/* length of last output */
130 	u_short	vs_lastx;		/* address of last packet sent */
131 	u_short	vs_lastr;		/* address of last packet received */
132 	short	vs_tries;		/* transmit current retry count */
133 	short	vs_init;		/* number of ring inits */
134 	short	vs_refused;		/* number of packets refused */
135 	short	vs_timeouts;		/* number of transmit timeouts */
136 	short	vs_otimeout;		/* number of output timeouts */
137 	short	vs_ibadf;		/* number of input bad formats */
138 	short	vs_parity;		/* number of parity errors on 10 meg, */
139 					/* link data errors on 80 meg */
140 } vv_softc[NVV];
141 
142 /*
143  * probe the interface to see that the registers exist, and then
144  * cause an interrupt to find its vector
145  */
146 vvprobe(reg)
147 	caddr_t reg;
148 {
149 	register int br, cvec;
150 	register struct vvreg *addr;
151 
152 #ifdef lint
153 	br = 0; cvec = br; br = cvec;
154 #endif
155 	addr = (struct vvreg *)reg;
156 
157 	/* reset interface, enable, and wait till dust settles */
158 	addr->vvicsr = VV_RST;
159 	addr->vvocsr = VV_RST;
160 	DELAY(100000);
161 
162 	/* generate interrupt by doing 1 word DMA from 0 in uba space!! */
163 	addr->vvoba = 0;		/* low 16 bits */
164 	addr->vvoea = 0;		/* extended bits */
165 	addr->vvowc = -1;		/* for 1 word */
166 	addr->vvocsr = VV_IEN | VV_DEN;	/* start the DMA, with interrupt */
167 	DELAY(100000);
168 	addr->vvocsr = VV_RST;		/* clear out the CSR */
169 	if (cvec && cvec != 0x200)
170 		cvec -= 4;		/* backup so vector => receive */
171 	return(1);
172 }
173 
174 /*
175  * Interface exists: make available by filling in network interface
176  * record.  System will initialize the interface when it is ready
177  * to accept packets.
178  */
179 vvattach(ui)
180 	struct uba_device *ui;
181 {
182 	register struct vv_softc *vs;
183 
184 	vs = &vv_softc[ui->ui_unit];
185 	vs->vs_if.if_unit = ui->ui_unit;
186 	vs->vs_if.if_name = "vv";
187 	vs->vs_if.if_mtu = VVMTU;
188 	vs->vs_if.if_flags = IFF_BROADCAST;
189 	vs->vs_if.if_init = vvinit;
190 	vs->vs_if.if_ioctl = vvioctl;
191 	vs->vs_if.if_output = vvoutput;
192 	vs->vs_if.if_reset = vvreset;
193 	vs->vs_if.if_timer = 0;
194 	vs->vs_if.if_watchdog = vvwatchdog;
195 	vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP | UBA_NEED16;
196 #if defined(VAX750)
197 	/* don't chew up 750 bdp's */
198 	if (cpu == VAX_750 && ui->ui_unit > 0)
199 		vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP;
200 #endif
201 	if_attach(&vs->vs_if);
202 }
203 
204 /*
205  * Reset of interface after UNIBUS reset.
206  * If interface is on specified uba, reset its state.
207  */
208 vvreset(unit, uban)
209 	int unit, uban;
210 {
211 	register struct uba_device *ui;
212 
213 	if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 ||
214 	    ui->ui_ubanum != uban)
215 		return;
216 	printf(" vv%d", unit);
217 	vvinit(unit);
218 }
219 
220 /*
221  * Initialization of interface; clear recorded pending
222  * operations, and reinitialize UNIBUS usage.
223  */
224 vvinit(unit)
225 	int unit;
226 {
227 	register struct vv_softc *vs;
228 	register struct uba_device *ui;
229 	register struct vvreg *addr;
230 	register int ubainfo, s;
231 
232 	vs = &vv_softc[unit];
233 	ui = vvinfo[unit];
234 
235 	if (vs->vs_if.if_addrlist == (struct ifaddr *)0)
236 		return;
237 
238 	addr = (struct vvreg *)ui->ui_addr;
239 	if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum,
240 	    sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) {
241 		printf("vv%d: can't initialize, if_ubainit() failed\n", unit);
242 		vs->vs_if.if_flags &= ~IFF_UP;
243 		return;
244 	}
245 
246 	/*
247 	 * Now that the uba is set up, figure out our address and
248 	 * update complete our host address.
249 	 */
250 	if ((vs->vs_host = vvidentify(unit)) == -1) {
251 		vs->vs_if.if_flags &= ~IFF_UP;
252 		return;
253 	}
254 	printf("vv%d: host %d\n", unit, vs->vs_host);
255 
256 	/*
257 	 * Reset the interface, and stay in the ring
258 	 */
259 	addr->vvocsr = VV_RST;			/* take over output */
260 	addr->vvocsr = VV_CPB;			/* clear packet buffer */
261 	addr->vvicsr = VV_RST | VV_HEN;		/* take over input, */
262 						/* keep relay closed */
263 	DELAY(500000);				/* let contacts settle */
264 
265 	vs->vs_init = 0;			/* clear counters, etc. */
266 	vs->vs_refused = 0;
267 	vs->vs_timeouts = 0;
268 	vs->vs_otimeout = 0;
269 	vs->vs_ibadf = 0;
270 	vs->vs_parity = 0;
271 	vs->vs_lastx = 256;			/* an invalid address */
272 	vs->vs_lastr = 256;			/* an invalid address */
273 
274 	/*
275 	 * Hang a receive and start any
276 	 * pending writes by faking a transmit complete.
277 	 */
278 	s = splimp();
279 	ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
280 	addr->vviba = (u_short)ubainfo;
281 	addr->vviea = (u_short)(ubainfo >> 16);
282 	addr->vviwc = -(VVBUFSIZE) >> 1;
283 	addr->vvicsr = VV_IEN | VV_HEN | VV_DEN | VV_ENB;
284 	vs->vs_oactive = 1;
285 	vs->vs_if.if_flags |= IFF_RUNNING;
286 	vvxint(unit);
287 	splx(s);
288 }
289 
290 /*
291  * Do a moderately thorough self-test in all three modes. Mostly
292  * to keeps defective nodes off the ring, rather than to be especially
293  * thorough. The key issue is to detect any cable breaks before joining
294  * the ring. Return our node address on success, return -1 on failure.
295  *
296  */
297 
298 /* the three self-test modes */
299 static u_short vv_modes[] = {
300 	VV_STE|VV_LPB,			/* digital loopback */
301 	VV_STE,				/* analog loopback */
302 	VV_HEN				/* network mode */
303 };
304 
305 vvidentify(unit)
306 	int unit;
307 {
308 	register struct vv_softc *vs;
309 	register struct uba_device *ui;
310 	register struct vvreg *addr;
311 	register struct mbuf *m;
312 	register struct vv_header *v;
313 	register int ubainfo;
314 	register int i, successes, failures, waitcount;
315 	u_short shost = -1;
316 
317 	vs = &vv_softc[unit];
318 	ui = vvinfo[unit];
319 	addr = (struct vvreg *)ui->ui_addr;
320 
321 	/*
322 	 * Build a multicast message to identify our address
323 	 * We need do this only once, since nobody else is about to use
324 	 * the intermediate transmit buffer (ifu_w.ifrw_addr) that
325 	 * if_ubainit() aquired for us.
326 	 */
327 	m = m_get(M_DONTWAIT, MT_HEADER);
328 	if (m == NULL) {
329 		printf("vv%d: can't initialize, m_get() failed\n", unit);
330 		return (0);
331 	}
332 	m->m_next = 0;
333 	m->m_off = MMINOFF;
334 	m->m_len = sizeof(struct vv_header);
335 	v = mtod(m, struct vv_header *);
336 	v->vh_dhost = VV_BROADCAST;	/* multicast destination address */
337 	v->vh_shost = 0;		/* will be overwritten with ours */
338 	v->vh_version = RING_VERSION;
339 	v->vh_type = RING_DIAGNOSTICS;
340 	v->vh_info = 0;
341 	/* map xmit message into uba, copying to intermediate buffer */
342 	vs->vs_olen = if_wubaput(&vs->vs_ifuba, m);
343 
344 	/*
345 	 * For each of the modes (digital, analog, network), go through
346 	 * a self-test that requires me to send VVIDENTSUCC good packets
347 	 * in VVIDENTRETRY attempts. Use broadcast destination to find out
348 	 * who I am, then use this as my address to check my address match
349 	 * logic. Only data checked is the vh_type field.
350 	 */
351 
352 	for (i = 0; i < 3; i++) {
353 		successes = 0;	/* clear successes for this mode */
354 		failures = 0;	/* and clear failures, too */
355 
356 		/* take over device, and leave ring */
357 		addr->vvicsr = VV_RST;
358 		addr->vvocsr = VV_RST;
359 		addr->vvicsr = vv_modes[i];	/* test mode */
360 
361 		/*
362 		 * let the flag and token timers pop so that the init ring bit
363 		 * will be allowed to work, by waiting about 1 second
364 		 */
365 		DELAY(1000000L);
366 
367 		/*
368 		 * retry loop
369  		 */
370 		while ((successes < VVIDENTSUCC) && (failures < VVIDENTRETRY))
371 		{
372 			/* start a receive */
373 			ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
374 			addr->vvicsr = VV_RST | vv_modes[i]; /* abort last */
375 			addr->vviba = (u_short) ubainfo;
376 			addr->vviea = (u_short) (ubainfo >> 16);
377 			addr->vviwc = -(VVBUFSIZE) >> 1;
378 			addr->vvicsr = vv_modes[i] | VV_DEN | VV_ENB;
379 
380 			/* purge stale data from BDP */
381 			if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP)
382 				UBAPURGE(vs->vs_ifuba.ifu_uba,
383 				    vs->vs_ifuba.ifu_w.ifrw_bdp);
384 
385 			/* do a transmit */
386 			ubainfo = vs->vs_ifuba.ifu_w.ifrw_info;
387 			addr->vvocsr = VV_RST;	/* abort last try */
388 			addr->vvoba = (u_short) ubainfo;
389 			addr->vvoea = (u_short) (ubainfo >> 16);
390 			addr->vvowc = -((vs->vs_olen + 1) >> 1);
391 			addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB;
392 
393 			/* poll receive side for completion */
394 			DELAY(10000);		/* give it a chance */
395 			for (waitcount = 0; waitcount < 10; waitcount++) {
396 				if (addr->vvicsr & VV_RDY)
397 					goto gotit;
398 				DELAY(1000);
399 			}
400 			failures++;		/* no luck */
401 			continue;
402 
403 gotit:			/* we got something--is it any good? */
404 			if ((addr->vvicsr & (VVRERR|VV_LDE)) ||
405 			    (addr->vvocsr & (VVXERR|VV_RFS))) {
406 				failures++;
407 				continue;
408 			}
409 
410 			/* Purge BDP before looking at received packet */
411 			if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP)
412 				UBAPURGE(vs->vs_ifuba.ifu_uba,
413 				    vs->vs_ifuba.ifu_r.ifrw_bdp);
414 			m = if_rubaget(&vs->vs_ifuba,
415 			    sizeof(struct vv_header), 0);
416 			if (m != NULL)
417 				m_freem(m);
418 
419 			v = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr);
420 
421 			/* check message type, catch our node address */
422 			if ((v->vh_type & 0xff) == RING_DIAGNOSTICS) {
423 				if (shost == -1) {
424 					shost = v->vh_shost & 0xff;
425 					/* send to ourself now */
426 					((struct vv_header *)
427 					    (vs->vs_ifuba.ifu_r.ifrw_addr))
428 					    ->vh_dhost = shost;
429 				}
430 				successes++;
431 				v->vh_type = 0;  /* clear to check again */
432 			}
433 		}
434 
435 		if (failures >= VVIDENTRETRY)
436 		{
437 			printf("vv%d: failed self-test after %d tries \
438 in %s mode\n",
439 			    unit, VVIDENTRETRY, i == 0 ? "digital loopback" :
440 			    (i == 1 ? "analog loopback" : "network"));
441 			printf("vv%d: icsr = %b, ocsr = %b\n",
442 			    unit, 0xffff & addr->vvicsr, VV_IBITS,
443 			    0xffff & addr->vvocsr, VV_OBITS);
444 			addr->vvicsr = VV_RST;	/* kill the sick board */
445 			addr->vvocsr = VV_RST;
446 			shost = -1;
447 			goto done;
448 		}
449 	}
450 
451 done:
452 	/* deallocate mbuf used for send packet (won't be one, anyways) */
453 	if (vs->vs_ifuba.ifu_xtofree) {
454 		m_freem(vs->vs_ifuba.ifu_xtofree);
455 		vs->vs_ifuba.ifu_xtofree = 0;
456 	}
457 
458 	return(shost);
459 }
460 
461 /*
462  * Start or restart output on interface.
463  * If interface is active, this is a retransmit, so just
464  * restuff registers and go.
465  * If interface is not already active, get another datagram
466  * to send off of the interface queue, and map it to the interface
467  * before starting the output.
468  */
469 vvstart(dev)
470 	dev_t dev;
471 {
472 	register struct uba_device *ui;
473 	register struct vv_softc *vs;
474 	register struct vvreg *addr;
475 	register struct mbuf *m;
476 	register int unit, ubainfo, dest, s;
477 
478 	unit = VVUNIT(dev);
479 	ui = vvinfo[unit];
480 	vs = &vv_softc[unit];
481 	if (vs->vs_oactive)
482 		goto restart;
483 	/*
484 	 * Not already active: dequeue another request
485 	 * and map it to the UNIBUS.  If no more requests,
486 	 * just return.
487 	 */
488 	s = splimp();
489 	IF_DEQUEUE(&vs->vs_if.if_snd, m);
490 	splx(s);
491 	if (m == NULL) {
492 		vs->vs_oactive = 0;
493 		return;
494 	}
495 	dest = mtod(m, struct vv_header *)->vh_dhost;
496 	vs->vs_olen = if_wubaput(&vs->vs_ifuba, m);
497 	vs->vs_lastx = dest;
498 restart:
499 	/*
500 	 * Have request mapped to UNIBUS for transmission.
501 	 * Purge any stale data from this BDP, and start the output.
502 	 *
503 	 * Make sure this packet will fit in the interface.
504 	 */
505 	if (vs->vs_olen > VVBUFSIZE) {
506 		printf("vv%d vs_olen: %d > VVBUFSIZE\n", unit, vs->vs_olen);
507 		panic("vvdriver vs_olen botch");
508 	}
509 
510 	vs->vs_if.if_timer = VVTIMEOUT;
511 	vs->vs_oactive = 1;
512 
513 	/* ship it */
514 	if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP)
515 		UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp);
516 	addr = (struct vvreg *)ui->ui_addr;
517 	ubainfo = vs->vs_ifuba.ifu_w.ifrw_info;
518 	addr->vvoba = (u_short) ubainfo;
519 	addr->vvoea = (u_short) (ubainfo >> 16);
520 	addr->vvowc = -((vs->vs_olen + 1) >> 1);
521 	addr->vvowc = -((vs->vs_olen + 1) >> 1); /* extra byte is garbage */
522 	if (addr->vvocsr & VV_NOK)
523 		vs->vs_init++;			/* count ring inits */
524 	addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB;
525 	vs->vs_if.if_timer = VVTIMEOUT;
526 	vs->vs_oactive = 1;
527 }
528 
529 /*
530  * proNET transmit interrupt
531  * Start another output if more data to send.
532  */
533 vvxint(unit)
534 	int unit;
535 {
536 	register struct uba_device *ui;
537 	register struct vv_softc *vs;
538 	register struct vvreg *addr;
539 	register int oc;
540 
541 	ui = vvinfo[unit];
542 	vs = &vv_softc[unit];
543 	vs->vs_if.if_timer = 0;
544 	addr = (struct vvreg *)ui->ui_addr;
545 	oc = 0xffff & (addr->vvocsr);
546 	if (vs->vs_oactive == 0) {
547 		vvprintf("vv%d: stray interrupt vvocsr = %b\n", unit,
548 		    oc, VV_OBITS);
549 		return;
550 	}
551 
552 	/*
553 	 * we retransmit on soft error
554 	 * TODO: sort retransmits to end of queue if possible!
555 	 */
556 	if (oc & (VV_OPT | VV_RFS)) {
557 		if (vs->vs_tries++ < VVRETRY) {
558 			if (oc & VV_OPT)
559 				vs->vs_otimeout++;
560 			if (oc & VV_RFS) {
561 				vs->vs_if.if_collisions++;
562 				vs->vs_refused++;
563 			}
564 			vvstart(unit);		/* restart this message */
565 			return;
566 		}
567 	}
568 	vs->vs_if.if_opackets++;
569 	vs->vs_oactive = 0;
570 	vs->vs_tries = 0;
571 
572 	if (oc & VVXERR) {
573 		vs->vs_if.if_oerrors++;
574 		vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc,
575 		    VV_OBITS);
576 	}
577 	if (vs->vs_ifuba.ifu_xtofree) {
578 		m_freem(vs->vs_ifuba.ifu_xtofree);
579 		vs->vs_ifuba.ifu_xtofree = 0;
580 	}
581 	vvstart(unit);
582 }
583 
584 /*
585  * Transmit watchdog timer routine.
586  * This routine gets called when we lose a transmit interrupt.
587  * The best we can do is try to restart output.
588  */
589 vvwatchdog(unit)
590 	int unit;
591 {
592 	register struct vv_softc *vs;
593 	register int s;
594 
595 	vs = &vv_softc[unit];
596 	vvprintf("vv%d: lost a transmit interrupt.\n", unit);
597 	vs->vs_timeouts++;
598 	s = splimp();
599 	vvstart(unit);
600 	splx(s);
601 }
602 
603 /*
604  * proNET interface receiver interrupt.
605  * If input error just drop packet.
606  * Otherwise purge input buffered data path and examine
607  * packet to determine type.  If can't determine length
608  * from type, then have to drop packet.  Otherwise decapsulate
609  * packet based on type and pass to type specific higher-level
610  * input routine.
611  */
612 vvrint(unit)
613 	int unit;
614 {
615 	register struct vv_softc *vs;
616 	register struct vvreg *addr;
617 	register struct vv_header *vv;
618 	register struct ifqueue *inq;
619 	register struct mbuf *m;
620 	int ubainfo, len, off, s;
621 	short resid;
622 
623 	vs = &vv_softc[unit];
624 	vs->vs_if.if_ipackets++;
625 	addr = (struct vvreg *)vvinfo[unit]->ui_addr;
626 
627 	/*
628 	 * Purge BDP; drop if input error indicated.
629 	 */
630 	if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP)
631 		UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_r.ifrw_bdp);
632 
633 	/*
634 	 * receive errors?
635 	 */
636 	if (addr->vvicsr & VVRERR) {
637 		vvprintf("vv%d: receive error, vvicsr = %b\n", unit,
638 		    0xffff&(addr->vvicsr), VV_IBITS);
639 		if (addr->vvicsr & VV_BDF)
640 			vs->vs_ibadf++;
641 		goto dropit;
642 	}
643 
644 	/*
645 	 * parity errors?
646 	 */
647 	if (addr->vvicsr & VV_LDE) {
648 		/* we don't have to clear it because the receive command */
649 		/* writes 0 to parity bit */
650 		vs->vs_parity++;
651 #ifndef PRONET80
652 		/*
653 		 * only on 10 megabit proNET is VV_LDE an end-to-end parity
654 		 * bit. On 80 megabit, it returns to the intended use of
655 		 * node-to-node parity. End-to-end parity errors on 80 megabit
656 		 * give VV_BDF.
657 		 */
658 		goto dropit;
659 #endif
660 	}
661 
662 	/*
663 	 * Get packet length from residual word count
664 	 *
665 	 * Compute header offset if trailer protocol
666 	 *
667 	 * Pull packet off interface.  Off is nonzero if packet
668 	 * has trailing header; if_rubaget will then force this header
669 	 * information to be at the front.  The vh_info field
670 	 * carries the offset to the trailer data in trailer
671 	 * format packets.
672 	 */
673 	vv = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr);
674 	vvtracehdr("vi", vv);
675 	resid = addr->vviwc & 01777;	/* only low 10 bits valid */
676 	if (resid)
677 		resid |= 0176000;	/* high 6 bits are undefined */
678 	len = ((VVBUFSIZE >> 1) + resid) << 1;
679 	len -= sizeof(struct vv_header);
680 
681 	if ((addr->vvicsr & VV_DPR) || len > VVMRU || len <= 0) {
682 		vvprintf("vv%d: len too long or short, \
683 len = %d, vvicsr = %b\n",
684 			    unit, len, 0xffff&(addr->vvicsr), VV_IBITS);
685 		goto dropit;
686 	}
687 
688 	/* check the protocol header version */
689 	if (vv->vh_version != RING_VERSION) {
690 		vvprintf("vv%d: bad protocol header version %d\n",
691 		    unit, vv->vh_version & 0xff);
692 		goto dropit;
693 	}
694 
695 #define	vvdataaddr(vv, off, type)	((type)(((caddr_t)((vv)+1)+(off))))
696 	if (vv->vh_type >= RING_IPTrailer &&
697 	     vv->vh_type < RING_IPTrailer+RING_IPNTrailer) {
698 		off = (vv->vh_type - RING_IPTrailer) * 512;
699 		if (off > VVMTU) {
700 			vvprintf("vv%d: off > VVMTU, off = %d, vvicsr = %b\n",
701 				    unit, off, 0xffff&(addr->vvicsr), VV_IBITS);
702 			goto dropit;
703 		}
704 		vv->vh_type = *vvdataaddr(vv, off, u_short *);
705 		resid = *(vvdataaddr(vv, off+2, u_short *));
706 		if (off + resid > len) {
707 			vvprintf("vv%d: trailer packet too short\n", unit);
708 			vvprintf("vv%d: off = %d, resid = %d, vvicsr = %b\n",
709 				    unit, off, resid,
710 				    0xffff&(addr->vvicsr), VV_IBITS);
711 			goto dropit;
712 		}
713 		len = off + resid;
714 	} else
715 		off = 0;
716 
717 	if (len == 0) {
718 		vvprintf("vv%d: len is zero, vvicsr = %b\n", unit,
719 			    0xffff&(addr->vvicsr), VV_IBITS);
720 		goto dropit;
721 	}
722 
723 	m = if_rubaget(&vs->vs_ifuba, len, off);
724 	if (m == NULL) {
725 		vvprintf("vv%d: if_rubaget() failed, vvicsr = %b\n", unit,
726 			    0xffff&(addr->vvicsr), VV_IBITS);
727 		goto dropit;
728 	}
729 	if (off) {
730 		m->m_off += 2 * sizeof(u_short);
731 		m->m_len -= 2 * sizeof(u_short);
732 	}
733 
734 	/* Keep track of source address of this packet */
735 	vs->vs_lastr = vv->vh_shost;
736 
737 	/*
738 	 * Demultiplex on packet type
739 	 */
740 	switch (vv->vh_type) {
741 
742 #ifdef INET
743 	case RING_IP:
744 		schednetisr(NETISR_IP);
745 		inq = &ipintrq;
746 		break;
747 #endif
748 	default:
749 		vvprintf("vv%d: unknown pkt type 0x%x\n", unit, vv->vh_type);
750 		m_freem(m);
751 		goto setup;
752 	}
753 	s = splimp();
754 	if (IF_QFULL(inq)) {
755 		IF_DROP(inq);
756 		m_freem(m);
757 	} else
758 		IF_ENQUEUE(inq, m);
759 
760 	splx(s);
761 	/*
762 	 * Reset for the next packet.
763 	 */
764 setup:
765 	ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
766 	addr->vviba = (u_short) ubainfo;
767 	addr->vviea = (u_short) (ubainfo >> 16);
768 	addr->vviwc = -(VVBUFSIZE) >> 1;
769 	addr->vvicsr = VV_HEN | VV_IEN | VV_DEN | VV_ENB;
770 	return;
771 
772 	/*
773 	 * Drop packet on floor -- count them!!
774 	 */
775 dropit:
776 	vs->vs_if.if_ierrors++;
777 	goto setup;
778 }
779 
780 /*
781  * proNET output routine.
782  * Encapsulate a packet of type family for the local net.
783  * Use trailer local net encapsulation if enough data in first
784  * packet leaves a multiple of 512 bytes of data in remainder.
785  */
786 vvoutput(ifp, m0, dst)
787 	struct ifnet *ifp;
788 	struct mbuf *m0;
789 	struct sockaddr *dst;
790 {
791 	register struct mbuf *m;
792 	register struct vv_header *vv;
793 	register int off;
794 	register int unit;
795 	register struct vvreg *addr;
796 	register struct vv_softc *vs;
797 	register int s;
798 	int type, dest, error;
799 
800 	m = m0;
801 	unit = ifp->if_unit;
802 	addr = (struct vvreg *)vvinfo[unit]->ui_addr;
803 	vs = &vv_softc[unit];
804 
805 	/*
806 	 * Check to see if the input side has wedged due the UBA
807 	 * vectoring through 0.
808 	 *
809 	 * We are lower than device ipl when we enter this routine,
810 	 * so if the interface is ready with an input packet then
811 	 * an input interrupt must have slipped through the cracks.
812 	 *
813 	 * Avoid the race with an input interrupt by watching to see
814 	 * if any packets come in.
815 	 */
816 	s = vs->vs_if.if_ipackets;
817 	if (addr->vvicsr & VV_RDY && s == vs->vs_if.if_ipackets) {
818 		vvprintf("vv%d: lost a receive interrupt, icsr = %b\n",
819 			    unit, 0xffff&(addr->vvicsr), VV_IBITS);
820 		s = splimp();
821 		vvrint(unit);
822 		splx(s);
823 	}
824 
825 	switch (dst->sa_family) {
826 
827 #ifdef INET
828 	case AF_INET:
829 		if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr))
830 			dest = VV_BROADCAST;
831 		else
832 			dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr);
833 #ifdef LOOPBACK
834 		if (dest == vs->vs_host && (loif.if_flags & IFF_UP))
835 			return (looutput(&loif, m0, dst));
836 #endif LOOPBACK
837 		if (dest >= 0x100) {
838 			error = EPERM;
839 			goto bad;
840 		}
841 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
842 		/*
843 		 * Trailerize, if the configuration allows it.
844 		 * TODO: Need per host negotiation.
845 		 */
846 		if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
847 		if (off > 0 && (off & 0x1ff) == 0 &&
848 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
849 			type = RING_IPTrailer + (off>>9);
850 			m->m_off -= 2 * sizeof (u_short);
851 			m->m_len += 2 * sizeof (u_short);
852 			*mtod(m, u_short *) = RING_IP;
853 			*(mtod(m, u_short *) + 1) = m->m_len;
854 			goto gottrailertype;
855 		}
856 		type = RING_IP;
857 		off = 0;
858 		goto gottype;
859 #endif
860 	default:
861 		printf("vv%d: can't handle af%d\n", unit, dst->sa_family);
862 		error = EAFNOSUPPORT;
863 		goto bad;
864 	}
865 
866 gottrailertype:
867 	/*
868 	 * Packet to be sent as trailer: move first packet
869 	 * (control information) to end of chain.
870 	 */
871 	while (m->m_next)
872 		m = m->m_next;
873 	m->m_next = m0;
874 	m = m0->m_next;
875 	m0->m_next = 0;
876 	m0 = m;
877 gottype:
878 	/*
879 	 * Add local net header.  If no space in first mbuf,
880 	 * allocate another.
881 	 */
882 	if (m->m_off > MMAXOFF ||
883 	    MMINOFF + sizeof (struct vv_header) > m->m_off) {
884 		m = m_get(M_DONTWAIT, MT_HEADER);
885 		if (m == NULL) {
886 			error = ENOBUFS;
887 			goto bad;
888 		}
889 		m->m_next = m0;
890 		m->m_off = MMINOFF;
891 		m->m_len = sizeof (struct vv_header);
892 	} else {
893 		m->m_off -= sizeof (struct vv_header);
894 		m->m_len += sizeof (struct vv_header);
895 	}
896 	vv = mtod(m, struct vv_header *);
897 	vv->vh_shost = vs->vs_host;
898 	vv->vh_dhost = dest;
899 	vv->vh_version = RING_VERSION;
900 	vv->vh_type = type;
901 	vv->vh_info = off;
902 	vvtracehdr("vo", vv);
903 
904 	/*
905 	 * Queue message on interface, and start output if interface
906 	 * not yet active.
907 	 */
908 	s = splimp();
909 	if (IF_QFULL(&ifp->if_snd)) {
910 		IF_DROP(&ifp->if_snd);
911 		error = ENOBUFS;
912 		goto qfull;
913 	}
914 	IF_ENQUEUE(&ifp->if_snd, m);
915 	if (vs->vs_oactive == 0)
916 		vvstart(unit);
917 	splx(s);
918 	return (0);
919 qfull:
920 	m0 = m;
921 	splx(s);
922 bad:
923 	m_freem(m0);
924 	return(error);
925 }
926 
927 /*
928  * Process an ioctl request.
929  */
930 vvioctl(ifp, cmd, data)
931 	register struct ifnet *ifp;
932 	int cmd;
933 	caddr_t data;
934 {
935 	struct ifaddr *ifa = (struct ifaddr *) data;
936 	int s = splimp(), error = 0;
937 
938 	switch (cmd) {
939 
940 	case SIOCSIFADDR:
941 		if ((ifp->if_flags & IFF_RUNNING) == 0)
942 			vvinit(ifp->if_unit);
943                 /*
944                  * Attempt to check agreement of protocol address
945                  * and board address.
946                  */
947 		switch (ifa->ifa_addr.sa_family) {
948                 case AF_INET:
949 			if (in_lnaof(IA_SIN(ifa)->sin_addr) !=
950 			    vv_softc[ifp->if_unit].vs_host)
951 				return (EADDRNOTAVAIL);
952 			break;
953 		}
954 		ifp->if_flags |= IFF_UP;
955 		break;
956 
957 	default:
958 		error = EINVAL;
959 	}
960 	splx(s);
961 	return (error);
962 }
963