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