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