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