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