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