|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)dca.c 7.12 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "dca.h" ! 37: #if NDCA > 0 ! 38: /* ! 39: * 98626/98644/internal serial interface ! 40: * uses National Semiconductor INS8250/NS16550AF UART ! 41: */ ! 42: #include "sys/param.h" ! 43: #include "sys/systm.h" ! 44: #include "sys/ioctl.h" ! 45: #include "sys/tty.h" ! 46: #include "sys/proc.h" ! 47: #include "sys/conf.h" ! 48: #include "sys/file.h" ! 49: #include "sys/uio.h" ! 50: #include "sys/kernel.h" ! 51: #include "sys/syslog.h" ! 52: ! 53: #include "device.h" ! 54: #include "dcareg.h" ! 55: #include "machine/cpu.h" ! 56: #include "../hp300/isr.h" ! 57: ! 58: int dcaprobe(); ! 59: struct driver dcadriver = { ! 60: dcaprobe, "dca", ! 61: }; ! 62: ! 63: int dcastart(), dcaparam(), dcaintr(); ! 64: int dcasoftCAR; ! 65: int dca_active; ! 66: int dca_hasfifo; ! 67: int ndca = NDCA; ! 68: #ifdef DCACONSOLE ! 69: int dcaconsole = DCACONSOLE; ! 70: #else ! 71: int dcaconsole = -1; ! 72: #endif ! 73: int dcaconsinit; ! 74: int dcadefaultrate = TTYDEF_SPEED; ! 75: int dcamajor; ! 76: struct dcadevice *dca_addr[NDCA]; ! 77: struct tty dca_tty[NDCA]; ! 78: struct isr dcaisr[NDCA]; ! 79: ! 80: struct speedtab dcaspeedtab[] = { ! 81: 0, 0, ! 82: 50, DCABRD(50), ! 83: 75, DCABRD(75), ! 84: 110, DCABRD(110), ! 85: 134, DCABRD(134), ! 86: 150, DCABRD(150), ! 87: 200, DCABRD(200), ! 88: 300, DCABRD(300), ! 89: 600, DCABRD(600), ! 90: 1200, DCABRD(1200), ! 91: 1800, DCABRD(1800), ! 92: 2400, DCABRD(2400), ! 93: 4800, DCABRD(4800), ! 94: 9600, DCABRD(9600), ! 95: 19200, DCABRD(19200), ! 96: 38400, DCABRD(38400), ! 97: -1, -1 ! 98: }; ! 99: ! 100: extern struct tty *constty; ! 101: #ifdef KGDB ! 102: #include "machine/remote-sl.h" ! 103: ! 104: extern dev_t kgdb_dev; ! 105: extern int kgdb_rate; ! 106: extern int kgdb_debug_init; ! 107: #endif ! 108: ! 109: #define UNIT(x) minor(x) ! 110: ! 111: #ifdef DEBUG ! 112: long fifoin[17]; ! 113: long fifoout[17]; ! 114: long dcaintrcount[16]; ! 115: long dcamintcount[16]; ! 116: #endif ! 117: ! 118: dcaprobe(hd) ! 119: register struct hp_device *hd; ! 120: { ! 121: register struct dcadevice *dca; ! 122: register int unit; ! 123: ! 124: dca = (struct dcadevice *)hd->hp_addr; ! 125: if (dca->dca_irid != DCAID0 && ! 126: dca->dca_irid != DCAREMID0 && ! 127: dca->dca_irid != DCAID1 && ! 128: dca->dca_irid != DCAREMID1) ! 129: return (0); ! 130: unit = hd->hp_unit; ! 131: if (unit == dcaconsole) ! 132: DELAY(100000); ! 133: dca->dca_irid = 0xFF; ! 134: DELAY(100); ! 135: ! 136: /* look for a NS 16550AF UART with FIFOs */ ! 137: dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; ! 138: DELAY(100); ! 139: if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) ! 140: dca_hasfifo |= 1 << unit; ! 141: ! 142: hd->hp_ipl = DCAIPL(dca->dca_ic); ! 143: dcaisr[unit].isr_ipl = hd->hp_ipl; ! 144: dcaisr[unit].isr_arg = unit; ! 145: dcaisr[unit].isr_intr = dcaintr; ! 146: dca_addr[unit] = dca; ! 147: dca_active |= 1 << unit; ! 148: dcasoftCAR = hd->hp_flags; ! 149: isrlink(&dcaisr[unit]); ! 150: #ifdef KGDB ! 151: if (kgdb_dev == makedev(dcamajor, unit)) { ! 152: if (dcaconsole == unit) ! 153: kgdb_dev = NODEV; /* can't debug over console port */ ! 154: else { ! 155: (void) dcainit(unit, kgdb_rate); ! 156: dcaconsinit = 1; /* don't re-init in dcaputc */ ! 157: if (kgdb_debug_init) { ! 158: /* ! 159: * Print prefix of device name, ! 160: * let kgdb_connect print the rest. ! 161: */ ! 162: printf("dca%d: ", unit); ! 163: kgdb_connect(1); ! 164: } else ! 165: printf("dca%d: kgdb enabled\n", unit); ! 166: } ! 167: } ! 168: #endif ! 169: dca->dca_ic = IC_IE; ! 170: /* ! 171: * Need to reset baud rate, etc. of next print so reset dcaconsinit. ! 172: * Also make sure console is always "hardwired." ! 173: */ ! 174: if (unit == dcaconsole) { ! 175: dcaconsinit = 0; ! 176: dcasoftCAR |= (1 << unit); ! 177: } ! 178: return (1); ! 179: } ! 180: ! 181: /* ARGSUSED */ ! 182: #ifdef __STDC__ ! 183: dcaopen(dev_t dev, int flag, int mode, struct proc *p) ! 184: #else ! 185: dcaopen(dev, flag, mode, p) ! 186: dev_t dev; ! 187: int flag, mode; ! 188: struct proc *p; ! 189: #endif ! 190: { ! 191: register struct tty *tp; ! 192: register int unit; ! 193: int error = 0; ! 194: ! 195: unit = UNIT(dev); ! 196: if (unit >= NDCA || (dca_active & (1 << unit)) == 0) ! 197: return (ENXIO); ! 198: tp = &dca_tty[unit]; ! 199: tp->t_oproc = dcastart; ! 200: tp->t_param = dcaparam; ! 201: tp->t_dev = dev; ! 202: if ((tp->t_state & TS_ISOPEN) == 0) { ! 203: tp->t_state |= TS_WOPEN; ! 204: ttychars(tp); ! 205: if (tp->t_ispeed == 0) { ! 206: tp->t_iflag = TTYDEF_IFLAG; ! 207: tp->t_oflag = TTYDEF_OFLAG; ! 208: tp->t_cflag = TTYDEF_CFLAG; ! 209: tp->t_lflag = TTYDEF_LFLAG; ! 210: tp->t_ispeed = tp->t_ospeed = dcadefaultrate; ! 211: } ! 212: dcaparam(tp, &tp->t_termios); ! 213: ttsetwater(tp); ! 214: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) ! 215: return (EBUSY); ! 216: (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); ! 217: if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) ! 218: tp->t_state |= TS_CARR_ON; ! 219: (void) spltty(); ! 220: while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && ! 221: (tp->t_state & TS_CARR_ON) == 0) { ! 222: tp->t_state |= TS_WOPEN; ! 223: if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ! 224: ttopen, 0)) ! 225: break; ! 226: } ! 227: (void) spl0(); ! 228: if (error == 0) ! 229: error = (*linesw[tp->t_line].l_open)(dev, tp); ! 230: return (error); ! 231: } ! 232: ! 233: /*ARGSUSED*/ ! 234: dcaclose(dev, flag, mode, p) ! 235: dev_t dev; ! 236: int flag, mode; ! 237: struct proc *p; ! 238: { ! 239: register struct tty *tp; ! 240: register struct dcadevice *dca; ! 241: register int unit; ! 242: ! 243: unit = UNIT(dev); ! 244: dca = dca_addr[unit]; ! 245: tp = &dca_tty[unit]; ! 246: (*linesw[tp->t_line].l_close)(tp, flag); ! 247: dca->dca_cfcr &= ~CFCR_SBREAK; ! 248: #ifdef KGDB ! 249: /* do not disable interrupts if debugging */ ! 250: if (dev != kgdb_dev) ! 251: #endif ! 252: dca->dca_ier = 0; ! 253: if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || ! 254: (tp->t_state&TS_ISOPEN) == 0) ! 255: (void) dcamctl(dev, 0, DMSET); ! 256: ttyclose(tp); ! 257: return (0); ! 258: } ! 259: ! 260: dcaread(dev, uio, flag) ! 261: dev_t dev; ! 262: struct uio *uio; ! 263: { ! 264: register struct tty *tp = &dca_tty[UNIT(dev)]; ! 265: ! 266: return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); ! 267: } ! 268: ! 269: dcawrite(dev, uio, flag) ! 270: dev_t dev; ! 271: struct uio *uio; ! 272: { ! 273: int unit = UNIT(dev); ! 274: register struct tty *tp = &dca_tty[unit]; ! 275: ! 276: /* ! 277: * (XXX) We disallow virtual consoles if the physical console is ! 278: * a serial port. This is in case there is a display attached that ! 279: * is not the console. In that situation we don't need/want the X ! 280: * server taking over the console. ! 281: */ ! 282: if (constty && unit == dcaconsole) ! 283: constty = NULL; ! 284: return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); ! 285: } ! 286: ! 287: dcaintr(unit) ! 288: register int unit; ! 289: { ! 290: register struct dcadevice *dca; ! 291: register u_char code; ! 292: register struct tty *tp; ! 293: ! 294: dca = dca_addr[unit]; ! 295: if ((dca->dca_ic & IC_IR) == 0) ! 296: return (0); ! 297: while (1) { ! 298: code = dca->dca_iir; ! 299: #ifdef DEBUG ! 300: dcaintrcount[code & IIR_IMASK]++; ! 301: #endif ! 302: switch (code & IIR_IMASK) { ! 303: case IIR_NOPEND: ! 304: return (1); ! 305: case IIR_RXTOUT: ! 306: case IIR_RXRDY: ! 307: /* do time-critical read in-line */ ! 308: tp = &dca_tty[unit]; ! 309: /* ! 310: * Process a received byte. Inline for speed... ! 311: */ ! 312: #ifdef KGDB ! 313: #define RCVBYTE() \ ! 314: code = dca->dca_data; \ ! 315: if ((tp->t_state & TS_ISOPEN) == 0) { \ ! 316: if (code == FRAME_END && \ ! 317: kgdb_dev == makedev(dcamajor, unit)) \ ! 318: kgdb_connect(0); /* trap into kgdb */ \ ! 319: } else \ ! 320: (*linesw[tp->t_line].l_rint)(code, tp) ! 321: #else ! 322: #define RCVBYTE() \ ! 323: code = dca->dca_data; \ ! 324: if ((tp->t_state & TS_ISOPEN) != 0) \ ! 325: (*linesw[tp->t_line].l_rint)(code, tp) ! 326: #endif ! 327: RCVBYTE(); ! 328: if (dca_hasfifo & (1 << unit)) { ! 329: #ifdef DEBUG ! 330: register int fifocnt = 1; ! 331: #endif ! 332: while ((code = dca->dca_lsr) & LSR_RCV_MASK) { ! 333: if (code == LSR_RXRDY) { ! 334: RCVBYTE(); ! 335: } else ! 336: dcaeint(unit, code, dca); ! 337: #ifdef DEBUG ! 338: fifocnt++; ! 339: #endif ! 340: } ! 341: #ifdef DEBUG ! 342: if (fifocnt > 16) ! 343: fifoin[0]++; ! 344: else ! 345: fifoin[fifocnt]++; ! 346: #endif ! 347: } ! 348: break; ! 349: case IIR_TXRDY: ! 350: tp = &dca_tty[unit]; ! 351: tp->t_state &=~ (TS_BUSY|TS_FLUSH); ! 352: if (tp->t_line) ! 353: (*linesw[tp->t_line].l_start)(tp); ! 354: else ! 355: dcastart(tp); ! 356: break; ! 357: case IIR_RLS: ! 358: dcaeint(unit, dca->dca_lsr, dca); ! 359: break; ! 360: default: ! 361: if (code & IIR_NOPEND) ! 362: return (1); ! 363: log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", ! 364: unit, code); ! 365: /* fall through */ ! 366: case IIR_MLSC: ! 367: dcamint(unit, dca); ! 368: break; ! 369: } ! 370: } ! 371: } ! 372: ! 373: dcaeint(unit, stat, dca) ! 374: register int unit, stat; ! 375: register struct dcadevice *dca; ! 376: { ! 377: register struct tty *tp; ! 378: register int c; ! 379: ! 380: tp = &dca_tty[unit]; ! 381: c = dca->dca_data; ! 382: if ((tp->t_state & TS_ISOPEN) == 0) { ! 383: #ifdef KGDB ! 384: /* we don't care about parity errors */ ! 385: if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && ! 386: kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) ! 387: kgdb_connect(0); /* trap into kgdb */ ! 388: #endif ! 389: return; ! 390: } ! 391: if (stat & (LSR_BI | LSR_FE)) ! 392: c |= TTY_FE; ! 393: else if (stat & LSR_PE) ! 394: c |= TTY_PE; ! 395: else if (stat & LSR_OE) ! 396: log(LOG_WARNING, "dca%d: silo overflow\n", unit); ! 397: (*linesw[tp->t_line].l_rint)(c, tp); ! 398: } ! 399: ! 400: dcamint(unit, dca) ! 401: register int unit; ! 402: register struct dcadevice *dca; ! 403: { ! 404: register struct tty *tp; ! 405: register int stat; ! 406: ! 407: tp = &dca_tty[unit]; ! 408: stat = dca->dca_msr; ! 409: #ifdef DEBUG ! 410: dcamintcount[stat & 0xf]++; ! 411: #endif ! 412: if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { ! 413: if (stat & MSR_DCD) ! 414: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 415: else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) ! 416: dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); ! 417: } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && ! 418: (tp->t_flags & CRTSCTS)) { ! 419: /* the line is up and we want to do rts/cts flow control */ ! 420: if (stat & MSR_CTS) { ! 421: tp->t_state &=~ TS_TTSTOP; ! 422: ttstart(tp); ! 423: } else ! 424: tp->t_state |= TS_TTSTOP; ! 425: } ! 426: } ! 427: ! 428: dcaioctl(dev, cmd, data, flag) ! 429: dev_t dev; ! 430: caddr_t data; ! 431: { ! 432: register struct tty *tp; ! 433: register int unit = UNIT(dev); ! 434: register struct dcadevice *dca; ! 435: register int error; ! 436: ! 437: tp = &dca_tty[unit]; ! 438: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 439: if (error >= 0) ! 440: return (error); ! 441: error = ttioctl(tp, cmd, data, flag); ! 442: if (error >= 0) ! 443: return (error); ! 444: ! 445: dca = dca_addr[unit]; ! 446: switch (cmd) { ! 447: ! 448: case TIOCSBRK: ! 449: dca->dca_cfcr |= CFCR_SBREAK; ! 450: break; ! 451: ! 452: case TIOCCBRK: ! 453: dca->dca_cfcr &= ~CFCR_SBREAK; ! 454: break; ! 455: ! 456: case TIOCSDTR: ! 457: (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); ! 458: break; ! 459: ! 460: case TIOCCDTR: ! 461: (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); ! 462: break; ! 463: ! 464: case TIOCMSET: ! 465: (void) dcamctl(dev, *(int *)data, DMSET); ! 466: break; ! 467: ! 468: case TIOCMBIS: ! 469: (void) dcamctl(dev, *(int *)data, DMBIS); ! 470: break; ! 471: ! 472: case TIOCMBIC: ! 473: (void) dcamctl(dev, *(int *)data, DMBIC); ! 474: break; ! 475: ! 476: case TIOCMGET: ! 477: *(int *)data = dcamctl(dev, 0, DMGET); ! 478: break; ! 479: ! 480: default: ! 481: return (ENOTTY); ! 482: } ! 483: return (0); ! 484: } ! 485: ! 486: dcaparam(tp, t) ! 487: register struct tty *tp; ! 488: register struct termios *t; ! 489: { ! 490: register struct dcadevice *dca; ! 491: register int cfcr, cflag = t->c_cflag; ! 492: int unit = UNIT(tp->t_dev); ! 493: int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); ! 494: ! 495: /* check requested parameters */ ! 496: if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) ! 497: return (EINVAL); ! 498: /* and copy to tty */ ! 499: tp->t_ispeed = t->c_ispeed; ! 500: tp->t_ospeed = t->c_ospeed; ! 501: tp->t_cflag = cflag; ! 502: ! 503: dca = dca_addr[unit]; ! 504: dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; ! 505: if (ospeed == 0) { ! 506: (void) dcamctl(unit, 0, DMSET); /* hang up line */ ! 507: return (0); ! 508: } ! 509: dca->dca_cfcr |= CFCR_DLAB; ! 510: dca->dca_data = ospeed & 0xFF; ! 511: dca->dca_ier = ospeed >> 8; ! 512: switch (cflag&CSIZE) { ! 513: case CS5: ! 514: cfcr = CFCR_5BITS; break; ! 515: case CS6: ! 516: cfcr = CFCR_6BITS; break; ! 517: case CS7: ! 518: cfcr = CFCR_7BITS; break; ! 519: case CS8: ! 520: cfcr = CFCR_8BITS; break; ! 521: } ! 522: if (cflag&PARENB) { ! 523: cfcr |= CFCR_PENAB; ! 524: if ((cflag&PARODD) == 0) ! 525: cfcr |= CFCR_PEVEN; ! 526: } ! 527: if (cflag&CSTOPB) ! 528: cfcr |= CFCR_STOPB; ! 529: dca->dca_cfcr = cfcr; ! 530: if (dca_hasfifo & (1 << unit)) ! 531: dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; ! 532: return (0); ! 533: } ! 534: ! 535: dcastart(tp) ! 536: register struct tty *tp; ! 537: { ! 538: register struct dcadevice *dca; ! 539: int s, unit, c; ! 540: ! 541: unit = UNIT(tp->t_dev); ! 542: dca = dca_addr[unit]; ! 543: s = spltty(); ! 544: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) ! 545: goto out; ! 546: if (tp->t_outq.c_cc <= tp->t_lowat) { ! 547: if (tp->t_state&TS_ASLEEP) { ! 548: tp->t_state &= ~TS_ASLEEP; ! 549: wakeup((caddr_t)&tp->t_outq); ! 550: } ! 551: if (tp->t_wsel) { ! 552: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 553: tp->t_wsel = 0; ! 554: tp->t_state &= ~TS_WCOLL; ! 555: } ! 556: } ! 557: if (tp->t_outq.c_cc == 0) ! 558: goto out; ! 559: if (dca->dca_lsr & LSR_TXRDY) { ! 560: c = getc(&tp->t_outq); ! 561: tp->t_state |= TS_BUSY; ! 562: dca->dca_data = c; ! 563: if (dca_hasfifo & (1 << unit)) { ! 564: for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) ! 565: dca->dca_data = getc(&tp->t_outq); ! 566: #ifdef DEBUG ! 567: if (c > 16) ! 568: fifoout[0]++; ! 569: else ! 570: fifoout[c]++; ! 571: #endif ! 572: } ! 573: } ! 574: out: ! 575: splx(s); ! 576: } ! 577: ! 578: /* ! 579: * Stop output on a line. ! 580: */ ! 581: /*ARGSUSED*/ ! 582: dcastop(tp, flag) ! 583: register struct tty *tp; ! 584: { ! 585: register int s; ! 586: ! 587: s = spltty(); ! 588: if (tp->t_state & TS_BUSY) { ! 589: if ((tp->t_state&TS_TTSTOP)==0) ! 590: tp->t_state |= TS_FLUSH; ! 591: } ! 592: splx(s); ! 593: } ! 594: ! 595: dcamctl(dev, bits, how) ! 596: dev_t dev; ! 597: int bits, how; ! 598: { ! 599: register struct dcadevice *dca; ! 600: register int unit; ! 601: int s; ! 602: ! 603: unit = UNIT(dev); ! 604: dca = dca_addr[unit]; ! 605: s = spltty(); ! 606: switch (how) { ! 607: ! 608: case DMSET: ! 609: dca->dca_mcr = bits; ! 610: break; ! 611: ! 612: case DMBIS: ! 613: dca->dca_mcr |= bits; ! 614: break; ! 615: ! 616: case DMBIC: ! 617: dca->dca_mcr &= ~bits; ! 618: break; ! 619: ! 620: case DMGET: ! 621: bits = dca->dca_msr; ! 622: break; ! 623: } ! 624: (void) splx(s); ! 625: return (bits); ! 626: } ! 627: ! 628: /* ! 629: * Following are all routines needed for DCA to act as console ! 630: */ ! 631: #include "../hp300/cons.h" ! 632: ! 633: dcacnprobe(cp) ! 634: struct consdev *cp; ! 635: { ! 636: int unit; ! 637: ! 638: /* locate the major number */ ! 639: for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) ! 640: if (cdevsw[dcamajor].d_open == dcaopen) ! 641: break; ! 642: ! 643: /* XXX: ick */ ! 644: unit = CONUNIT; ! 645: dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); ! 646: ! 647: /* make sure hardware exists */ ! 648: if (badaddr((short *)dca_addr[unit])) { ! 649: cp->cn_pri = CN_DEAD; ! 650: return; ! 651: } ! 652: ! 653: /* initialize required fields */ ! 654: cp->cn_dev = makedev(dcamajor, unit); ! 655: cp->cn_tp = &dca_tty[unit]; ! 656: switch (dca_addr[unit]->dca_irid) { ! 657: case DCAID0: ! 658: case DCAID1: ! 659: cp->cn_pri = CN_NORMAL; ! 660: break; ! 661: case DCAREMID0: ! 662: case DCAREMID1: ! 663: cp->cn_pri = CN_REMOTE; ! 664: break; ! 665: default: ! 666: cp->cn_pri = CN_DEAD; ! 667: break; ! 668: } ! 669: /* ! 670: * If dcaconsole is initialized, raise our priority. ! 671: */ ! 672: if (dcaconsole == unit) ! 673: cp->cn_pri = CN_REMOTE; ! 674: #ifdef KGDB ! 675: if (major(kgdb_dev) == 1) /* XXX */ ! 676: kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); ! 677: #endif ! 678: } ! 679: ! 680: dcacninit(cp) ! 681: struct consdev *cp; ! 682: { ! 683: int unit = UNIT(cp->cn_dev); ! 684: ! 685: dcainit(unit, dcadefaultrate); ! 686: dcaconsole = unit; ! 687: dcaconsinit = 1; ! 688: } ! 689: ! 690: dcainit(unit, rate) ! 691: int unit, rate; ! 692: { ! 693: register struct dcadevice *dca; ! 694: int s; ! 695: short stat; ! 696: ! 697: #ifdef lint ! 698: stat = unit; if (stat) return; ! 699: #endif ! 700: dca = dca_addr[unit]; ! 701: s = splhigh(); ! 702: dca->dca_irid = 0xFF; ! 703: DELAY(100); ! 704: dca->dca_ic = IC_IE; ! 705: dca->dca_cfcr = CFCR_DLAB; ! 706: rate = ttspeedtab(rate, dcaspeedtab); ! 707: dca->dca_data = rate & 0xFF; ! 708: dca->dca_ier = rate >> 8; ! 709: dca->dca_cfcr = CFCR_8BITS; ! 710: dca->dca_ier = IER_ERXRDY | IER_ETXRDY; ! 711: dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; ! 712: stat = dca->dca_iir; ! 713: splx(s); ! 714: } ! 715: ! 716: dcacngetc(dev) ! 717: { ! 718: register struct dcadevice *dca = dca_addr[UNIT(dev)]; ! 719: short stat; ! 720: int c, s; ! 721: ! 722: #ifdef lint ! 723: stat = dev; if (stat) return (0); ! 724: #endif ! 725: s = splhigh(); ! 726: while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) ! 727: ; ! 728: c = dca->dca_data; ! 729: stat = dca->dca_iir; ! 730: splx(s); ! 731: return (c); ! 732: } ! 733: ! 734: /* ! 735: * Console kernel output character routine. ! 736: */ ! 737: dcacnputc(dev, c) ! 738: dev_t dev; ! 739: register int c; ! 740: { ! 741: register struct dcadevice *dca = dca_addr[UNIT(dev)]; ! 742: register int timo; ! 743: short stat; ! 744: int s = splhigh(); ! 745: ! 746: #ifdef lint ! 747: stat = dev; if (stat) return; ! 748: #endif ! 749: if (dcaconsinit == 0) { ! 750: (void) dcainit(UNIT(dev), dcadefaultrate); ! 751: dcaconsinit = 1; ! 752: } ! 753: /* wait for any pending transmission to finish */ ! 754: timo = 50000; ! 755: while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) ! 756: ; ! 757: dca->dca_data = c; ! 758: /* wait for this transmission to complete */ ! 759: timo = 1500000; ! 760: while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) ! 761: ; ! 762: /* clear any interrupts generated by this transmission */ ! 763: stat = dca->dca_iir; ! 764: splx(s); ! 765: } ! 766: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.