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*/ 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 */ 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*/ 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*/ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 616 dmfsrint() 617 { 618 printf("dmfsrint\n"); 619 } 620 621 dmfsxint() 622 { 623 printf("dmfsxint\n"); 624 } 625 626 dmfdaint() 627 { 628 printf("dmfdaint\n"); 629 } 630 631 dmfdbint() 632 { 633 printf("dmfdbint\n"); 634 } 635 #endif NDMF 636