1 /* dh.c 6.1 83/07/29 */ 2 3 #include "dh.h" 4 #if NDH > 0 5 /* 6 * DH-11/DM-11 driver 7 */ 8 #include "../machine/pte.h" 9 10 #include "bk.h" 11 #include "../h/param.h" 12 #include "../h/conf.h" 13 #include "../h/dir.h" 14 #include "../h/user.h" 15 #include "../h/proc.h" 16 #include "../h/ioctl.h" 17 #include "../h/tty.h" 18 #include "../h/map.h" 19 #include "../h/buf.h" 20 #include "../h/vm.h" 21 22 #include "../vaxuba/ubareg.h" 23 #include "../vaxuba/ubavar.h" 24 #include "../vaxuba/dhreg.h" 25 #include "../vaxuba/dmreg.h" 26 27 #include "../h/bk.h" 28 #include "../h/clist.h" 29 #include "../h/file.h" 30 #include "../h/uio.h" 31 32 /* 33 * Definition of the driver for the auto-configuration program. 34 * There is one definition for the dh and one for the dm. 35 */ 36 int dhprobe(), dhattach(), dhrint(), dhxint(); 37 struct uba_device *dhinfo[NDH]; 38 u_short dhstd[] = { 0 }; 39 struct uba_driver dhdriver = 40 { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo }; 41 42 int dmprobe(), dmattach(), dmintr(); 43 struct uba_device *dminfo[NDH]; 44 u_short dmstd[] = { 0 }; 45 struct uba_driver dmdriver = 46 { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo }; 47 48 #ifndef PORTSELECTOR 49 #define ISPEED B300 50 #define IFLAGS (EVENP|ODDP|ECHO) 51 #else 52 #define ISPEED B4800 53 #define IFLAGS (EVENP|ODDP) 54 #endif 55 56 /* 57 * Local variables for the driver 58 */ 59 short dhsar[NDH]; /* software copy of last bar */ 60 short dhsoftCAR[NDH]; 61 62 struct tty dh11[NDH*16]; 63 int ndh11 = NDH*16; 64 int dhact; /* mask of active dh's */ 65 int dhstart(), ttrstrt(); 66 67 /* 68 * The clist space is mapped by the driver onto each UNIBUS. 69 * The UBACVT macro converts a clist space address for unibus uban 70 * into an i/o space address for the DMA routine. 71 */ 72 int dh_ubinfo[MAXNUBA]; /* info about allocated unibus map */ 73 int cbase[MAXNUBA]; /* base address in unibus map */ 74 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 75 76 /* 77 * Routine for configuration to force a dh to interrupt. 78 * Set to transmit at 9600 baud, and cause a transmitter interrupt. 79 */ 80 /*ARGSUSED*/ 81 dhprobe(reg) 82 caddr_t reg; 83 { 84 register int br, cvec; /* these are ``value-result'' */ 85 register struct dhdevice *dhaddr = (struct dhdevice *)reg; 86 87 #ifdef lint 88 br = 0; cvec = br; br = cvec; 89 if (ndh11 == 0) ndh11 = 1; 90 dhrint(0); dhxint(0); 91 #endif 92 #ifndef notdef 93 dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI; 94 DELAY(1000); 95 dhaddr->un.dhcsr &= ~DH_RI; 96 dhaddr->un.dhcsr = 0; 97 #else 98 dhaddr->un.dhcsr = DH_TIE; 99 DELAY(5); 100 dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE; 101 dhaddr->dhbcr = -1; 102 dhaddr->dhcar = 0; 103 dhaddr->dhbar = 1; 104 DELAY(100000); /* wait 1/10'th of a sec for interrupt */ 105 dhaddr->un.dhcsr = 0; 106 if (cvec && cvec != 0x200) 107 cvec -= 4; /* transmit -> receive */ 108 #endif 109 return (sizeof (struct dhdevice)); 110 } 111 112 /* 113 * Routine called to attach a dh. 114 */ 115 dhattach(ui) 116 struct uba_device *ui; 117 { 118 119 dhsoftCAR[ui->ui_unit] = ui->ui_flags; 120 } 121 122 /* 123 * Configuration routine to cause a dm to interrupt. 124 */ 125 dmprobe(reg) 126 caddr_t reg; 127 { 128 register int br, vec; /* value-result */ 129 register struct dmdevice *dmaddr = (struct dmdevice *)reg; 130 131 #ifdef lint 132 br = 0; vec = br; br = vec; 133 dmintr(0); 134 #endif 135 dmaddr->dmcsr = DM_DONE|DM_IE; 136 DELAY(20); 137 dmaddr->dmcsr = 0; 138 return (1); 139 } 140 141 /*ARGSUSED*/ 142 dmattach(ui) 143 struct uba_device *ui; 144 { 145 146 /* no local state to set up */ 147 } 148 149 /* 150 * Open a DH11 line, mapping the clist onto the uba if this 151 * is the first dh on this uba. Turn on this dh if this is 152 * the first use of it. Also do a dmopen to wait for carrier. 153 */ 154 /*ARGSUSED*/ 155 dhopen(dev, flag) 156 dev_t dev; 157 { 158 register struct tty *tp; 159 register int unit, dh; 160 register struct dhdevice *addr; 161 register struct uba_device *ui; 162 int s; 163 164 unit = minor(dev); 165 dh = unit >> 4; 166 if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0) 167 return (ENXIO); 168 tp = &dh11[unit]; 169 if (tp->t_state&TS_XCLUDE && u.u_uid!=0) 170 return (EBUSY); 171 addr = (struct dhdevice *)ui->ui_addr; 172 tp->t_addr = (caddr_t)addr; 173 tp->t_oproc = dhstart; 174 tp->t_state |= TS_WOPEN; 175 /* 176 * While setting up state for this uba and this dh, 177 * block uba resets which can clear the state. 178 */ 179 s = spl5(); 180 if (dh_ubinfo[ui->ui_ubanum] == 0) { 181 /* 512+ is a kludge to try to get around a hardware problem */ 182 dh_ubinfo[ui->ui_ubanum] = 183 uballoc(ui->ui_ubanum, (caddr_t)cfree, 184 512+nclist*sizeof(struct cblock), 0); 185 cbase[ui->ui_ubanum] = dh_ubinfo[ui->ui_ubanum]&0x3ffff; 186 } 187 if ((dhact&(1<<dh)) == 0) { 188 addr->un.dhcsr |= DH_IE; 189 dhact |= (1<<dh); 190 addr->dhsilo = 16; 191 } 192 splx(s); 193 /* 194 * If this is first open, initialze tty state to default. 195 */ 196 if ((tp->t_state&TS_ISOPEN) == 0) { 197 ttychars(tp); 198 #ifndef PORTSELECTOR 199 if (tp->t_ispeed == 0) { 200 #endif 201 tp->t_ispeed = ISPEED; 202 tp->t_ospeed = ISPEED; 203 tp->t_flags = IFLAGS; 204 #ifndef PORTSELECTOR 205 } 206 #endif 207 dhparam(unit); 208 } 209 /* 210 * Wait for carrier, then process line discipline specific open. 211 */ 212 dmopen(dev); 213 return ((*linesw[tp->t_line].l_open)(dev, tp)); 214 } 215 216 /* 217 * Close a DH11 line, turning off the DM11. 218 */ 219 /*ARGSUSED*/ 220 dhclose(dev, flag) 221 dev_t dev; 222 int flag; 223 { 224 register struct tty *tp; 225 register unit; 226 227 unit = minor(dev); 228 tp = &dh11[unit]; 229 (*linesw[tp->t_line].l_close)(tp); 230 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 231 if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) 232 dmctl(unit, DML_OFF, DMSET); 233 ttyclose(tp); 234 } 235 236 dhread(dev, uio) 237 dev_t dev; 238 struct uio *uio; 239 { 240 register struct tty *tp = &dh11[minor(dev)]; 241 242 return ((*linesw[tp->t_line].l_read)(tp, uio)); 243 } 244 245 dhwrite(dev, uio) 246 dev_t dev; 247 struct uio *uio; 248 { 249 register struct tty *tp = &dh11[minor(dev)]; 250 251 return ((*linesw[tp->t_line].l_write)(tp, uio)); 252 } 253 254 /* 255 * DH11 receiver interrupt. 256 */ 257 dhrint(dh) 258 int dh; 259 { 260 register struct tty *tp; 261 register c; 262 register struct dhdevice *addr; 263 register struct tty *tp0; 264 register struct uba_device *ui; 265 int overrun = 0; 266 267 ui = dhinfo[dh]; 268 if (ui == 0 || ui->ui_alive == 0) 269 return; 270 addr = (struct dhdevice *)ui->ui_addr; 271 tp0 = &dh11[dh<<4]; 272 /* 273 * Loop fetching characters from the silo for this 274 * dh until there are no more in the silo. 275 */ 276 while ((c = addr->dhrcr) < 0) { 277 tp = tp0 + ((c>>8)&0xf); 278 #ifndef PORTSELECTOR 279 if ((tp->t_state&TS_ISOPEN)==0) { 280 #else 281 if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0) { 282 #endif 283 wakeup((caddr_t)tp); 284 continue; 285 } 286 if (c & DH_PE) 287 if ((tp->t_flags&(EVENP|ODDP))==EVENP 288 || (tp->t_flags&(EVENP|ODDP))==ODDP ) 289 continue; 290 if ((c & DH_DO) && overrun == 0) { 291 printf("dh%d: silo overflow\n", dh); 292 overrun = 1; 293 } 294 if (c & DH_FE) 295 /* 296 * At framing error (break) generate 297 * a null (in raw mode, for getty), or a 298 * interrupt (in cooked/cbreak mode). 299 */ 300 if (tp->t_flags&RAW) 301 c = 0; 302 else 303 c = tp->t_intrc; 304 #if NBK > 0 305 if (tp->t_line == NETLDISC) { 306 c &= 0177; 307 BKINPUT(c, tp); 308 } else 309 #endif 310 (*linesw[tp->t_line].l_rint)(c, tp); 311 } 312 } 313 314 /* 315 * Ioctl for DH11. 316 */ 317 /*ARGSUSED*/ 318 dhioctl(dev, cmd, data, flag) 319 caddr_t data; 320 { 321 register struct tty *tp; 322 register int unit = minor(dev); 323 int error; 324 325 tp = &dh11[unit]; 326 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 327 if (error >= 0) 328 return (error); 329 error = ttioctl(tp, cmd, data, flag); 330 if (error >= 0) { 331 if (cmd == TIOCSETP || cmd == TIOCSETN) 332 dhparam(unit); 333 return (error); 334 } 335 switch (cmd) { 336 337 case TIOCSBRK: 338 ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); 339 break; 340 341 case TIOCCBRK: 342 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 343 break; 344 345 case TIOCSDTR: 346 dmctl(unit, DML_DTR|DML_RTS, DMBIS); 347 break; 348 349 case TIOCCDTR: 350 dmctl(unit, DML_DTR|DML_RTS, DMBIC); 351 break; 352 353 default: 354 return (ENOTTY); 355 } 356 return (0); 357 } 358 359 /* 360 * Set parameters from open or stty into the DH hardware 361 * registers. 362 */ 363 dhparam(unit) 364 register int unit; 365 { 366 register struct tty *tp; 367 register struct dhdevice *addr; 368 register int lpar; 369 int s; 370 371 tp = &dh11[unit]; 372 addr = (struct dhdevice *)tp->t_addr; 373 /* 374 * Block interrupts so parameters will be set 375 * before the line interrupts. 376 */ 377 s = spl5(); 378 addr->un.dhcsrl = (unit&0xf) | DH_IE; 379 if ((tp->t_ispeed)==0) { 380 tp->t_state |= TS_HUPCLS; 381 dmctl(unit, DML_OFF, DMSET); 382 return; 383 } 384 lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); 385 if ((tp->t_ispeed) == B134) 386 lpar |= BITS6|PENABLE|HDUPLX; 387 else if (tp->t_flags & (RAW|LITOUT)) 388 lpar |= BITS8; 389 else 390 lpar |= BITS7|PENABLE; 391 if ((tp->t_flags&EVENP) == 0) 392 lpar |= OPAR; 393 if ((tp->t_ospeed) == B110) 394 lpar |= TWOSB; 395 addr->dhlpr = lpar; 396 splx(s); 397 } 398 399 /* 400 * DH11 transmitter interrupt. 401 * Restart each line which used to be active but has 402 * terminated transmission since the last interrupt. 403 */ 404 dhxint(dh) 405 int dh; 406 { 407 register struct tty *tp; 408 register struct dhdevice *addr; 409 short ttybit, bar, *sbar; 410 register struct uba_device *ui; 411 register int unit; 412 u_short cntr; 413 414 ui = dhinfo[dh]; 415 addr = (struct dhdevice *)ui->ui_addr; 416 if (addr->un.dhcsr & DH_NXM) { 417 addr->un.dhcsr |= DH_CNI; 418 printf("dh%d: NXM\n", dh); 419 } 420 sbar = &dhsar[dh]; 421 bar = *sbar & ~addr->dhbar; 422 unit = dh * 16; ttybit = 1; 423 addr->un.dhcsr &= (short)~DH_TI; 424 for (; bar; unit++, ttybit <<= 1) { 425 if (bar & ttybit) { 426 *sbar &= ~ttybit; 427 bar &= ~ttybit; 428 tp = &dh11[unit]; 429 tp->t_state &= ~TS_BUSY; 430 if (tp->t_state&TS_FLUSH) 431 tp->t_state &= ~TS_FLUSH; 432 else { 433 addr->un.dhcsrl = (unit&017)|DH_IE; 434 /* 435 * Do arithmetic in a short to make up 436 * for lost 16&17 bits. 437 */ 438 cntr = addr->dhcar - 439 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 440 ndflush(&tp->t_outq, (int)cntr); 441 } 442 if (tp->t_line) 443 (*linesw[tp->t_line].l_start)(tp); 444 else 445 dhstart(tp); 446 } 447 } 448 } 449 450 /* 451 * Start (restart) transmission on the given DH11 line. 452 */ 453 dhstart(tp) 454 register struct tty *tp; 455 { 456 register struct dhdevice *addr; 457 register int car, dh, unit, nch; 458 int s; 459 460 unit = minor(tp->t_dev); 461 dh = unit >> 4; 462 unit &= 0xf; 463 addr = (struct dhdevice *)tp->t_addr; 464 465 /* 466 * Must hold interrupts in following code to prevent 467 * state of the tp from changing. 468 */ 469 s = spl5(); 470 /* 471 * If it's currently active, or delaying, no need to do anything. 472 */ 473 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 474 goto out; 475 /* 476 * If there are sleepers, and output has drained below low 477 * water mark, wake up the sleepers. 478 */ 479 if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 480 if (tp->t_state&TS_ASLEEP) { 481 tp->t_state &= ~TS_ASLEEP; 482 wakeup((caddr_t)&tp->t_outq); 483 } 484 if (tp->t_wsel) { 485 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 486 tp->t_wsel = 0; 487 tp->t_state &= ~TS_WCOLL; 488 } 489 } 490 /* 491 * Now restart transmission unless the output queue is 492 * empty. 493 */ 494 if (tp->t_outq.c_cc == 0) 495 goto out; 496 if (tp->t_flags & (RAW|LITOUT)) 497 nch = ndqb(&tp->t_outq, 0); 498 else { 499 nch = ndqb(&tp->t_outq, 0200); 500 /* 501 * If first thing on queue is a delay process it. 502 */ 503 if (nch == 0) { 504 nch = getc(&tp->t_outq); 505 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 506 tp->t_state |= TS_TIMEOUT; 507 goto out; 508 } 509 } 510 /* 511 * If characters to transmit, restart transmission. 512 */ 513 if (nch) { 514 car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum); 515 addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE; 516 /* 517 * The following nonsense with short word 518 * is to make sure the dhbar |= word below 519 * is done with an interlocking bisw2 instruction. 520 */ 521 { short word = 1 << unit; 522 dhsar[dh] |= word; 523 addr->dhcar = car; 524 addr->dhbcr = -nch; 525 addr->dhbar |= word; 526 } 527 tp->t_state |= TS_BUSY; 528 } 529 out: 530 splx(s); 531 } 532 533 /* 534 * Stop output on a line, e.g. for ^S/^Q or output flush. 535 */ 536 /*ARGSUSED*/ 537 dhstop(tp, flag) 538 register struct tty *tp; 539 { 540 register struct dhdevice *addr; 541 register int unit, s; 542 543 addr = (struct dhdevice *)tp->t_addr; 544 /* 545 * Block input/output interrupts while messing with state. 546 */ 547 s = spl5(); 548 if (tp->t_state & TS_BUSY) { 549 /* 550 * Device is transmitting; stop output 551 * by selecting the line and setting the byte 552 * count to -1. We will clean up later 553 * by examining the address where the dh stopped. 554 */ 555 unit = minor(tp->t_dev); 556 addr->un.dhcsrl = (unit&017) | DH_IE; 557 if ((tp->t_state&TS_TTSTOP)==0) 558 tp->t_state |= TS_FLUSH; 559 addr->dhbcr = -1; 560 } 561 splx(s); 562 } 563 564 /* 565 * Reset state of driver if UBA reset was necessary. 566 * Reset the csrl and lpr registers on open lines, and 567 * restart transmitters. 568 */ 569 dhreset(uban) 570 int uban; 571 { 572 register int dh, unit; 573 register struct tty *tp; 574 register struct uba_device *ui; 575 int i; 576 577 if (dh_ubinfo[uban] == 0) 578 return; 579 dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 580 512+nclist*sizeof (struct cblock), 0); 581 cbase[uban] = dh_ubinfo[uban]&0x3ffff; 582 dh = 0; 583 for (dh = 0; dh < NDH; dh++) { 584 ui = dhinfo[dh]; 585 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 586 continue; 587 printf(" dh%d", dh); 588 ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE; 589 ((struct dhdevice *)ui->ui_addr)->dhsilo = 16; 590 unit = dh * 16; 591 for (i = 0; i < 16; i++) { 592 tp = &dh11[unit]; 593 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 594 dhparam(unit); 595 dmctl(unit, DML_ON, DMSET); 596 tp->t_state &= ~TS_BUSY; 597 dhstart(tp); 598 } 599 unit++; 600 } 601 } 602 dhtimer(); 603 } 604 605 /* 606 * At software clock interrupt time or after a UNIBUS reset 607 * empty all the dh silos. 608 */ 609 dhtimer() 610 { 611 register int dh; 612 register int s = spl5(); 613 614 for (dh = 0; dh < NDH; dh++) 615 dhrint(dh); 616 splx(s); 617 } 618 619 /* 620 * Turn on the line associated with dh dev. 621 */ 622 dmopen(dev) 623 dev_t dev; 624 { 625 register struct tty *tp; 626 register struct dmdevice *addr; 627 register struct uba_device *ui; 628 register int unit; 629 register int dm; 630 int s; 631 632 unit = minor(dev); 633 dm = unit >> 4; 634 tp = &dh11[unit]; 635 unit &= 0xf; 636 if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 || 637 (dhsoftCAR[dm]&(1<<unit))) { 638 tp->t_state |= TS_CARR_ON; 639 return; 640 } 641 addr = (struct dmdevice *)ui->ui_addr; 642 s = spl5(); 643 addr->dmcsr &= ~DM_SE; 644 while (addr->dmcsr & DM_BUSY) 645 ; 646 addr->dmcsr = unit; 647 addr->dmlstat = DML_ON; 648 if (addr->dmlstat&DML_CAR) 649 tp->t_state |= TS_CARR_ON; 650 addr->dmcsr = DM_IE|DM_SE; 651 while ((tp->t_state&TS_CARR_ON)==0) 652 sleep((caddr_t)&tp->t_rawq, TTIPRI); 653 splx(s); 654 } 655 656 /* 657 * Dump control bits into the DM registers. 658 */ 659 dmctl(dev, bits, how) 660 dev_t dev; 661 int bits, how; 662 { 663 register struct uba_device *ui; 664 register struct dmdevice *addr; 665 register int unit, s; 666 int dm; 667 668 unit = minor(dev); 669 dm = unit >> 4; 670 if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0) 671 return; 672 addr = (struct dmdevice *)ui->ui_addr; 673 s = spl5(); 674 addr->dmcsr &= ~DM_SE; 675 while (addr->dmcsr & DM_BUSY) 676 ; 677 addr->dmcsr = unit & 0xf; 678 switch(how) { 679 case DMSET: 680 addr->dmlstat = bits; 681 break; 682 case DMBIS: 683 addr->dmlstat |= bits; 684 break; 685 case DMBIC: 686 addr->dmlstat &= ~bits; 687 break; 688 } 689 addr->dmcsr = DM_IE|DM_SE; 690 splx(s); 691 } 692 693 /* 694 * DM11 interrupt; deal with carrier transitions. 695 */ 696 dmintr(dm) 697 register int dm; 698 { 699 register struct uba_device *ui; 700 register struct tty *tp; 701 register struct dmdevice *addr; 702 703 ui = dminfo[dm]; 704 if (ui == 0) 705 return; 706 addr = (struct dmdevice *)ui->ui_addr; 707 if (addr->dmcsr&DM_DONE) { 708 if (addr->dmcsr&DM_CF) { 709 tp = &dh11[(dm<<4)+(addr->dmcsr&0xf)]; 710 wakeup((caddr_t)&tp->t_rawq); 711 if ((tp->t_state&TS_WOPEN) == 0 && 712 (tp->t_flags & MDMBUF)) { 713 if (addr->dmlstat & DML_CAR) { 714 tp->t_state &= ~TS_TTSTOP; 715 ttstart(tp); 716 } else if ((tp->t_state&TS_TTSTOP) == 0) { 717 tp->t_state |= TS_TTSTOP; 718 dhstop(tp, 0); 719 } 720 } else if ((addr->dmlstat&DML_CAR)==0) { 721 if ((tp->t_state&TS_WOPEN)==0 && 722 (tp->t_flags & NOHANG) == 0) { 723 gsignal(tp->t_pgrp, SIGHUP); 724 gsignal(tp->t_pgrp, SIGCONT); 725 addr->dmlstat = 0; 726 ttyflush(tp, FREAD|FWRITE); 727 } 728 tp->t_state &= ~TS_CARR_ON; 729 } else 730 tp->t_state |= TS_CARR_ON; 731 } 732 addr->dmcsr = DM_IE|DM_SE; 733 } 734 } 735 #endif 736