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