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