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