1 /* 2 * Copyright (c) 1985, 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 * @(#)dhu.c 7.6 (Berkeley) 05/01/89 7 */ 8 9 /* 10 * based on dh.c 6.3 84/03/15 11 * and on dmf.c 6.2 84/02/16 12 * 13 * Dave Johnson, Brown University Computer Science 14 * ddj%brown@csnet-relay 15 */ 16 17 #include "dhu.h" 18 #if NDHU > 0 19 /* 20 * DHU-11 driver 21 */ 22 #include "machine/pte.h" 23 24 #include "bk.h" 25 #include "param.h" 26 #include "conf.h" 27 #include "dir.h" 28 #include "user.h" 29 #include "proc.h" 30 #include "ioctl.h" 31 #include "tty.h" 32 #include "ttydefaults.h" 33 #include "map.h" 34 #include "buf.h" 35 #include "vm.h" 36 #include "kernel.h" 37 #include "syslog.h" 38 39 #include "uba.h" 40 #include "ubareg.h" 41 #include "ubavar.h" 42 #include "dhureg.h" 43 44 #include "bkmac.h" 45 #include "clist.h" 46 #include "file.h" 47 #include "uio.h" 48 49 /* 50 * Definition of the driver for the auto-configuration program. 51 */ 52 int dhuprobe(), dhuattach(), dhurint(), dhuxint(); 53 struct uba_device *dhuinfo[NDHU]; 54 u_short dhustd[] = { 160440, 160500, 0 }; /* some common addresses */ 55 struct uba_driver dhudriver = 56 { dhuprobe, 0, dhuattach, 0, dhustd, "dhu", dhuinfo }; 57 58 #define NDHULINE (NDHU*16) 59 60 #define UNIT(x) (minor(x)) 61 62 #ifndef PORTSELECTOR 63 #define SPEED TTYDEF_SPEED 64 #define LFLAG TTYDEF_LFLAG 65 #else 66 #define SPEED B4800 67 #define LFLAG (TTYDEF_LFLAG & ~ECHO) 68 #endif 69 70 /* 71 * default receive silo timeout value -- valid values are 2..255 72 * number of ms. to delay between first char received and receive interrupt 73 * 74 * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0 75 */ 76 #define DHU_DEF_TIMO 20 77 78 /* 79 * Other values for silo timeout register defined here but not used: 80 * receive interrupt only on modem control or silo alarm (3/4 full) 81 */ 82 #define DHU_POLL_TIMO 0 83 /* 84 * receive interrupt immediately on receive character 85 */ 86 #define DHU_NO_TIMO 1 87 88 /* 89 * Local variables for the driver 90 */ 91 /* 92 * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B". 93 * EXTA => 19200 baud 94 * EXTB => 2000 baud 95 */ 96 struct speedtab dhuspeedtab[] = { 97 19200, 14, 98 9600, 13, 99 4800, 11, 100 2400, 10, 101 2000, 9, 102 1800, 8, 103 1200, 7, 104 600, 6, 105 300, 5, 106 150, 4, 107 134, 3, 108 110, 2, 109 75, 1, 110 0, 0, 111 -1, -1, 112 }; 113 114 short dhusoftCAR[NDHU]; 115 116 struct tty dhu_tty[NDHULINE]; 117 int ndhu = NDHULINE; 118 int dhuact; /* mask of active dhu's */ 119 int dhustart(), ttrstrt(); 120 121 /* 122 * The clist space is mapped by one terminal driver onto each UNIBUS. 123 * The identity of the board which allocated resources is recorded, 124 * so the process may be repeated after UNIBUS resets. 125 * The UBACVT macro converts a clist space address for unibus uban 126 * into an i/o space address for the DMA routine. 127 */ 128 int dhu_uballoc[NUBA]; /* which dhu (if any) allocated unibus map */ 129 int cbase[NUBA]; /* base address of clists in unibus map */ 130 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 131 132 /* 133 * Routine for configuration to force a dhu to interrupt. 134 */ 135 /*ARGSUSED*/ 136 dhuprobe(reg) 137 caddr_t reg; 138 { 139 register int br, cvec; /* these are ``value-result'' */ 140 register struct dhudevice *dhuaddr = (struct dhudevice *)reg; 141 int i; 142 143 #ifdef lint 144 br = 0; cvec = br; br = cvec; 145 if (ndhu == 0) ndhu = 1; 146 dhurint(0); dhuxint(0); 147 #endif 148 /* 149 * The basic idea here is: 150 * do a self-test by setting the Master-Reset bit 151 * if this fails, then return 152 * if successful, there will be 8 diagnostic codes in RX FIFO 153 * therefore ask for a Received-Data-Available interrupt 154 * wait for it... 155 * reset the interrupt-enable bit and flush out the diag. codes 156 */ 157 dhuaddr->dhucsr = DHU_CS_MCLR; 158 for (i = 0; i < 1000; i++) { 159 DELAY(10000); 160 if ((dhuaddr->dhucsr&DHU_CS_MCLR) == 0) 161 break; 162 } 163 if (dhuaddr->dhucsr&DHU_CS_MCLR) 164 return(0); 165 if (dhuaddr->dhucsr&DHU_CS_DFAIL) 166 return(0); 167 dhuaddr->dhucsr = DHU_CS_RIE; 168 DELAY(1000); 169 dhuaddr->dhucsr = 0; 170 while (dhuaddr->dhurbuf < 0) 171 /* void */; 172 return (sizeof(struct dhudevice)); 173 } 174 175 /* 176 * Routine called to attach a dhu. 177 */ 178 dhuattach(ui) 179 struct uba_device *ui; 180 { 181 182 dhusoftCAR[ui->ui_unit] = ui->ui_flags; 183 cbase[ui->ui_ubanum] = -1; 184 dhu_uballoc[ui->ui_ubanum] = -1; 185 } 186 187 /* 188 * Open a DHU11 line, mapping the clist onto the uba if this 189 * is the first dhu on this uba. Turn on this dhu if this is 190 * the first use of it. 191 */ 192 /*ARGSUSED*/ 193 dhuopen(dev, flag) 194 dev_t dev; 195 { 196 register struct tty *tp; 197 register int unit, dhu; 198 register struct dhudevice *addr; 199 register struct uba_device *ui; 200 int s; 201 extern dhuparam(); 202 203 unit = UNIT(dev); 204 dhu = unit >> 4; 205 if (unit >= NDHULINE || (ui = dhuinfo[dhu])== 0 || ui->ui_alive == 0) 206 return (ENXIO); 207 tp = &dhu_tty[unit]; 208 if (tp->t_state & TS_XCLUDE && u.u_uid != 0) 209 return (EBUSY); 210 addr = (struct dhudevice *)ui->ui_addr; 211 tp->t_addr = (caddr_t)addr; 212 tp->t_oproc = dhustart; 213 tp->t_param = dhuparam; 214 /* 215 * While setting up state for this uba and this dhu, 216 * block uba resets which can clear the state. 217 */ 218 s = spl5(); 219 if (cbase[ui->ui_ubanum] == -1) { 220 dhu_uballoc[ui->ui_ubanum] = dhu; 221 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 222 (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 223 } 224 if ((dhuact&(1<<dhu)) == 0) { 225 addr->dhucsr = DHU_SELECT(0) | DHU_IE; 226 addr->dhutimo = DHU_DEF_TIMO; 227 dhuact |= (1<<dhu); 228 /* anything else to configure whole board */ 229 } 230 (void) splx(s); 231 /* 232 * If this is first open, initialize tty state to default. 233 */ 234 if ((tp->t_state&TS_ISOPEN) == 0) { 235 ttychars(tp); 236 #ifndef PORTSELECTOR 237 if (tp->t_ospeed == 0) { 238 #endif 239 tp->t_ispeed = SPEED; 240 tp->t_ospeed = SPEED; 241 ttsetwater(tp); 242 tp->t_iflag = TTYDEF_IFLAG; 243 tp->t_oflag = TTYDEF_OFLAG; 244 tp->t_lflag = LFLAG; 245 tp->t_cflag = TTYDEF_CFLAG; 246 #ifdef PORTSELECTOR 247 tp->t_cflag |= HUPCL; 248 #else 249 } 250 #endif 251 tp->t_dev = dev; 252 dhuparam(tp, &tp->t_termios); 253 } 254 /* 255 * Wait for carrier, then process line discipline specific open. 256 */ 257 s = spltty(); 258 if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) || 259 (dhusoftCAR[dhu] & (1<<(unit&0xf)))) 260 tp->t_state |= TS_CARR_ON; 261 while ((tp->t_state & TS_CARR_ON) == 0) { 262 tp->t_state |= TS_WOPEN; 263 sleep((caddr_t)&tp->t_rawq, TTIPRI); 264 } 265 (void) splx(s); 266 return ((*linesw[tp->t_line].l_open)(dev, tp)); 267 } 268 269 /* 270 * Close a DHU11 line, turning off the modem control. 271 */ 272 /*ARGSUSED*/ 273 dhuclose(dev, flag) 274 dev_t dev; 275 int flag; 276 { 277 register struct tty *tp; 278 register unit; 279 280 unit = UNIT(dev); 281 tp = &dhu_tty[unit]; 282 (*linesw[tp->t_line].l_close)(tp); 283 (void) dhumctl(unit, DHU_BRK, DMBIC); 284 if ((tp->t_state&TS_WOPEN) || (tp->t_cflag&HUPCL) || 285 (tp->t_state&TS_ISOPEN)==0) 286 #ifdef PORTSELECTOR 287 { 288 extern int wakeup(); 289 290 (void) dhumctl(unit, DHU_OFF, DMSET); 291 /* Hold DTR low for 0.5 seconds */ 292 timeout(wakeup, (caddr_t) &tp->t_dev, hz/2); 293 sleep((caddr_t) &tp->t_dev, PZERO); 294 } 295 #else 296 (void) dhumctl(unit, DHU_OFF, DMSET); 297 #endif PORTSELECTOR 298 ttyclose(tp); 299 } 300 301 dhuread(dev, uio) 302 dev_t dev; 303 struct uio *uio; 304 { 305 register struct tty *tp = &dhu_tty[UNIT(dev)]; 306 307 return ((*linesw[tp->t_line].l_read)(tp, uio)); 308 } 309 310 dhuwrite(dev, uio) 311 dev_t dev; 312 struct uio *uio; 313 { 314 register struct tty *tp = &dhu_tty[UNIT(dev)]; 315 316 return ((*linesw[tp->t_line].l_write)(tp, uio)); 317 } 318 319 /* 320 * DHU11 receiver interrupt. 321 */ 322 dhurint(dhu) 323 int dhu; 324 { 325 register struct tty *tp; 326 register creg, c; 327 register struct dhudevice *addr; 328 register struct tty *tp0; 329 register struct uba_device *ui; 330 register line; 331 int overrun = 0; 332 333 #ifdef QBA 334 (void) spltty(); 335 #endif 336 ui = dhuinfo[dhu]; 337 if (ui == 0 || ui->ui_alive == 0) 338 return; 339 addr = (struct dhudevice *)ui->ui_addr; 340 tp0 = &dhu_tty[dhu<<4]; 341 /* 342 * Loop fetching characters from the silo for this 343 * dhu until there are no more in the silo. 344 */ 345 while ((creg = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */ 346 line = DHU_RX_LINE(creg); 347 tp = tp0 + line; 348 c = creg & 0xff; 349 if ((creg & DHU_RB_STAT) == DHU_RB_STAT) { 350 /* 351 * modem changed or diag info 352 */ 353 if (creg & DHU_RB_DIAG) { 354 /* decode diagnostic messages */ 355 continue; 356 } 357 if (creg & DHU_ST_DCD) 358 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 359 else if ((dhusoftCAR[dhu] & (1<<line)) == 0 && 360 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 361 (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET); 362 continue; 363 } 364 if ((tp->t_state&TS_ISOPEN) == 0) { 365 wakeup((caddr_t)&tp->t_rawq); 366 #ifdef PORTSELECTOR 367 if ((tp->t_state&TS_WOPEN) == 0) 368 #endif 369 continue; 370 } 371 #ifdef COMPAT_43 372 if (tp->t_line != POSXDISC) { 373 if (creg & DHU_RB_PE) 374 if ((tp->t_flags&(EVENP|ODDP)) == EVENP || 375 (tp->t_flags&(EVENP|ODDP)) == ODDP) 376 continue; 377 if ((creg & DHU_RB_DO) && overrun == 0) { 378 log(LOG_WARNING, "dhu%d: silo overflow\n", dhu); 379 overrun = 1; 380 } 381 if (creg & DHU_RB_FE) 382 /* 383 * At framing error (break) generate 384 * a null (in raw mode, for getty), or a 385 * interrupt (in cooked/cbreak mode). 386 */ 387 if (tp->t_flags&RAW) 388 c = 0; 389 else 390 c = tp->t_intrc; 391 } else { 392 #endif /*COMPAT_43*/ 393 if (creg & DHU_RB_PE) 394 c |= TTY_PE; 395 if (creg & DHU_RB_DO && overrun == 0) { 396 log(LOG_WARNING, "dhu%d: silo overflow\n", dhu); 397 overrun = 1; 398 } 399 if (creg & DHU_RB_FE) 400 c |= TTY_FE; 401 #ifdef COMPAT_43 402 } 403 #endif 404 405 #if NBK > 0 406 if (tp->t_line == NETLDISC) { 407 c &= 0x7f; 408 BKINPUT(c, tp); 409 } else 410 #endif 411 (*linesw[tp->t_line].l_rint)(c, tp); 412 } 413 } 414 415 /* 416 * Ioctl for DHU11. 417 */ 418 /*ARGSUSED*/ 419 dhuioctl(dev, cmd, data, flag) 420 caddr_t data; 421 { 422 register struct tty *tp; 423 register int unit = UNIT(dev); 424 int error; 425 426 tp = &dhu_tty[unit]; 427 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 428 if (error >= 0) 429 return (error); 430 error = ttioctl(tp, cmd, data, flag); 431 if (error >= 0) 432 return (error); 433 434 switch (cmd) { 435 case TIOCSBRK: 436 (void) dhumctl(unit, DHU_BRK, DMBIS); 437 break; 438 439 case TIOCCBRK: 440 (void) dhumctl(unit, DHU_BRK, DMBIC); 441 break; 442 443 case TIOCSDTR: 444 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS); 445 break; 446 447 case TIOCCDTR: 448 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC); 449 break; 450 451 case TIOCMSET: 452 (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET); 453 break; 454 455 case TIOCMBIS: 456 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS); 457 break; 458 459 case TIOCMBIC: 460 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC); 461 break; 462 463 case TIOCMGET: 464 *(int *)data = dhutodm(dhumctl(dev, 0, DMGET)); 465 break; 466 default: 467 return (ENOTTY); 468 } 469 return (0); 470 } 471 472 dmtodhu(bits) 473 register int bits; 474 { 475 register int b = 0; 476 477 if (bits & DML_RTS) b |= DHU_RTS; 478 if (bits & DML_DTR) b |= DHU_DTR; 479 if (bits & DML_LE) b |= DHU_LE; 480 return(b); 481 } 482 483 dhutodm(bits) 484 register int bits; 485 { 486 register int b = 0; 487 488 if (bits & DHU_DSR) b |= DML_DSR; 489 if (bits & DHU_RNG) b |= DML_RNG; 490 if (bits & DHU_CAR) b |= DML_CAR; 491 if (bits & DHU_CTS) b |= DML_CTS; 492 if (bits & DHU_RTS) b |= DML_RTS; 493 if (bits & DHU_DTR) b |= DML_DTR; 494 if (bits & DHU_LE) b |= DML_LE; 495 return(b); 496 } 497 498 499 /* 500 * Set parameters from open or stty into the DHU hardware 501 * registers. Impossible values for speed or character 502 * size are ignored and not copied back into tp. 503 */ 504 dhuparam(tp, want) 505 register struct tty *tp; 506 register struct termios *want; 507 { 508 register int unit = UNIT(tp->t_dev); 509 register struct dhudevice *addr = (struct dhudevice *)tp->t_addr; 510 register int lpar; 511 register long cflag; 512 register int incode, outcode; 513 int s; 514 515 /* 516 * Block interrupts so parameters will be set 517 * before the line interrupts. 518 */ 519 s = spltty(); 520 521 if (want->c_ospeed == 0) { 522 tp->t_ospeed = 0; 523 tp->t_cflag |= HUPCL; 524 (void)dhumctl(unit, DHU_OFF, DMSET); 525 splx(s); 526 return; 527 } 528 529 if ((outcode = ttspeedtab(want->c_ospeed, dhuspeedtab)) >= 0) 530 tp->t_ospeed = want->c_ospeed; 531 else 532 outcode = ttspeedtab(tp->t_ospeed, dhuspeedtab); 533 534 if (want->c_ispeed == 0) { 535 tp->t_ispeed = 0; 536 incode = outcode; 537 } else if ((incode = ttspeedtab(want->c_ispeed, dhuspeedtab)) >= 0) 538 tp->t_ispeed = want->c_ispeed; 539 else 540 incode = ttspeedtab(tp->t_ispeed, dhuspeedtab); 541 542 lpar = ((char)outcode<<12) | ((char)incode<<8); 543 544 switch (want->c_cflag&CSIZE) { 545 case CS6: case CS7: case CS8: 546 tp->t_cflag = want->c_cflag; 547 break; 548 default: 549 tp->t_cflag = (tp->t_cflag&CSIZE) | (want->c_cflag & ~CSIZE); 550 } 551 cflag = tp->t_cflag; 552 553 switch(cflag&CSIZE) { 554 case CS6: 555 lpar |= DHU_LP_BITS6; 556 break; 557 case CS7: 558 lpar |= DHU_LP_BITS7; 559 break; 560 case CS8: 561 lpar |= DHU_LP_BITS8; 562 break; 563 } 564 if (cflag&PARENB) { 565 lpar |= DHU_LP_PENABLE; 566 if ((cflag&PARODD) == 0) 567 lpar |= DHU_LP_EPAR; 568 } 569 if (cflag&CSTOPB) 570 lpar |= DHU_LP_TWOSB; 571 if (cflag&CREAD) 572 addr->dhucsr = DHU_SELECT(unit) | DHU_IE; 573 else 574 addr->dhucsr = DHU_SELECT(unit) | DHU_CS_TIE; 575 576 addr->dhulpr = lpar; 577 splx(s); 578 } 579 580 /* 581 * DHU11 transmitter interrupt. 582 * Restart each line which used to be active but has 583 * terminated transmission since the last interrupt. 584 */ 585 dhuxint(dhu) 586 int dhu; 587 { 588 register struct tty *tp; 589 register struct dhudevice *addr; 590 register struct tty *tp0; 591 register struct uba_device *ui; 592 register int line, t; 593 u_short cntr; 594 595 #ifdef QBA 596 (void) spl5(); 597 #endif 598 ui = dhuinfo[dhu]; 599 tp0 = &dhu_tty[dhu<<4]; 600 addr = (struct dhudevice *)ui->ui_addr; 601 while ((t = addr->dhucsrh) & DHU_CSH_TI) { 602 line = DHU_TX_LINE(t); 603 tp = tp0 + line; 604 tp->t_state &= ~TS_BUSY; 605 if (t & DHU_CSH_NXM) { 606 printf("dhu(%d,%d): NXM fault\n", dhu, line); 607 /* SHOULD RESTART OR SOMETHING... */ 608 } 609 if (tp->t_state&TS_FLUSH) 610 tp->t_state &= ~TS_FLUSH; 611 else { 612 addr->dhucsrl = DHU_SELECT(line) | DHU_IE; 613 /* 614 * Do arithmetic in a short to make up 615 * for lost 16&17 bits. 616 */ 617 cntr = addr->dhubar1 - 618 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 619 ndflush(&tp->t_outq, (int)cntr); 620 } 621 if (tp->t_line) 622 (*linesw[tp->t_line].l_start)(tp); 623 else 624 dhustart(tp); 625 } 626 } 627 628 /* 629 * Start (restart) transmission on the given DHU11 line. 630 */ 631 dhustart(tp) 632 register struct tty *tp; 633 { 634 register struct dhudevice *addr; 635 register int car, dhu, unit, nch; 636 int s; 637 638 unit = minor(tp->t_dev); 639 dhu = unit >> 4; 640 unit &= 0xf; 641 addr = (struct dhudevice *)tp->t_addr; 642 643 /* 644 * Must hold interrupts in following code to prevent 645 * state of the tp from changing. 646 */ 647 s = spl5(); 648 /* 649 * If it's currently active, or delaying, no need to do anything. 650 */ 651 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 652 goto out; 653 /* 654 * If there are sleepers, and output has drained below low 655 * water mark, wake up the sleepers.. 656 */ 657 if (tp->t_outq.c_cc <= tp->t_lowat) { 658 if (tp->t_state&TS_ASLEEP) { 659 tp->t_state &= ~TS_ASLEEP; 660 wakeup((caddr_t)&tp->t_outq); 661 } 662 if (tp->t_wsel) { 663 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 664 tp->t_wsel = 0; 665 tp->t_state &= ~TS_WCOLL; 666 } 667 } 668 /* 669 * Now restart transmission unless the output queue is 670 * empty. 671 */ 672 if (tp->t_outq.c_cc == 0) 673 goto out; 674 if (!(tp->t_oflag & OPOST)) 675 nch = ndqb(&tp->t_outq, 0); 676 else { 677 nch = ndqb(&tp->t_outq, 0200); 678 /* 679 * If first thing on queue is a delay process it. 680 */ 681 if (nch == 0) { 682 nch = getc(&tp->t_outq); 683 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 684 tp->t_state |= TS_TIMEOUT; 685 goto out; 686 } 687 } 688 /* 689 * If characters to transmit, restart transmission. 690 */ 691 if (nch) { 692 car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum); 693 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; 694 addr->dhulcr &= ~DHU_LC_TXABORT; 695 addr->dhubcr = nch; 696 addr->dhubar1 = car; 697 addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) | 698 DHU_BA2_DMAGO; 699 tp->t_state |= TS_BUSY; 700 } 701 out: 702 splx(s); 703 } 704 705 /* 706 * Stop output on a line, e.g. for ^S/^Q or output flush. 707 */ 708 /*ARGSUSED*/ 709 dhustop(tp, flag) 710 register struct tty *tp; 711 { 712 register struct dhudevice *addr; 713 register int unit, s; 714 715 addr = (struct dhudevice *)tp->t_addr; 716 /* 717 * Block input/output interrupts while messing with state. 718 */ 719 s = spl5(); 720 if (tp->t_state & TS_BUSY) { 721 /* 722 * Device is transmitting; stop output 723 * by selecting the line and setting the 724 * abort xmit bit. We will get an xmit interrupt, 725 * where we will figure out where to continue the 726 * next time the transmitter is enabled. If 727 * TS_FLUSH is set, the outq will be flushed. 728 * In either case, dhustart will clear the TXABORT bit. 729 */ 730 unit = minor(tp->t_dev); 731 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; 732 addr->dhulcr |= DHU_LC_TXABORT; 733 if ((tp->t_state&TS_TTSTOP)==0) 734 tp->t_state |= TS_FLUSH; 735 } 736 (void) splx(s); 737 } 738 739 /* 740 * DHU11 modem control 741 */ 742 dhumctl(dev, bits, how) 743 dev_t dev; 744 int bits, how; 745 { 746 register struct dhudevice *dhuaddr; 747 register int unit, mbits; 748 int s; 749 750 unit = UNIT(dev); 751 dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr); 752 unit &= 0xf; 753 s = spl5(); 754 dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE; 755 /* 756 * combine byte from stat register (read only, bits 16..23) 757 * with lcr register (read write, bits 0..15). 758 */ 759 mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16); 760 switch (how) { 761 case DMSET: 762 mbits = (mbits & 0xff0000) | bits; 763 break; 764 765 case DMBIS: 766 mbits |= bits; 767 break; 768 769 case DMBIC: 770 mbits &= ~bits; 771 break; 772 773 case DMGET: 774 (void) splx(s); 775 return(mbits); 776 } 777 dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN; 778 dhuaddr->dhulcr2 = DHU_LC2_TXEN; 779 (void) splx(s); 780 return(mbits); 781 } 782 783 /* 784 * Reset state of driver if UBA reset was necessary. 785 * Reset the line and modem control registers. 786 * restart transmitters. 787 */ 788 dhureset(uban) 789 int uban; 790 { 791 register int dhu, unit; 792 register struct tty *tp; 793 register struct uba_device *ui; 794 register struct dhudevice *addr; 795 int i; 796 797 for (dhu = 0; dhu < NDHU; dhu++) { 798 ui = dhuinfo[dhu]; 799 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 800 continue; 801 printf(" dhu%d", dhu); 802 if (dhu_uballoc[uban] == dhu) { 803 int info; 804 805 info = uballoc(uban, (caddr_t)cfree, 806 nclist * sizeof(struct cblock), UBA_CANTWAIT); 807 if (info) 808 cbase[uban] = UBAI_ADDR(info); 809 else { 810 printf(" [can't get uba map]"); 811 cbase[uban] = -1; 812 } 813 } 814 addr = (struct dhudevice *)ui->ui_addr; 815 addr->dhucsr = DHU_SELECT(0) | DHU_IE; 816 addr->dhutimo = DHU_DEF_TIMO; 817 unit = dhu * 16; 818 for (i = 0; i < 16; i++) { 819 tp = &dhu_tty[unit]; 820 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 821 dhuparam(tp, &tp->t_termios); 822 (void)dhumctl(unit, DHU_ON, DMSET); 823 tp->t_state &= ~TS_BUSY; 824 dhustart(tp); 825 } 826 unit++; 827 } 828 } 829 } 830 #endif 831