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