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.17 (Berkeley) 05/16/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, mode, p) 271 dev_t dev; 272 int flag, mode; 273 struct proc *p; 274 { 275 register struct tty *tp; 276 register unit; 277 278 unit = minor(dev); 279 tp = &dh11[unit]; 280 (*linesw[tp->t_line].l_close)(tp, flag); 281 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 282 if (tp->t_cflag&HUPCL || (tp->t_state&TS_ISOPEN)==0) 283 dmctl(unit, DML_OFF, DMSET); 284 return (ttyclose(tp)); 285 } 286 287 dhread(dev, uio, flag) 288 dev_t dev; 289 struct uio *uio; 290 { 291 register struct tty *tp = &dh11[minor(dev)]; 292 293 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 294 } 295 296 dhwrite(dev, uio, flag) 297 dev_t dev; 298 struct uio *uio; 299 { 300 register struct tty *tp = &dh11[minor(dev)]; 301 302 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 303 } 304 305 /* 306 * DH11 receiver interrupt. 307 */ 308 dhrint(dh) 309 int dh; 310 { 311 register struct tty *tp; 312 register c, cc; 313 register struct dhdevice *addr; 314 register struct tty *tp0; 315 register struct uba_device *ui; 316 int overrun = 0; 317 318 ui = dhinfo[dh]; 319 if (ui == 0 || ui->ui_alive == 0) 320 return; 321 addr = (struct dhdevice *)ui->ui_addr; 322 tp0 = &dh11[dh<<4]; 323 /* 324 * Loop fetching characters from the silo for this 325 * dh until there are no more in the silo. 326 */ 327 while ((c = addr->dhrcr) < 0) { 328 tp = tp0 + ((c>>8)&0xf); 329 dhchars[dh]++; 330 if ((tp->t_state&TS_ISOPEN)==0) { 331 wakeup((caddr_t)&tp->t_rawq); 332 #ifdef PORTSELECTOR 333 if ((tp->t_state&TS_WOPEN) == 0) 334 #endif 335 continue; 336 } 337 cc = c&0xff; 338 if (c&DH_PE) 339 cc |= TTY_PE; 340 if ((c&DH_DO) && overrun == 0) { 341 log(LOG_WARNING, "dh%d: silo overflow\n", dh); 342 overrun = 1; 343 } 344 if (c&DH_FE) 345 cc |= TTY_FE; 346 (*linesw[tp->t_line].l_rint)(cc, tp); 347 } 348 } 349 350 /* 351 * Ioctl for DH11. 352 */ 353 /*ARGSUSED*/ 354 dhioctl(dev, cmd, data, flag) 355 caddr_t data; 356 { 357 register struct tty *tp; 358 register int unit = minor(dev); 359 int error; 360 361 tp = &dh11[unit]; 362 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 363 if (error >= 0) 364 return (error); 365 error = ttioctl(tp, cmd, data, flag); 366 if (error >= 0) 367 return (error); 368 switch (cmd) { 369 370 case TIOCSBRK: 371 ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); 372 break; 373 374 case TIOCCBRK: 375 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 376 break; 377 378 case TIOCSDTR: 379 dmctl(unit, DML_DTR|DML_RTS, DMBIS); 380 break; 381 382 case TIOCCDTR: 383 dmctl(unit, DML_DTR|DML_RTS, DMBIC); 384 break; 385 386 default: 387 return (ENOTTY); 388 } 389 return (0); 390 } 391 392 /* 393 * Set parameters from open or stty into the DH hardware 394 * registers. 395 */ 396 dhparam(tp, t) 397 register struct tty *tp; 398 register struct termios *t; 399 { 400 register struct dhdevice *addr; 401 register int lpar; 402 register int cflag = t->c_cflag; 403 int unit = minor(tp->t_dev); 404 int s; 405 int ispeed = ttspeedtab(t->c_ispeed, dhspeedtab); 406 int ospeed = ttspeedtab(t->c_ospeed, dhspeedtab); 407 408 /* check requested parameters */ 409 if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5) 410 return(EINVAL); 411 if (ispeed == 0) 412 ispeed = ospeed; 413 /* and copy to tty */ 414 tp->t_ispeed = t->c_ispeed; 415 tp->t_ospeed = t->c_ospeed; 416 tp->t_cflag = cflag; 417 /* 418 * Block interrupts so parameters will be set 419 * before the line interrupts. 420 */ 421 addr = (struct dhdevice *)tp->t_addr; 422 s = spl5(); 423 addr->un.dhcsrl = (unit&0xf) | DH_IE; 424 if (ospeed == 0) { 425 tp->t_cflag |= HUPCL; 426 dmctl(unit, DML_OFF, DMSET); 427 splx(s); 428 return 0; 429 } 430 lpar = (ospeed<<10) | (ispeed<<6); 431 switch (cflag&CSIZE) { 432 case CS6: lpar |= BITS6; break; 433 case CS7: lpar |= BITS7; break; 434 case CS8: lpar |= BITS8; break; 435 } 436 if (cflag&PARENB) 437 lpar |= PENABLE; 438 if (cflag&PARODD) 439 lpar |= OPAR; 440 if (cflag&CSTOPB) 441 lpar |= TWOSB; 442 addr->dhlpr = lpar; 443 splx(s); 444 return 0; 445 } 446 447 /* 448 * DH11 transmitter interrupt. 449 * Restart each line which used to be active but has 450 * terminated transmission since the last interrupt. 451 */ 452 dhxint(dh) 453 int dh; 454 { 455 register struct tty *tp; 456 register struct dhdevice *addr; 457 short ttybit, bar, *sbar; 458 register struct uba_device *ui; 459 register int unit; 460 u_short cntr; 461 462 ui = dhinfo[dh]; 463 addr = (struct dhdevice *)ui->ui_addr; 464 if (addr->un.dhcsr & DH_NXM) { 465 addr->un.dhcsr |= DH_CNI; 466 printf("dh%d: NXM\n", dh); 467 } 468 sbar = &dhsar[dh]; 469 bar = *sbar & ~addr->dhbar; 470 unit = dh * 16; ttybit = 1; 471 addr->un.dhcsr &= (short)~DH_TI; 472 for (; bar; unit++, ttybit <<= 1) { 473 if (bar & ttybit) { 474 *sbar &= ~ttybit; 475 bar &= ~ttybit; 476 tp = &dh11[unit]; 477 tp->t_state &= ~TS_BUSY; 478 if (tp->t_state&TS_FLUSH) 479 tp->t_state &= ~TS_FLUSH; 480 else { 481 addr->un.dhcsrl = (unit&017)|DH_IE; 482 /* 483 * Do arithmetic in a short to make up 484 * for lost 16&17 bits. 485 */ 486 cntr = addr->dhcar - 487 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 488 ndflush(&tp->t_outq, (int)cntr); 489 } 490 if (tp->t_line) 491 (*linesw[tp->t_line].l_start)(tp); 492 else 493 dhstart(tp); 494 } 495 } 496 } 497 498 /* 499 * Start (restart) transmission on the given DH11 line. 500 */ 501 dhstart(tp) 502 register struct tty *tp; 503 { 504 register struct dhdevice *addr; 505 register int car, dh, unit, nch; 506 int s; 507 508 unit = minor(tp->t_dev); 509 dh = unit >> 4; 510 unit &= 0xf; 511 addr = (struct dhdevice *)tp->t_addr; 512 513 /* 514 * Must hold interrupts in following code to prevent 515 * state of the tp from changing. 516 */ 517 s = spl5(); 518 /* 519 * If it's currently active, or delaying, no need to do anything. 520 */ 521 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 522 goto out; 523 /* 524 * If there are sleepers, and output has drained below low 525 * water mark, wake up the sleepers. 526 */ 527 if (tp->t_outq.c_cc<=tp->t_lowat) { 528 if (tp->t_state&TS_ASLEEP) { 529 tp->t_state &= ~TS_ASLEEP; 530 wakeup((caddr_t)&tp->t_outq); 531 } 532 if (tp->t_wsel) { 533 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 534 tp->t_wsel = 0; 535 tp->t_state &= ~TS_WCOLL; 536 } 537 } 538 /* 539 * Now restart transmission unless the output queue is 540 * empty. 541 */ 542 if (tp->t_outq.c_cc == 0) 543 goto out; 544 if (1 || !(tp->t_oflag&OPOST)) /*XXX*/ 545 nch = ndqb(&tp->t_outq, 0); 546 else { 547 nch = ndqb(&tp->t_outq, 0200); 548 /* 549 * If first thing on queue is a delay process it. 550 */ 551 if (nch == 0) { 552 nch = getc(&tp->t_outq); 553 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 554 tp->t_state |= TS_TIMEOUT; 555 goto out; 556 } 557 } 558 /* 559 * If characters to transmit, restart transmission. 560 */ 561 if (nch) { 562 car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum); 563 addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE; 564 /* 565 * The following nonsense with short word 566 * is to make sure the dhbar |= word below 567 * is done with an interlocking bisw2 instruction. 568 */ 569 { short word = 1 << unit; 570 dhsar[dh] |= word; 571 addr->dhcar = car; 572 addr->dhbcr = -nch; 573 addr->dhbar |= word; 574 } 575 tp->t_state |= TS_BUSY; 576 } 577 out: 578 splx(s); 579 } 580 581 /* 582 * Stop output on a line, e.g. for ^S/^Q or output flush. 583 */ 584 /*ARGSUSED*/ 585 dhstop(tp, flag) 586 register struct tty *tp; 587 { 588 register struct dhdevice *addr; 589 register int unit, s; 590 591 addr = (struct dhdevice *)tp->t_addr; 592 /* 593 * Block input/output interrupts while messing with state. 594 */ 595 s = spl5(); 596 if (tp->t_state & TS_BUSY) { 597 /* 598 * Device is transmitting; stop output 599 * by selecting the line and setting the byte 600 * count to -1. We will clean up later 601 * by examining the address where the dh stopped. 602 */ 603 unit = minor(tp->t_dev); 604 addr->un.dhcsrl = (unit&017) | DH_IE; 605 if ((tp->t_state&TS_TTSTOP)==0) 606 tp->t_state |= TS_FLUSH; 607 addr->dhbcr = -1; 608 } 609 splx(s); 610 } 611 612 /* 613 * Reset state of driver if UBA reset was necessary. 614 * Reset the csrl and lpr registers on open lines, and 615 * restart transmitters. 616 */ 617 dhreset(uban) 618 int uban; 619 { 620 register int dh, unit; 621 register struct tty *tp; 622 register struct uba_device *ui; 623 int i; 624 625 dh = 0; 626 for (dh = 0; dh < NDH; dh++) { 627 ui = dhinfo[dh]; 628 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 629 continue; 630 printf(" dh%d", dh); 631 if (dh_uballoc[uban] == dh) { 632 int info; 633 634 info = uballoc(uban, (caddr_t)cfree, 635 nclist * sizeof(struct cblock), UBA_CANTWAIT); 636 if (info) 637 cbase[uban] = UBAI_ADDR(info); 638 else { 639 printf(" [can't get uba map]"); 640 cbase[uban] = -1; 641 } 642 } 643 ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE; 644 ((struct dhdevice *)ui->ui_addr)->dhsilo = 0; 645 unit = dh * 16; 646 for (i = 0; i < 16; i++) { 647 tp = &dh11[unit]; 648 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 649 dhparam(unit); 650 dmctl(unit, DML_ON, DMSET); 651 tp->t_state &= ~TS_BUSY; 652 dhstart(tp); 653 } 654 unit++; 655 } 656 } 657 dhsilos = 0; 658 } 659 660 int dhtransitions, dhslowtimers, dhfasttimers; /*DEBUG*/ 661 /* 662 * At software clock interrupt time, check status. 663 * Empty all the dh silos that are in use, and decide whether 664 * to turn any silos off or on. 665 */ 666 dhtimer() 667 { 668 register int dh, s; 669 static int timercalls; 670 671 if (dhsilos) { 672 dhfasttimers++; /*DEBUG*/ 673 timercalls++; 674 s = spl5(); 675 for (dh = 0; dh < NDH; dh++) 676 if (dhsilos & (1 << dh)) 677 dhrint(dh); 678 splx(s); 679 } 680 if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) { 681 dhslowtimers++; /*DEBUG*/ 682 timercalls = 0; 683 for (dh = 0; dh < NDH; dh++) { 684 ave(dhrate[dh], dhchars[dh], 8); 685 if ((dhchars[dh] > dhhighrate) && 686 ((dhsilos & (1 << dh)) == 0)) { 687 ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 688 (dhchars[dh] > 500? 32 : 16); 689 dhsilos |= (1 << dh); 690 dhtransitions++; /*DEBUG*/ 691 } else if ((dhsilos & (1 << dh)) && 692 (dhrate[dh] < dhlowrate)) { 693 ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0; 694 dhsilos &= ~(1 << dh); 695 } 696 dhchars[dh] = 0; 697 } 698 } 699 timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz); 700 } 701 702 /* 703 * Turn on the line associated with dh dev. 704 */ 705 dmopen(dev, flag) 706 dev_t dev; 707 { 708 register struct tty *tp; 709 register struct dmdevice *addr; 710 register struct uba_device *ui; 711 register int unit; 712 register int dm; 713 int s, error = 0; 714 715 unit = minor(dev); 716 dm = unit >> 4; 717 tp = &dh11[unit]; 718 unit &= 0xf; 719 if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) { 720 tp->t_state |= TS_CARR_ON; 721 return (0); 722 } 723 addr = (struct dmdevice *)ui->ui_addr; 724 s = spl5(); 725 for (;;) { 726 tp->t_state |= TS_WOPEN; 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 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 739 ttopen, 0)) 740 break; 741 } 742 splx(s); 743 return (error); 744 } 745 746 /* 747 * Dump control bits into the DM registers. 748 */ 749 dmctl(dev, bits, how) 750 dev_t dev; 751 int bits, how; 752 { 753 register struct uba_device *ui; 754 register struct dmdevice *addr; 755 register int unit, s; 756 int dm; 757 758 unit = minor(dev); 759 dm = unit >> 4; 760 if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0) 761 return; 762 addr = (struct dmdevice *)ui->ui_addr; 763 s = spl5(); 764 addr->dmcsr &= ~DM_SE; 765 while (addr->dmcsr & DM_BUSY) 766 ; 767 addr->dmcsr = unit & 0xf; 768 switch(how) { 769 case DMSET: 770 addr->dmlstat = bits; 771 break; 772 case DMBIS: 773 addr->dmlstat |= bits; 774 break; 775 case DMBIC: 776 addr->dmlstat &= ~bits; 777 break; 778 } 779 addr->dmcsr = DM_IE|DM_SE; 780 splx(s); 781 } 782 783 /* 784 * DM11 interrupt; deal with carrier transitions. 785 */ 786 dmintr(dm) 787 register int dm; 788 { 789 register struct uba_device *ui; 790 register struct tty *tp; 791 register struct dmdevice *addr; 792 int unit; 793 794 ui = dminfo[dm]; 795 if (ui == 0) 796 return; 797 addr = (struct dmdevice *)ui->ui_addr; 798 if (addr->dmcsr&DM_DONE) { 799 if (addr->dmcsr&DM_CF) { 800 unit = addr->dmcsr & 0xf; 801 tp = &dh11[(dm << 4) + unit]; 802 if (addr->dmlstat & DML_CAR) 803 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 804 else if ((dhsoftCAR[dm] & (1<<unit)) == 0 && 805 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 806 addr->dmlstat = 0; 807 } 808 addr->dmcsr = DM_IE|DM_SE; 809 } 810 } 811 #endif 812