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