rm bbnnet; combine common code in ilwait; use per-host trailer option from ARP;
[unix-history] / usr / src / sys / vax / if / if_dmc.c
CommitLineData
da7c5cc6
KM
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 *
8b924880 6 * @(#)if_dmc.c 6.9 (Berkeley) %G%
da7c5cc6 7 */
63665984
BJ
8
9#include "dmc.h"
10#if NDMC > 0
ba0b299a 11
63665984
BJ
12/*
13 * DMC11 device driver, internet version
14 *
ba0b299a 15 * Bill Nesheim
032f82b3 16 * Cornell University
c6020d6c 17 *
ba0b299a
MK
18 * Lou Salkind
19 * New York University
63665984 20 */
ba0b299a
MK
21
22/* #define DEBUG /* for base table dump on fatal error */
23
961945a8 24#include "../machine/pte.h"
63665984 25
a6e960e7
JB
26#include "param.h"
27#include "systm.h"
28#include "mbuf.h"
29#include "buf.h"
032f82b3 30#include "ioctl.h" /* must precede tty.h */
a6e960e7
JB
31#include "tty.h"
32#include "protosw.h"
33#include "socket.h"
34#include "vmmac.h"
35#include "errno.h"
a9687d27
BJ
36
37#include "../net/if.h"
4fce3bf9 38#include "../net/netisr.h"
a9687d27 39#include "../net/route.h"
822a4f2c 40
822a4f2c 41#ifdef INET
d2cc167c
BJ
42#include "../netinet/in.h"
43#include "../netinet/in_systm.h"
ba0b299a 44#include "../netinet/ip.h"
822a4f2c 45#endif
a9687d27
BJ
46
47#include "../vax/cpu.h"
48#include "../vax/mtpr.h"
a6e960e7
JB
49#include "if_uba.h"
50#include "if_dmc.h"
a9687d27
BJ
51#include "../vaxuba/ubareg.h"
52#include "../vaxuba/ubavar.h"
63665984 53
ba0b299a
MK
54#include "../h/time.h"
55#include "../h/kernel.h"
56
57int dmctimer; /* timer started? */
58int dmc_timeout = 8; /* timeout value */
59int dmcwatch();
60
63665984
BJ
61/*
62 * Driver information for auto-configuration stuff.
63 */
17718098
SL
64int dmcprobe(), dmcattach(), dmcinit(), dmcioctl();
65int dmcoutput(), dmcreset();
63665984
BJ
66struct uba_device *dmcinfo[NDMC];
67u_short dmcstd[] = { 0 };
68struct uba_driver dmcdriver =
69 { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
70
032f82b3 71#define NRCV 7
ba0b299a 72#define NXMT 3
822a4f2c 73#define NCMDS (NRCV+NXMT+4) /* size of command queue */
ba0b299a
MK
74
75#define printd if(dmcdebug)printf
76int dmcdebug = 0;
032f82b3
TF
77
78/* error reporting intervals */
79#define DMC_RPNBFS 50
80#define DMC_RPDSC 1
ba0b299a
MK
81#define DMC_RPTMO 10
82#define DMC_RPDCK 10
032f82b3
TF
83
84struct dmc_command {
85 char qp_cmd; /* command */
86 short qp_ubaddr; /* buffer address */
87 short qp_cc; /* character count || XMEM */
88 struct dmc_command *qp_next; /* next command on queue */
89};
90
032f82b3
TF
91struct dmcbufs {
92 int ubinfo; /* from uballoc */
93 short cc; /* buffer size */
94 short flags; /* access control */
95};
96#define DBUF_OURS 0 /* buffer is available */
97#define DBUF_DMCS 1 /* buffer claimed by somebody */
98#define DBUF_XMIT 4 /* transmit buffer */
ba0b299a 99#define DBUF_RCV 8 /* receive buffer */
032f82b3 100
032f82b3 101
63665984
BJ
102/*
103 * DMC software status per interface.
104 *
105 * Each interface is referenced by a network interface structure,
106 * sc_if, which the routing code uses to locate the interface.
107 * This structure contains the output queue for the interface, its address, ...
032f82b3
TF
108 * We also have, for each interface, a set of 7 UBA interface structures
109 * for each, which
110 * contain information about the UNIBUS resources held by the interface:
63665984
BJ
111 * map registers, buffered data paths, etc. Information is cached in this
112 * structure for use by the if_uba.c routines in running the interface
113 * efficiently.
114 */
115struct dmc_softc {
032f82b3
TF
116 short sc_oused; /* output buffers currently in use */
117 short sc_iused; /* input buffers given to DMC */
63665984 118 short sc_flag; /* flags */
ba0b299a 119 int sc_nticks; /* seconds since last interrupt */
032f82b3 120 struct ifnet sc_if; /* network-visible interface */
ba0b299a 121 struct dmcbufs sc_rbufs[NRCV]; /* receive buffer info */
032f82b3 122 struct dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */
822a4f2c
MK
123 struct ifubinfo sc_ifuba; /* UNIBUS resources */
124 struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */
125 struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */
63665984 126 int sc_ubinfo; /* UBA mapping info for base table */
032f82b3
TF
127 int sc_errors[4]; /* non-fatal error counters */
128#define sc_datck sc_errors[0]
129#define sc_timeo sc_errors[1]
130#define sc_nobuf sc_errors[2]
131#define sc_disc sc_errors[3]
132 /* command queue stuff */
ba0b299a 133 struct dmc_command sc_cmdbuf[NCMDS];
032f82b3
TF
134 struct dmc_command *sc_qhead; /* head of command queue */
135 struct dmc_command *sc_qtail; /* tail of command queue */
136 struct dmc_command *sc_qactive; /* command in progress */
137 struct dmc_command *sc_qfreeh; /* head of list of free cmd buffers */
138 struct dmc_command *sc_qfreet; /* tail of list of free cmd buffers */
139 /* end command queue stuff */
63665984
BJ
140} dmc_softc[NDMC];
141
142/* flags */
ba0b299a
MK
143#define DMC_ALLOC 01 /* unibus resources allocated */
144#define DMC_BMAPPED 02 /* base table mapped */
145#define DMC_RESTART 04 /* software restart in progress */
146#define DMC_ACTIVE 08 /* device active */
63665984 147
ba0b299a
MK
148struct dmc_base {
149 short d_base[128]; /* DMC base table */
63665984
BJ
150} dmc_base[NDMC];
151
032f82b3
TF
152/* queue manipulation macros */
153#define QUEUE_AT_HEAD(qp, head, tail) \
154 (qp)->qp_next = (head); \
155 (head) = (qp); \
156 if ((tail) == (struct dmc_command *) 0) \
157 (tail) = (head)
158
159#define QUEUE_AT_TAIL(qp, head, tail) \
160 if ((tail)) \
161 (tail)->qp_next = (qp); \
162 else \
163 (head) = (qp); \
164 (qp)->qp_next = (struct dmc_command *) 0; \
165 (tail) = (qp)
166
167#define DEQUEUE(head, tail) \
168 (head) = (head)->qp_next;\
169 if ((head) == (struct dmc_command *) 0)\
170 (tail) = (head)
63665984
BJ
171
172dmcprobe(reg)
173 caddr_t reg;
174{
175 register int br, cvec;
176 register struct dmcdevice *addr = (struct dmcdevice *)reg;
177 register int i;
178
179#ifdef lint
180 br = 0; cvec = br; br = cvec;
181 dmcrint(0); dmcxint(0);
182#endif
183 addr->bsel1 = DMC_MCLR;
184 for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
185 ;
ba0b299a
MK
186 if ((addr->bsel1 & DMC_RUN) == 0) {
187 printf("dmcprobe: can't start device\n" );
ee787340 188 return (0);
ba0b299a 189 }
63665984 190 addr->bsel0 = DMC_RQI|DMC_IEI;
ba0b299a
MK
191 /* let's be paranoid */
192 addr->bsel0 |= DMC_RQI|DMC_IEI;
193 DELAY(1000000);
63665984
BJ
194 addr->bsel1 = DMC_MCLR;
195 for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
196 ;
ee787340 197 return (1);
63665984
BJ
198}
199
200/*
201 * Interface exists: make available by filling in network interface
202 * record. System will initialize the interface when it is ready
203 * to accept packets.
204 */
205dmcattach(ui)
206 register struct uba_device *ui;
207{
208 register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
209
210 sc->sc_if.if_unit = ui->ui_unit;
211 sc->sc_if.if_name = "dmc";
212 sc->sc_if.if_mtu = DMCMTU;
63665984
BJ
213 sc->sc_if.if_init = dmcinit;
214 sc->sc_if.if_output = dmcoutput;
17718098 215 sc->sc_if.if_ioctl = dmcioctl;
51595ca2 216 sc->sc_if.if_reset = dmcreset;
032f82b3 217 sc->sc_if.if_flags = IFF_POINTOPOINT;
822a4f2c 218 sc->sc_ifuba.iff_flags = UBA_CANTWAIT;
032f82b3 219
ba0b299a
MK
220 if (dmctimer == 0) {
221 dmctimer = 1;
222 timeout(dmcwatch, (caddr_t) 0, hz);
223 }
822a4f2c 224 if_attach(&sc->sc_if);
63665984
BJ
225}
226
227/*
228 * Reset of interface after UNIBUS reset.
7f0e1e06 229 * If interface is on specified UBA, reset its state.
63665984
BJ
230 */
231dmcreset(unit, uban)
232 int unit, uban;
233{
234 register struct uba_device *ui;
032f82b3 235 register struct dmc_softc *sc = &dmc_softc[unit];
63665984
BJ
236
237 if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
238 ui->ui_ubanum != uban)
239 return;
240 printf(" dmc%d", unit);
ba0b299a 241 sc->sc_flag = 0;
7f0e1e06 242 sc->sc_if.if_flags &= ~IFF_RUNNING;
63665984
BJ
243 dmcinit(unit);
244}
245
246/*
247 * Initialization of interface; reinitialize UNIBUS usage.
248 */
249dmcinit(unit)
250 int unit;
251{
252 register struct dmc_softc *sc = &dmc_softc[unit];
253 register struct uba_device *ui = dmcinfo[unit];
254 register struct dmcdevice *addr;
17718098 255 register struct ifnet *ifp = &sc->sc_if;
032f82b3
TF
256 register struct ifrw *ifrw;
257 register struct ifxmt *ifxp;
258 register struct dmcbufs *rp;
ba0b299a 259 register struct dmc_command *qp;
7f0e1e06 260 struct ifaddr *ifa;
63665984 261 int base;
ba0b299a 262 int s;
63665984 263
032f82b3
TF
264 addr = (struct dmcdevice *)ui->ui_addr;
265
7f0e1e06
MK
266 /*
267 * Check to see that an address has been set
268 * (both local and destination for an address family).
269 */
270 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
271 if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family)
272 break;
273 if (ifa == (struct ifaddr *) 0)
032f82b3
TF
274 return;
275
276 if ((addr->bsel1&DMC_RUN) == 0) {
277 printf("dmcinit: DMC not running\n");
7f0e1e06 278 ifp->if_flags &= ~IFF_UP;
032f82b3
TF
279 return;
280 }
281 /* map base table */
ba0b299a 282 if ((sc->sc_flag & DMC_BMAPPED) == 0) {
032f82b3
TF
283 sc->sc_ubinfo = uballoc(ui->ui_ubanum,
284 (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0);
285 sc->sc_flag |= DMC_BMAPPED;
286 }
287 /* initialize UNIBUS resources */
288 sc->sc_iused = sc->sc_oused = 0;
7f0e1e06 289 if ((ifp->if_flags & IFF_RUNNING) == 0) {
822a4f2c
MK
290 if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum,
291 sizeof(struct dmc_header), (int)btoc(DMCMTU),
292 sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) {
7f0e1e06 293 printf("dmc%d: can't allocate uba resources\n", unit);
17718098
SL
294 ifp->if_flags &= ~IFF_UP;
295 return;
296 }
7f0e1e06 297 ifp->if_flags |= IFF_RUNNING;
032f82b3
TF
298 }
299
300 /* initialize buffer pool */
ba0b299a 301 /* receives */
822a4f2c 302 ifrw = &sc->sc_ifr[0];
032f82b3
TF
303 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
304 rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
ba0b299a 305 rp->cc = DMCMTU + sizeof (struct dmc_header);
032f82b3 306 rp->flags = DBUF_OURS|DBUF_RCV;
032f82b3 307 ifrw++;
63665984 308 }
032f82b3 309 /* transmits */
822a4f2c 310 ifxp = &sc->sc_ifw[0];
032f82b3 311 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
822a4f2c 312 rp->ubinfo = ifxp->ifw_info & 0x3ffff;
032f82b3
TF
313 rp->cc = 0;
314 rp->flags = DBUF_OURS|DBUF_XMIT;
032f82b3 315 ifxp++;
f6311fb6 316 }
ba0b299a
MK
317
318 /* set up command queues */
319 sc->sc_qfreeh = sc->sc_qfreet
320 = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive =
321 (struct dmc_command *)0;
322 /* set up free command buffer list */
323 for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) {
324 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
325 }
326
032f82b3
TF
327 /* base in */
328 base = sc->sc_ubinfo & 0x3ffff;
ba0b299a 329 dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM);
032f82b3
TF
330 /* specify half duplex operation, flags tell if primary */
331 /* or secondary station */
332 if (ui->ui_flags == 0)
ba0b299a
MK
333 /* use DDMCP mode in full duplex */
334 dmcload(sc, DMC_CNTLI, 0, 0);
032f82b3 335 else if (ui->ui_flags == 1)
ba0b299a
MK
336 /* use MAINTENENCE mode */
337 dmcload(sc, DMC_CNTLI, 0, DMC_MAINT );
032f82b3
TF
338 else if (ui->ui_flags == 2)
339 /* use DDCMP half duplex as primary station */
340 dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX);
341 else if (ui->ui_flags == 3)
342 /* use DDCMP half duplex as secondary station */
343 dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC);
ba0b299a
MK
344
345 /* enable operation done interrupts */
346 sc->sc_flag &= ~DMC_ACTIVE;
347 while ((addr->bsel2 & DMC_IEO) == 0)
348 addr->bsel2 |= DMC_IEO;
349 s = spl5();
032f82b3
TF
350 /* queue first NRCV buffers for DMC to fill */
351 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
352 rp->flags |= DBUF_DMCS;
353 dmcload(sc, DMC_READ, rp->ubinfo,
ba0b299a 354 (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc));
032f82b3
TF
355 sc->sc_iused++;
356 }
ba0b299a 357 splx(s);
63665984
BJ
358}
359
360/*
361 * Start output on interface. Get another datagram
362 * to send from the interface queue and map it to
363 * the interface before starting output.
032f82b3
TF
364 *
365 * Must be called at spl 5
63665984
BJ
366 */
367dmcstart(dev)
368 dev_t dev;
369{
370 int unit = minor(dev);
63665984 371 register struct dmc_softc *sc = &dmc_softc[unit];
63665984 372 struct mbuf *m;
032f82b3
TF
373 register struct dmcbufs *rp;
374 register int n;
63665984 375
63665984 376 /*
032f82b3
TF
377 * Dequeue up to NXMT requests and map them to the UNIBUS.
378 * If no more requests, or no dmc buffers available, just return.
63665984 379 */
032f82b3
TF
380 n = 0;
381 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) {
382 /* find an available buffer */
ba0b299a 383 if ((rp->flags & DBUF_DMCS) == 0) {
032f82b3
TF
384 IF_DEQUEUE(&sc->sc_if.if_snd, m);
385 if (m == 0)
386 return;
032f82b3
TF
387 /* mark it dmcs */
388 rp->flags |= (DBUF_DMCS);
389 /*
390 * Have request mapped to UNIBUS for transmission
391 * and start the output.
392 */
822a4f2c 393 rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m);
ba0b299a 394 rp->cc &= DMC_CCOUNT;
032f82b3
TF
395 sc->sc_oused++;
396 dmcload(sc, DMC_WRITE, rp->ubinfo,
397 rp->cc | ((rp->ubinfo>>2)&DMC_XMEM));
398 }
399 n++;
400 }
63665984
BJ
401}
402
403/*
404 * Utility routine to load the DMC device registers.
405 */
406dmcload(sc, type, w0, w1)
407 register struct dmc_softc *sc;
408 int type, w0, w1;
409{
410 register struct dmcdevice *addr;
032f82b3
TF
411 register int unit, sps;
412 register struct dmc_command *qp;
63665984 413
ba0b299a 414 unit = sc - dmc_softc;
63665984
BJ
415 addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
416 sps = spl5();
032f82b3
TF
417
418 /* grab a command buffer from the free list */
419 if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0)
420 panic("dmc command queue overflow");
421 DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);
422
423 /* fill in requested info */
424 qp->qp_cmd = (type | DMC_RQI);
425 qp->qp_ubaddr = w0;
426 qp->qp_cc = w1;
427
428 if (sc->sc_qactive) { /* command in progress */
429 if (type == DMC_READ) {
430 QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);
431 } else {
432 QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);
433 }
434 } else { /* command port free */
435 sc->sc_qactive = qp;
436 addr->bsel0 = qp->qp_cmd;
63665984 437 dmcrint(unit);
032f82b3 438 }
63665984
BJ
439 splx(sps);
440}
441
442/*
443 * DMC interface receiver interrupt.
444 * Ready to accept another command,
445 * pull one off the command queue.
446 */
447dmcrint(unit)
448 int unit;
449{
450 register struct dmc_softc *sc;
451 register struct dmcdevice *addr;
032f82b3 452 register struct dmc_command *qp;
63665984 453 register int n;
63665984
BJ
454
455 addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
456 sc = &dmc_softc[unit];
032f82b3 457 if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) {
ba0b299a 458 printf("dmc%d: dmcrint no command\n", unit);
032f82b3
TF
459 return;
460 }
63665984 461 while (addr->bsel0&DMC_RDYI) {
032f82b3
TF
462 addr->sel4 = qp->qp_ubaddr;
463 addr->sel6 = qp->qp_cc;
63665984 464 addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
032f82b3
TF
465 /* free command buffer */
466 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
467 while (addr->bsel0 & DMC_RDYI) {
468 /*
469 * Can't check for RDYO here 'cause
470 * this routine isn't reentrant!
471 */
472 DELAY(5);
473 }
474 /* move on to next command */
ba0b299a
MK
475 if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0)
476 break; /* all done */
032f82b3
TF
477 /* more commands to do, start the next one */
478 qp = sc->sc_qactive;
479 DEQUEUE(sc->sc_qhead, sc->sc_qtail);
480 addr->bsel0 = qp->qp_cmd;
63665984 481 n = RDYSCAN;
ba0b299a
MK
482 while (n-- > 0)
483 if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO))
484 break;
032f82b3
TF
485 }
486 if (sc->sc_qactive) {
487 addr->bsel0 |= DMC_IEI|DMC_RQI;
488 /* VMS does it twice !*$%@# */
489 addr->bsel0 |= DMC_IEI|DMC_RQI;
63665984 490 }
ba0b299a 491
63665984
BJ
492}
493
494/*
495 * DMC interface transmitter interrupt.
032f82b3 496 * A transfer may have completed, check for errors.
63665984
BJ
497 * If it was a read, notify appropriate protocol.
498 * If it was a write, pull the next one off the queue.
499 */
500dmcxint(unit)
501 int unit;
502{
503 register struct dmc_softc *sc;
abcd48c6 504 register struct ifnet *ifp;
63665984
BJ
505 struct uba_device *ui = dmcinfo[unit];
506 struct dmcdevice *addr;
507 struct mbuf *m;
ba0b299a 508 struct ifqueue *inq;
032f82b3
TF
509 int arg, pkaddr, cmd, len;
510 register struct ifrw *ifrw;
511 register struct dmcbufs *rp;
ba0b299a
MK
512 register struct ifxmt *ifxp;
513 struct dmc_header *dh;
514 int off, resid;
63665984
BJ
515
516 addr = (struct dmcdevice *)ui->ui_addr;
63665984 517 sc = &dmc_softc[unit];
abcd48c6 518 ifp = &sc->sc_if;
032f82b3 519
ba0b299a
MK
520 while (addr->bsel2 & DMC_RDYO) {
521
522 cmd = addr->bsel2 & 0xff;
523 arg = addr->sel6 & 0xffff;
524 /* reconstruct UNIBUS address of buffer returned to us */
525 pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff);
526 /* release port */
527 addr->bsel2 &= ~DMC_RDYO;
528 switch (cmd & 07) {
529
530 case DMC_OUR:
531 /*
532 * A read has completed.
533 * Pass packet to type specific
534 * higher-level input routine.
535 */
536 ifp->if_ipackets++;
537 /* find location in dmcuba struct */
822a4f2c 538 ifrw= &sc->sc_ifr[0];
ba0b299a
MK
539 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
540 if(rp->ubinfo == pkaddr)
541 break;
542 ifrw++;
543 }
544 if (rp >= &sc->sc_rbufs[NRCV])
545 panic("dmc rcv");
546 if ((rp->flags & DBUF_DMCS) == 0)
547 printf("dmc%d: done unalloc rbuf\n", unit);
548
549 len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header);
550 if (len < 0 || len > DMCMTU) {
551 ifp->if_ierrors++;
552 printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n",
553 unit, pkaddr, len);
554 goto setup;
555 }
556 /*
557 * Deal with trailer protocol: if type is trailer
558 * get true type from first 16-bit word past data.
559 * Remember that type was trailer by setting off.
560 */
561 dh = (struct dmc_header *)ifrw->ifrw_addr;
562 dh->dmc_type = ntohs((u_short)dh->dmc_type);
563#define dmcdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off))))
564 if (dh->dmc_type >= DMC_TRAILER &&
565 dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) {
566 off = (dh->dmc_type - DMC_TRAILER) * 512;
567 if (off >= DMCMTU)
568 goto setup; /* sanity */
569 dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *));
570 resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *)));
571 if (off + resid > len)
572 goto setup; /* sanity */
573 len = off + resid;
574 } else
575 off = 0;
576 if (len == 0)
577 goto setup;
578
579 /*
580 * Pull packet off interface. Off is nonzero if
581 * packet has trailing header; dmc_get will then
582 * force this header information to be at the front,
583 * but we still have to drop the type and length
584 * which are at the front of any trailer data.
585 */
822a4f2c 586 m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp);
ba0b299a
MK
587 if (m == 0)
588 goto setup;
589 if (off) {
822a4f2c
MK
590 struct ifnet *ifp;
591
592 ifp = *(mtod(m, struct ifnet **));
ba0b299a
MK
593 m->m_off += 2 * sizeof (u_short);
594 m->m_len -= 2 * sizeof (u_short);
822a4f2c 595 *(mtod(m, struct ifnet **)) = ifp;
ba0b299a
MK
596 }
597 switch (dh->dmc_type) {
63665984 598
63665984 599#ifdef INET
ba0b299a
MK
600 case DMC_IPTYPE:
601 schednetisr(NETISR_IP);
602 inq = &ipintrq;
603 break;
63665984 604#endif
ba0b299a
MK
605 default:
606 m_freem(m);
607 goto setup;
608 }
63665984 609
ba0b299a
MK
610 if (IF_QFULL(inq)) {
611 IF_DROP(inq);
612 m_freem(m);
613 } else
614 IF_ENQUEUE(inq, m);
032f82b3 615
ba0b299a
MK
616 setup:
617 /* is this needed? */
618 rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
63665984 619
ba0b299a
MK
620 dmcload(sc, DMC_READ, rp->ubinfo,
621 ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc);
622 break;
63665984 623
ba0b299a
MK
624 case DMC_OUX:
625 /*
626 * A write has completed, start another
627 * transfer if there is more data to send.
628 */
629 ifp->if_opackets++;
630 /* find associated dmcbuf structure */
822a4f2c 631 ifxp = &sc->sc_ifw[0];
ba0b299a
MK
632 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
633 if(rp->ubinfo == pkaddr)
634 break;
635 ifxp++;
636 }
637 if (rp >= &sc->sc_xbufs[NXMT]) {
638 printf("dmc%d: bad packet address 0x%x\n",
639 unit, pkaddr);
640 break;
641 }
642 if ((rp->flags & DBUF_DMCS) == 0)
643 printf("dmc%d: unallocated packet 0x%x\n",
644 unit, pkaddr);
645 /* mark buffer free */
822a4f2c
MK
646 if (ifxp->ifw_xtofree) {
647 (void)m_freem(ifxp->ifw_xtofree);
648 ifxp->ifw_xtofree = 0;
ba0b299a
MK
649 }
650 rp->flags &= ~DBUF_DMCS;
651 sc->sc_oused--;
652 sc->sc_nticks = 0;
653 sc->sc_flag |= DMC_ACTIVE;
032f82b3 654 break;
ba0b299a
MK
655
656 case DMC_CNTLO:
657 arg &= DMC_CNTMASK;
658 if (arg & DMC_FATAL) {
659 printd("dmc%d: fatal error, flags=%b\n",
660 unit, arg, CNTLO_BITS);
ba0b299a
MK
661 dmcrestart(unit);
662 break;
663 }
664 /* ACCUMULATE STATISTICS */
032f82b3
TF
665 switch(arg) {
666 case DMC_NOBUFS:
ba0b299a
MK
667 ifp->if_ierrors++;
668 if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0)
669 goto report;
670 break;
032f82b3 671 case DMC_DISCONN:
ba0b299a
MK
672 if ((sc->sc_disc++ % DMC_RPDSC) == 0)
673 goto report;
674 break;
032f82b3 675 case DMC_TIMEOUT:
ba0b299a
MK
676 if ((sc->sc_timeo++ % DMC_RPTMO) == 0)
677 goto report;
678 break;
032f82b3 679 case DMC_DATACK:
ba0b299a
MK
680 ifp->if_oerrors++;
681 if ((sc->sc_datck++ % DMC_RPDCK) == 0)
682 goto report;
683 break;
032f82b3
TF
684 default:
685 goto report;
686 }
687 break;
688 report:
ba0b299a
MK
689 printd("dmc%d: soft error, flags=%b\n", unit,
690 arg, CNTLO_BITS);
691 if ((sc->sc_flag & DMC_RESTART) == 0) {
692 /*
693 * kill off the dmc to get things
694 * going again by generating a
695 * procedure error
696 */
697 sc->sc_flag |= DMC_RESTART;
698 arg = sc->sc_ubinfo & 0x3ffff;
699 dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);
700 }
701 break;
63665984 702
ba0b299a
MK
703 default:
704 printf("dmc%d: bad control %o\n", unit, cmd);
705 break;
706 }
63665984 707 }
ba0b299a 708 dmcstart(unit);
032f82b3 709 return;
63665984
BJ
710}
711
712/*
713 * DMC output routine.
ba0b299a
MK
714 * Encapsulate a packet of type family for the dmc.
715 * Use trailer local net encapsulation if enough data in first
716 * packet leaves a multiple of 512 bytes of data in remainder.
63665984 717 */
ba0b299a 718dmcoutput(ifp, m0, dst)
63665984 719 register struct ifnet *ifp;
ba0b299a 720 register struct mbuf *m0;
ee787340 721 struct sockaddr *dst;
63665984 722{
ba0b299a
MK
723 int type, error, s;
724 register struct mbuf *m = m0;
725 register struct dmc_header *dh;
726 register int off;
727
728 switch (dst->sa_family) {
729#ifdef INET
730 case AF_INET:
731 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
732 if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
733 if (off > 0 && (off & 0x1ff) == 0 &&
734 m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
735 type = DMC_TRAILER + (off>>9);
736 m->m_off -= 2 * sizeof (u_short);
737 m->m_len += 2 * sizeof (u_short);
738 *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE);
739 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
740 goto gottrailertype;
741 }
742 type = DMC_IPTYPE;
743 off = 0;
744 goto gottype;
745#endif
63665984 746
ba0b299a
MK
747 case AF_UNSPEC:
748 dh = (struct dmc_header *)dst->sa_data;
749 type = dh->dmc_type;
750 goto gottype;
751
752 default:
753 printf("dmc%d: can't handle af%d\n", ifp->if_unit,
754 dst->sa_family);
755 error = EAFNOSUPPORT;
756 goto bad;
63665984 757 }
ba0b299a
MK
758
759gottrailertype:
760 /*
761 * Packet to be sent as a trailer; move first packet
762 * (control information) to end of chain.
763 */
764 while (m->m_next)
765 m = m->m_next;
766 m->m_next = m0;
767 m = m0->m_next;
768 m0->m_next = 0;
769 m0 = m;
770
771gottype:
772 /*
773 * Add local network header
774 * (there is space for a uba on a vax to step on)
775 */
776 if (m->m_off > MMAXOFF ||
777 MMINOFF + sizeof(struct dmc_header) > m->m_off) {
778 m = m_get(M_DONTWAIT, MT_HEADER);
779 if (m == 0) {
780 error = ENOBUFS;
781 goto bad;
782 }
783 m->m_next = m0;
784 m->m_off = MMINOFF;
785 m->m_len = sizeof (struct dmc_header);
786 } else {
787 m->m_off -= sizeof (struct dmc_header);
788 m->m_len += sizeof (struct dmc_header);
789 }
790 dh = mtod(m, struct dmc_header *);
791 dh->dmc_type = htons((u_short)type);
792
793 /*
794 * Queue message on interface, and start output if interface
795 * not yet active.
796 */
797 s = splimp();
1e977657
BJ
798 if (IF_QFULL(&ifp->if_snd)) {
799 IF_DROP(&ifp->if_snd);
ee787340 800 m_freem(m);
1e977657 801 splx(s);
8a2f82db 802 return (ENOBUFS);
1e977657 803 }
63665984 804 IF_ENQUEUE(&ifp->if_snd, m);
032f82b3 805 dmcstart(ifp->if_unit);
63665984 806 splx(s);
8a2f82db 807 return (0);
ba0b299a
MK
808
809bad:
810 m_freem(m0);
811 return (error);
63665984 812}
17718098 813
ba0b299a 814
17718098
SL
815/*
816 * Process an ioctl request.
817 */
822a4f2c 818/* ARGSUSED */
17718098
SL
819dmcioctl(ifp, cmd, data)
820 register struct ifnet *ifp;
821 int cmd;
822 caddr_t data;
823{
17718098
SL
824 int s = splimp(), error = 0;
825
826 switch (cmd) {
827
828 case SIOCSIFADDR:
032f82b3 829 ifp->if_flags |= IFF_UP;
7f0e1e06
MK
830 if ((ifp->if_flags & IFF_RUNNING) == 0)
831 dmcinit(ifp->if_unit);
17718098
SL
832 break;
833
834 case SIOCSIFDSTADDR:
7f0e1e06
MK
835 if ((ifp->if_flags & IFF_RUNNING) == 0)
836 dmcinit(ifp->if_unit);
17718098 837 break;
032f82b3 838
17718098
SL
839 default:
840 error = EINVAL;
841 }
842 splx(s);
843 return (error);
844}
032f82b3 845
ba0b299a
MK
846/*
847 * Restart after a fatal error.
848 * Clear device and reinitialize.
849 */
850dmcrestart(unit)
851 int unit;
852{
853 register struct dmc_softc *sc = &dmc_softc[unit];
854 register struct uba_device *ui = dmcinfo[unit];
855 register struct dmcdevice *addr;
856 register struct ifxmt *ifxp;
857 register int i;
822a4f2c 858 struct ifubinfo *ifu;
ba0b299a
MK
859
860 addr = (struct dmcdevice *)ui->ui_addr;
861 ifu = &sc->sc_ifuba;
862#ifdef DEBUG
863 /* dump base table */
864 printf("dmc%d base table:\n", unit);
865 for (i = 0; i < sizeof (struct dmc_base); i++)
866 printf("%o\n" ,dmc_base[unit].d_base[i]);
867#endif
868 /*
869 * Let the DMR finish the MCLR. At 1 Mbit, it should do so
870 * in about a max of 6.4 milliseconds with diagnostics enabled.
871 */
872 addr->bsel1 = DMC_MCLR;
873 for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
874 ;
875 /* Did the timer expire or did the DMR finish? */
876 if ((addr->bsel1 & DMC_RUN) == 0) {
877 printf("dmc%d: M820 Test Failed\n", unit);
878 return;
879 }
880
822a4f2c
MK
881 for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) {
882 if (ifxp->ifw_xtofree) {
883 (void) m_freem(ifxp->ifw_xtofree);
884 ifxp->ifw_xtofree = 0;
ba0b299a
MK
885 }
886 }
887
888 /* restart DMC */
889 dmcinit(unit);
890 sc->sc_flag &= ~DMC_RESTART;
891 sc->sc_if.if_collisions++; /* why not? */
892}
893
894/*
895 * Check to see that transmitted packets don't
896 * lose interrupts. The device has to be active.
897 */
898dmcwatch()
899{
900 register struct uba_device *ui;
901 register struct dmc_softc *sc;
902 struct dmcdevice *addr;
903 register int i;
904
905 for (i = 0; i < NDMC; i++) {
906 sc = &dmc_softc[i];
907 if ((sc->sc_flag & DMC_ACTIVE) == 0)
908 continue;
909 if ((ui = dmcinfo[i]) == 0 || ui->ui_alive == 0)
910 continue;
911 if (sc->sc_oused) {
912 sc->sc_nticks++;
913 if (sc->sc_nticks > dmc_timeout) {
914 sc->sc_nticks = 0;
915 addr = (struct dmcdevice *)ui->ui_addr;
916 printd("dmc%d hung: bsel0=%b bsel2=%b\n", i,
917 addr->bsel0 & 0xff, DMC0BITS,
918 addr->bsel2 & 0xff, DMC2BITS);
919 dmcrestart(i);
920 }
921 }
922 }
923 timeout(dmcwatch, (caddr_t) 0, hz);
924}
44eb2da3 925#endif