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