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