1 /*
2 * Copyright (c) 1982, 1986 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 * @(#)dmf.c 7.15 (Berkeley) 05/16/91
7 */
8
9 /*
10 * DMF32 driver
11 *
12 *
13 * TODO:
14 * test with modem
15 * load as much as possible into silo
16 * use auto XON/XOFF
17 * test reset code
18 */
19 #include "dmf.h"
20 #if NDMF > 0
21
22 #ifndef NDMF_LP
23 #define NDMF_LP NDMF
24 #endif NDMF_LP
25 #include "../include/pte.h"
26
27 #include "sys/param.h"
28 #include "uba.h"
29 #include "sys/conf.h"
30 #include "sys/user.h"
31 #include "sys/proc.h"
32 #include "sys/ioctl.h"
33 #include "sys/tty.h"
34 #include "sys/map.h"
35 #include "sys/buf.h"
36 #include "sys/vm.h"
37 #include "sys/clist.h"
38 #include "sys/file.h"
39 #include "sys/uio.h"
40 #include "sys/kernel.h"
41 #include "sys/syslog.h"
42
43 #include "dmx.h"
44 #include "ubareg.h"
45 #include "ubavar.h"
46 #include "dmxreg.h"
47 #include "dmfreg.h"
48 #include "dmreg.h"
49
50 extern int dmx_timeout; /* silo timeout, in ms */
51 int dmfstart();
52
53 /*
54 * The clist space is mapped by one terminal driver onto each UNIBUS.
55 * The identity of the board which allocated resources is recorded,
56 * so the process may be repeated after UNIBUS resets.
57 * The UBACVT macro converts a clist space address for unibus uban
58 * into an i/o space address for the DMA routine.
59 */
60 int dmf_uballoc[NUBA]; /* which dmf (if any) allocated unibus map */
61 int cbase[NUBA]; /* base address of clists in unibus map */
62
63 /*
64 * Autoconfiguration and variables for DMF32
65 */
66 int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
67 int dmflint();
68 struct uba_device *dmfinfo[NDMF];
69 u_short dmfstd[] = { 0 };
70 struct uba_driver dmfdriver =
71 { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
72
73 struct tty dmf_tty[NDMF*8];
74 struct dmx_softc dmf_softc[NDMF];
75 #ifndef lint
76 int ndmf = NDMF*8; /* used by iostat */
77 #endif
78
79 /*
80 * Routine for configuration to set dmf interrupt.
81 */
82 /*ARGSUSED*/
dmfprobe(reg,ctlr)83 dmfprobe(reg, ctlr)
84 caddr_t reg;
85 struct uba_device *ctlr;
86 {
87 register int br, cvec; /* these are ``value-result'' */
88 register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
89 register int i;
90 register unsigned int a;
91 static char *dmfdevs[]=
92 {"parallel","printer","synch","asynch"};
93 unsigned int dmfoptions;
94 static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
95
96 #ifdef lint
97 br = 0; cvec = br; br = cvec;
98 dmfxint(0); dmfrint(0);
99 dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
100 #endif
101 /*
102 * Pick the usual size DMF vector here (don't decrement it here).
103 * grab configuration; note that the DMF32
104 * doesn't seem to put the right bits in this
105 * register until AFTER the interrupt vector is set.
106 */
107 br = 0x15;
108 cvec = (uba_hd[numuba].uh_lastiv - 4*8);
109 dmfaddr->dmfccsr0 = (cvec >> 2);
110 dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
111
112 /* catch a couple of special cases: Able vmz/32n and vmz/lp */
113 if (dmfoptions == DMFC_ASYNC) {
114 /* Async portion only */
115
116 cvec = (uba_hd[numuba].uh_lastiv -= 8);
117 dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
118 intrv[0] = ctlr->ui_intr[4];
119 intrv[1] = ctlr->ui_intr[5];
120 ctlr->ui_intr = intrv;
121 } else if (dmfoptions == DMFC_LP) {
122 /* LP portion only */
123
124 cvec = (uba_hd[numuba].uh_lastiv -= 8);
125 ctlr->ui_intr = &ctlr->ui_intr[6];
126 } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
127 /* LP and Async portions only */
128
129 cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
130 ctlr->ui_intr = &ctlr->ui_intr[4];
131 } else {
132 /* All other configurations get everything */
133
134 cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
135 }
136 a = (dmfoptions >> 12) & 0xf;
137 printf("dmf%d:", ctlr->ui_unit);
138 for (i = 0; a != 0; ++i, a >>= 1) {
139 if (a & 1)
140 printf(" %s",dmfdevs[i]);
141 }
142 printf(".\n");
143
144 if (dmfoptions & DMFC_LP)
145 dmfaddr->dmfl_ctrl = DMFL_RESET;
146 return (sizeof (struct dmfdevice));
147 }
148
149 /*
150 * Routine called to attach a dmf.
151 */
dmfattach(ui)152 dmfattach(ui)
153 register struct uba_device *ui;
154 {
155 register struct dmx_softc *sc;
156
157 sc = &dmf_softc[ui->ui_unit];
158 sc->dmx_type = 'f';
159 sc->dmx_unit = ui->ui_unit;
160 sc->dmx_unit0 = 0;
161 sc->dmx_ubanum = ui->ui_ubanum;
162 sc->dmx_softCAR = ui->ui_flags & 0xff;
163 sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
164 sc->dmx_octet =
165 (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
166
167 cbase[ui->ui_ubanum] = -1;
168 dmf_uballoc[ui->ui_ubanum] = -1;
169 #if NDMF_LP > 0
170 dmflattach(ui);
171 #endif NDMF_LP
172 }
173
174 /*
175 * Open a DMF32 line, mapping the clist onto the uba if this
176 * is the first dmf on this uba. Turn on this dmf if this is
177 * the first use of it.
178 */
179 /*ARGSUSED*/
dmfopen(dev,flag)180 dmfopen(dev, flag)
181 dev_t dev;
182 {
183 register struct tty *tp;
184 register struct dmx_softc *sc;
185 int unit, dmf;
186 register struct dmfdevice *addr;
187 register struct uba_device *ui;
188 int s;
189 int dmxparam();
190
191 unit = minor(dev);
192 if (unit & 0200)
193 return (dmflopen(dev,flag));
194 dmf = unit >> 3;
195 if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
196 return (ENXIO);
197
198 tp = &dmf_tty[unit];
199 sc = &dmf_softc[dmf];
200 addr = (struct dmfdevice *)ui->ui_addr;
201 tp->t_addr = (caddr_t)(&addr->dmfa);
202 tp->t_oproc = dmfstart;
203 tp->t_dev = dev; /* needed before dmxopen */
204 tp->t_param = dmxparam;
205
206 /*
207 * While setting up state for this uba,
208 * block uba resets which can clear the state.
209 */
210 s = spl6();
211 if (cbase[ui->ui_ubanum] == -1) {
212 dmf_uballoc[ui->ui_ubanum] = dmf;
213 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
214 (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
215 }
216 splx(s);
217
218 return (dmxopen(tp, sc, flag));
219 }
220
221 /*
222 * Close a DMF32 line.
223 */
224 /*ARGSUSED*/
dmfclose(dev,flag,mode,p)225 dmfclose(dev, flag, mode, p)
226 dev_t dev;
227 int flag, mode;
228 struct proc *p;
229 {
230 register unit;
231
232 unit = minor(dev);
233 if (unit & 0200) {
234 dmflclose(dev, flag);
235 return;
236 }
237 return (dmxclose(&dmf_tty[unit]), flag);
238 }
239
dmfread(dev,uio,flag)240 dmfread(dev, uio, flag)
241 dev_t dev;
242 struct uio *uio;
243 {
244 register struct tty *tp;
245
246 if (minor(dev) & 0200)
247 return(ENXIO);
248 tp = &dmf_tty[minor(dev)];
249 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
250 }
251
dmfwrite(dev,uio)252 dmfwrite(dev, uio)
253 dev_t dev;
254 struct uio *uio;
255 {
256 register struct tty *tp;
257
258 if (minor(dev) & 0200)
259 return (dmflwrite(dev,uio));
260 tp = &dmf_tty[minor(dev)];
261 return ((*linesw[tp->t_line].l_write)(tp, uio));
262 }
263
264 /*
265 * DMF32 receiver interrupt.
266 */
dmfrint(dmf)267 dmfrint(dmf)
268 int dmf;
269 {
270 struct uba_device *ui;
271
272 ui = dmfinfo[dmf];
273 if (ui == 0 || ui->ui_alive == 0)
274 return;
275 dmxrint(&dmf_softc[dmf]);
276 }
277
278 /*
279 * Ioctl for DMF32.
280 */
dmfioctl(dev,cmd,data,flag)281 dmfioctl(dev, cmd, data, flag)
282 dev_t dev;
283 caddr_t data;
284 {
285 int unit = minor(dev);
286
287 if (unit & 0200)
288 return (ENOTTY);
289 return (dmxioctl(&dmf_tty[unit], cmd, data, flag));
290 }
291
292 /*
293 * DMF32 transmitter interrupt.
294 * Restart the idle line.
295 */
dmfxint(dmf)296 dmfxint(dmf)
297 int dmf;
298 {
299
300 dmxxint(&dmf_softc[dmf]);
301 }
302
303 /*
304 * Start (restart) transmission on the given line.
305 */
306 dmfstart(tp)
307 struct tty *tp;
308 {
309
310 dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]);
311 }
312
313 /*
314 * Stop output on a line, e.g. for ^S/^Q or output flush.
315 */
316 dmfstop(tp, flag)
317 struct tty *tp;
318 {
319
320 dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag);
321 }
322
323 /*
324 * Reset state of driver if UBA reset was necessary.
325 * Reset the csr, lpr, and lcr registers on open lines, and
326 * restart transmitters.
327 */
dmfreset(uban)328 dmfreset(uban)
329 int uban;
330 {
331 register int dmf;
332 register struct tty *tp;
333 register struct uba_device *ui;
334 register struct dmfdevice *addr;
335 int i;
336
337 for (dmf = 0; dmf < NDMF; dmf++) {
338 ui = dmfinfo[dmf];
339 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
340 continue;
341 printf(" dmf%d", dmf);
342 if (dmf_uballoc[uban] == dmf) {
343 int info;
344
345 info = uballoc(uban, (caddr_t)cfree,
346 nclist * sizeof(struct cblock), UBA_CANTWAIT);
347 if (info)
348 cbase[uban] = UBAI_ADDR(info);
349 else {
350 printf(" [can't get uba map]");
351 cbase[uban] = -1;
352 }
353 }
354 addr = (struct dmfdevice *)ui->ui_addr;
355 addr->dmfa.csr = DMF_IE;
356 addr->dmfa.rsp = dmx_timeout;
357 tp = &dmf_tty[dmf * 8];
358 for (i = 0; i < 8; i++, tp++) {
359 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
360 dmxparam(tp, &tp->t_termios);
361 (void) dmxmctl(tp, DMF_ON, DMSET);
362 tp->t_state &= ~TS_BUSY;
363 dmfstart(tp);
364 }
365 }
366 #if NDMF_LP > 0
367 dmflint(dmf);
368 #endif
369 }
370 }
371
372 #if NDMF_LP > 0
373 /*
374 * DMF32 line printer driver
375 *
376 * the line printer on dmfx is indicated by a minor device code of 128+x
377 *
378 * the flags field of the config file is interpreted like so:
379 * bits meaning
380 * ---- -------
381 * 0-7 soft carrier bits for ttys part of dmf32
382 * 8-15 number of cols/line on the line printer
383 * if 0, 132 will be used.
384 * 16-23 number of lines/page on the line printer
385 * if 0, 66 will be used.
386 * 24 if 1 DO NOT use the auto format mode of the
387 * line printer parallel port
388 */
389
390 struct dmfl_softc {
391 u_int dmfl_state; /* soft state bits */
392 int dmfl_info; /* uba info */
393 u_short dmfl_lines; /* lines per page (66 def.) */
394 u_short dmfl_cols; /* cols per line (132 def.) */
395 u_short dmfl_format; /* fflag for auto form feed */
396 char dmfl_buf[DMFL_BUFSIZ];
397 } dmfl_softc[NDMF];
398
399 /*
400 * convert device number into DMF line printer unit number
401 */
402 #define DMFL_UNIT(d) (minor(d) & 0xf) /* up to 16 DMFs */
403
404 #define ASLP 1 /* waiting for interrupt from dmf */
405 #define OPEN 2 /* line printer is open */
406 #define ERROR 4 /* error while printing, driver
407 refuses to do anything till closed */
408 #define MOREIO 8 /* more data for printer */
409
410 /*
411 * Attach printer portion of dmf.
412 */
dmflattach(ui)413 dmflattach(ui)
414 register struct uba_device *ui;
415 {
416 register int unit = ui->ui_unit;
417 register int cols = (ui->ui_flags>>8) & 0xff;
418 register int lines = (ui->ui_flags>>16) & 0xff;
419 register struct dmfl_softc *sc;
420
421 sc = &dmfl_softc[unit];
422 sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
423 sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
424 if ((ui->ui_flags >> 24) & 0x1)
425 sc->dmfl_format = (2 << 8);
426 else
427 sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
428 }
429
430 /*
431 * dmflopen -- open the line printer port on a dmf32
432 */
433 /* ARGSUSED */
dmflopen(dev,flag)434 dmflopen(dev, flag)
435 dev_t dev;
436 int flag;
437 {
438 register int dmf;
439 register struct dmfl_softc *sc;
440 register struct uba_device *ui;
441 register struct dmfdevice *addr;
442
443 dmf = DMFL_UNIT(dev);
444 if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
445 return (ENXIO);
446 sc = &dmfl_softc[dmf];
447 if (sc->dmfl_state & OPEN)
448 return (EBUSY);
449 addr = (struct dmfdevice *)ui->ui_addr;
450 if (addr->dmfl_ctrl & DMFL_OFFLINE) {
451 #ifdef notdef
452 log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
453 dmf);
454 #endif
455 return (EIO);
456 }
457 if ((addr->dmfl_ctrl & DMFL_CONV)) {
458 log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
459 return (EIO);
460 }
461
462 addr->dmfl_ctrl = 0;
463 sc->dmfl_state |= OPEN;
464 return (0);
465 }
466
467 /* ARGSUSED */
dmflclose(dev,flag)468 dmflclose(dev, flag)
469 dev_t dev;
470 int flag;
471 {
472 register int dmf = DMFL_UNIT(dev);
473 register struct dmfl_softc *sc = &dmfl_softc[dmf];
474 register struct uba_device *ui = dmfinfo[dmf];
475
476 sc->dmfl_state = 0;
477 if (sc->dmfl_info != 0)
478 ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
479
480 ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
481 }
482
dmflwrite(dev,uio)483 dmflwrite(dev, uio)
484 dev_t dev;
485 struct uio *uio;
486 {
487 register int n;
488 register int error;
489 register struct dmfl_softc *sc;
490
491 sc = &dmfl_softc[DMFL_UNIT(dev)];
492 if (sc->dmfl_state & ERROR)
493 return (EIO);
494 while (n = (unsigned)uio->uio_resid) {
495 if (n > DMFL_BUFSIZ) {
496 n = DMFL_BUFSIZ;
497 sc->dmfl_state |= MOREIO;
498 } else
499 sc->dmfl_state &= ~MOREIO;
500 if (error = uiomove(sc->dmfl_buf, (int)n, uio))
501 return (error);
502 if (error = dmflout(dev, sc->dmfl_buf, n))
503 return (error);
504 }
505 return (0);
506 }
507
508
509 /*
510 * dmflout -- start io operation to dmf line printer
511 * cp is addr of buf of n chars to be sent.
512 *
513 * -- dmf will be put in formatted output mode, this will
514 * be selectable from an ioctl if the
515 * need ever arises.
516 */
dmflout(dev,cp,n)517 dmflout(dev, cp, n)
518 dev_t dev;
519 char *cp;
520 int n;
521 {
522 register struct dmfl_softc *sc;
523 register int dmf;
524 register struct uba_device *ui;
525 register struct dmfdevice *d;
526 int s, error;
527
528 dmf = DMFL_UNIT(dev);
529 sc = &dmfl_softc[dmf];
530 if (sc->dmfl_state & ERROR)
531 return (EIO);
532 ui = dmfinfo[dmf];
533 /*
534 * allocate unibus resources, will be released when io
535 * operation is done.
536 */
537 if (sc->dmfl_info == 0)
538 sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
539 d = (struct dmfdevice *)ui->ui_addr;
540 d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */
541 /* indir reg auto increments on r/w */
542 /* SO DON'T CHANGE THE ORDER OF THIS CODE */
543 d->dmfl_indrct = 0; /* prefix chars & num */
544 d->dmfl_indrct = 0; /* suffix chars & num */
545 d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */
546 d->dmfl_indrct = -n; /* number of chars */
547
548 d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
549 /* dma hi 2 bits addr */
550 d->dmfl_indrct = sc->dmfl_lines /* lines per page */
551 | (sc->dmfl_cols<<8); /* carriage width */
552 sc->dmfl_state |= ASLP;
553 error = 0;
554 s = spltty();
555 d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
556 while (sc->dmfl_state & ASLP) {
557 if (error = tsleep(sc->dmfl_buf, (PZERO + 8) | PCATCH,
558 ttyout, 0))
559 break;
560 while (sc->dmfl_state & ERROR) {
561 timeout(dmflint, (caddr_t)dmf, 10 * hz);
562 if (error = tsleep((caddr_t)&sc->dmfl_state,
563 (PZERO + 8) | PCATCH, ttyout, 0))
564 goto out;
565 }
566 }
567 out:
568 splx(s);
569 return (0);
570 }
571
572 /*
573 * dmflint -- handle an interrupt from the line printer part of the dmf32
574 */
dmflint(dmf)575 dmflint(dmf)
576 int dmf;
577 {
578 register struct uba_device *ui;
579 register struct dmfl_softc *sc;
580 register struct dmfdevice *d;
581 short dmfl_stats;
582
583 ui = dmfinfo[dmf];
584 sc = &dmfl_softc[dmf];
585 d = (struct dmfdevice *)ui->ui_addr;
586
587 d->dmfl_ctrl &= ~DMFL_IE;
588 dmfl_stats = d->dmfl_ctrl;
589 if (sc->dmfl_state & ERROR) {
590 if ((dmfl_stats & DMFL_OFFLINE) == 0)
591 sc->dmfl_state &= ~ERROR;
592 wakeup((caddr_t)&sc->dmfl_state);
593 return;
594 }
595 if (dmfl_stats & DMFL_DMAERR)
596 log(LOG_WARNING, "dmf%d: NXM\n", dmf);
597 if (dmfl_stats & DMFL_OFFLINE) {
598 log(LOG_WARNING, "dmf%d: printer error\n", dmf);
599 sc->dmfl_state |= ERROR;
600 }
601 #ifdef notdef
602 if (dmfl_stats & DMFL_PDONE) {
603 printf("bytes= %d\n", d->dmfl_indrct);
604 printf("lines= %d\n", d->dmfl_indrct);
605 }
606 #endif
607 sc->dmfl_state &= ~ASLP;
608 wakeup((caddr_t)sc->dmfl_buf);
609 if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
610 ubarelse(ui->ui_ubanum, &sc->dmfl_info);
611 }
612 #endif NDMF_LP
613
614 /* stubs for interrupt routines for devices not yet supported */
615
dmfsrint()616 dmfsrint()
617 {
618 printf("dmfsrint\n");
619 }
620
dmfsxint()621 dmfsxint()
622 {
623 printf("dmfsxint\n");
624 }
625
dmfdaint()626 dmfdaint()
627 {
628 printf("dmfdaint\n");
629 }
630
dmfdbint()631 dmfdbint()
632 {
633 printf("dmfdbint\n");
634 }
635 #endif NDMF
636