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