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