|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1991 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: * @(#)com.c 7.5 (Berkeley) 5/16/91 ! 34: */ ! 35: ! 36: #include "com.h" ! 37: #if NCOM > 0 ! 38: /* ! 39: * COM driver, based on HP dca driver ! 40: * uses National Semiconductor NS16450/NS16550AF UART ! 41: */ ! 42: #include "param.h" ! 43: #include "systm.h" ! 44: #include "ioctl.h" ! 45: #include "tty.h" ! 46: #include "proc.h" ! 47: #include "user.h" ! 48: #include "conf.h" ! 49: #include "file.h" ! 50: #include "uio.h" ! 51: #include "kernel.h" ! 52: #include "syslog.h" ! 53: ! 54: #include "i386/isa/isa_device.h" ! 55: #include "i386/isa/comreg.h" ! 56: #include "i386/isa/ic/ns16550.h" ! 57: ! 58: int comprobe(), comattach(), comintr(), comstart(), comparam(); ! 59: ! 60: struct isa_driver comdriver = { ! 61: comprobe, comattach, "com" ! 62: }; ! 63: ! 64: int comsoftCAR; ! 65: int com_active; ! 66: int com_hasfifo; ! 67: int ncom = NCOM; ! 68: #ifdef COMCONSOLE ! 69: int comconsole = COMCONSOLE; ! 70: #else ! 71: int comconsole = -1; ! 72: #endif ! 73: int comconsinit; ! 74: int comdefaultrate = TTYDEF_SPEED; ! 75: int commajor; ! 76: short com_addr[NCOM]; ! 77: struct tty com_tty[NCOM]; ! 78: ! 79: struct speedtab comspeedtab[] = { ! 80: 0, 0, ! 81: 50, COMBRD(50), ! 82: 75, COMBRD(75), ! 83: 110, COMBRD(110), ! 84: 134, COMBRD(134), ! 85: 150, COMBRD(150), ! 86: 200, COMBRD(200), ! 87: 300, COMBRD(300), ! 88: 600, COMBRD(600), ! 89: 1200, COMBRD(1200), ! 90: 1800, COMBRD(1800), ! 91: 2400, COMBRD(2400), ! 92: 4800, COMBRD(4800), ! 93: 9600, COMBRD(9600), ! 94: 19200, COMBRD(19200), ! 95: 38400, COMBRD(38400), ! 96: 57600, COMBRD(57600), ! 97: -1, -1 ! 98: }; ! 99: ! 100: extern struct tty *constty; ! 101: #ifdef KGDB ! 102: #include "machine/remote-sl.h" ! 103: ! 104: extern int kgdb_dev; ! 105: extern int kgdb_rate; ! 106: extern int kgdb_debug_init; ! 107: #endif ! 108: ! 109: #define UNIT(x) minor(x) ! 110: ! 111: comprobe(dev) ! 112: struct isa_device *dev; ! 113: { ! 114: /* force access to id reg */ ! 115: outb(dev->id_iobase+com_cfcr, 0); ! 116: outb(dev->id_iobase+com_iir, 0); ! 117: if ((inb(dev->id_iobase+com_iir) & 0x38) == 0) ! 118: return(1); ! 119: return(1); ! 120: ! 121: } ! 122: ! 123: ! 124: int ! 125: comattach(isdp) ! 126: struct isa_device *isdp; ! 127: { ! 128: struct tty *tp; ! 129: u_char unit; ! 130: int port = isdp->id_iobase; ! 131: ! 132: unit = isdp->id_unit; ! 133: if (unit == comconsole) ! 134: DELAY(100000); ! 135: com_addr[unit] = port; ! 136: com_active |= 1 << unit; ! 137: comsoftCAR |= 1 << unit; /* XXX */ ! 138: ! 139: /* look for a NS 16550AF UART with FIFOs */ ! 140: outb(port+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14); ! 141: DELAY(100); ! 142: if ((inb(port+com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK) ! 143: com_hasfifo |= 1 << unit; ! 144: ! 145: outb(port+com_ier, 0); ! 146: outb(port+com_mcr, 0 | MCR_IENABLE); ! 147: #ifdef KGDB ! 148: if (kgdb_dev == makedev(commajor, unit)) { ! 149: if (comconsole == unit) ! 150: kgdb_dev = -1; /* can't debug over console port */ ! 151: else { ! 152: (void) cominit(unit, kgdb_rate); ! 153: if (kgdb_debug_init) { ! 154: /* ! 155: * Print prefix of device name, ! 156: * let kgdb_connect print the rest. ! 157: */ ! 158: printf("com%d: ", unit); ! 159: kgdb_connect(1); ! 160: } else ! 161: printf("com%d: kgdb enabled\n", unit); ! 162: } ! 163: } ! 164: #endif ! 165: /* ! 166: * Need to reset baud rate, etc. of next print so reset comconsinit. ! 167: * Also make sure console is always "hardwired" ! 168: */ ! 169: if (unit == comconsole) { ! 170: comconsinit = 0; ! 171: comsoftCAR |= (1 << unit); ! 172: } ! 173: return (1); ! 174: } ! 175: ! 176: /* ARGSUSED */ ! 177: #ifdef __STDC__ ! 178: comopen(dev_t dev, int flag, int mode, struct proc *p) ! 179: #else ! 180: comopen(dev, flag, mode, p) ! 181: dev_t dev; ! 182: int flag, mode; ! 183: struct proc *p; ! 184: #endif ! 185: { ! 186: register struct tty *tp; ! 187: register int unit; ! 188: int error = 0; ! 189: ! 190: unit = UNIT(dev); ! 191: if (unit >= NCOM || (com_active & (1 << unit)) == 0) ! 192: return (ENXIO); ! 193: tp = &com_tty[unit]; ! 194: tp->t_oproc = comstart; ! 195: tp->t_param = comparam; ! 196: tp->t_dev = dev; ! 197: if ((tp->t_state & TS_ISOPEN) == 0) { ! 198: tp->t_state |= TS_WOPEN; ! 199: ttychars(tp); ! 200: if (tp->t_ispeed == 0) { ! 201: tp->t_iflag = TTYDEF_IFLAG; ! 202: tp->t_oflag = TTYDEF_OFLAG; ! 203: tp->t_cflag = TTYDEF_CFLAG; ! 204: tp->t_lflag = TTYDEF_LFLAG; ! 205: tp->t_ispeed = tp->t_ospeed = comdefaultrate; ! 206: } ! 207: comparam(tp, &tp->t_termios); ! 208: ttsetwater(tp); ! 209: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) ! 210: return (EBUSY); ! 211: (void) spltty(); ! 212: (void) commctl(dev, MCR_DTR | MCR_RTS, DMSET); ! 213: if ((comsoftCAR & (1 << unit)) || (commctl(dev, 0, DMGET) & MSR_DCD)) ! 214: tp->t_state |= TS_CARR_ON; ! 215: while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && ! 216: (tp->t_state & TS_CARR_ON) == 0) { ! 217: tp->t_state |= TS_WOPEN; ! 218: if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ! 219: ttopen, 0)) ! 220: break; ! 221: } ! 222: (void) spl0(); ! 223: if (error == 0) ! 224: error = (*linesw[tp->t_line].l_open)(dev, tp); ! 225: return (error); ! 226: } ! 227: ! 228: /*ARGSUSED*/ ! 229: comclose(dev, flag, mode, p) ! 230: dev_t dev; ! 231: int flag, mode; ! 232: struct proc *p; ! 233: { ! 234: register struct tty *tp; ! 235: register com; ! 236: register int unit; ! 237: ! 238: unit = UNIT(dev); ! 239: com = com_addr[unit]; ! 240: tp = &com_tty[unit]; ! 241: (*linesw[tp->t_line].l_close)(tp, flag); ! 242: outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK); ! 243: #ifdef KGDB ! 244: /* do not disable interrupts if debugging */ ! 245: if (kgdb_dev != makedev(commajor, unit)) ! 246: #endif ! 247: outb(com+com_ier, 0); ! 248: if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || ! 249: (tp->t_state&TS_ISOPEN) == 0) ! 250: (void) commctl(dev, 0, DMSET); ! 251: ttyclose(tp); ! 252: return(0); ! 253: } ! 254: ! 255: comread(dev, uio, flag) ! 256: dev_t dev; ! 257: struct uio *uio; ! 258: { ! 259: register struct tty *tp = &com_tty[UNIT(dev)]; ! 260: ! 261: return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); ! 262: } ! 263: ! 264: comwrite(dev, uio, flag) ! 265: dev_t dev; ! 266: struct uio *uio; ! 267: { ! 268: int unit = UNIT(dev); ! 269: register struct tty *tp = &com_tty[unit]; ! 270: ! 271: /* ! 272: * (XXX) We disallow virtual consoles if the physical console is ! 273: * a serial port. This is in case there is a display attached that ! 274: * is not the console. In that situation we don't need/want the X ! 275: * server taking over the console. ! 276: */ ! 277: if (constty && unit == comconsole) ! 278: constty = NULL; ! 279: return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); ! 280: } ! 281: ! 282: comintr(unit) ! 283: register int unit; ! 284: { ! 285: register com; ! 286: register u_char code; ! 287: register struct tty *tp; ! 288: ! 289: com = com_addr[unit]; ! 290: while (1) { ! 291: code = inb(com+com_iir); ! 292: switch (code & IIR_IMASK) { ! 293: case IIR_NOPEND: ! 294: return (1); ! 295: case IIR_RXTOUT: ! 296: case IIR_RXRDY: ! 297: tp = &com_tty[unit]; ! 298: /* ! 299: * Process received bytes. Inline for speed... ! 300: */ ! 301: #ifdef KGDB ! 302: #define RCVBYTE() \ ! 303: code = inb(com+com_data); \ ! 304: if ((tp->t_state & TS_ISOPEN) == 0) { \ ! 305: if (kgdb_dev == makedev(commajor, unit) && \ ! 306: code == FRAME_END) \ ! 307: kgdb_connect(0); /* trap into kgdb */ \ ! 308: } else \ ! 309: (*linesw[tp->t_line].l_rint)(code, tp) ! 310: #else ! 311: #define RCVBYTE() \ ! 312: code = inb(com+com_data); \ ! 313: if (tp->t_state & TS_ISOPEN) \ ! 314: (*linesw[tp->t_line].l_rint)(code, tp) ! 315: #endif ! 316: ! 317: RCVBYTE(); ! 318: ! 319: if (com_hasfifo & (1 << unit)) ! 320: while ((code = inb(com+com_lsr)) & LSR_RCV_MASK) { ! 321: if (code == LSR_RXRDY) { ! 322: RCVBYTE(); ! 323: } else ! 324: comeint(unit, code, com); ! 325: } ! 326: break; ! 327: case IIR_TXRDY: ! 328: tp = &com_tty[unit]; ! 329: tp->t_state &=~ (TS_BUSY|TS_FLUSH); ! 330: if (tp->t_line) ! 331: (*linesw[tp->t_line].l_start)(tp); ! 332: else ! 333: comstart(tp); ! 334: break; ! 335: case IIR_RLS: ! 336: comeint(unit, inb(com+com_lsr), com); ! 337: break; ! 338: default: ! 339: if (code & IIR_NOPEND) ! 340: return (1); ! 341: log(LOG_WARNING, "com%d: weird interrupt: 0x%x\n", ! 342: unit, code); ! 343: /* fall through */ ! 344: case IIR_MLSC: ! 345: commint(unit, com); ! 346: break; ! 347: } ! 348: } ! 349: } ! 350: ! 351: comeint(unit, stat, com) ! 352: register int unit, stat; ! 353: register com; ! 354: { ! 355: register struct tty *tp; ! 356: register int c; ! 357: ! 358: tp = &com_tty[unit]; ! 359: c = inb(com+com_data); ! 360: if ((tp->t_state & TS_ISOPEN) == 0) { ! 361: #ifdef KGDB ! 362: /* we don't care about parity errors */ ! 363: if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && ! 364: kgdb_dev == makedev(commajor, unit) && c == FRAME_END) ! 365: kgdb_connect(0); /* trap into kgdb */ ! 366: #endif ! 367: return; ! 368: } ! 369: if (stat & (LSR_BI | LSR_FE)) ! 370: c |= TTY_FE; ! 371: else if (stat & LSR_PE) ! 372: c |= TTY_PE; ! 373: else if (stat & LSR_OE) ! 374: log(LOG_WARNING, "com%d: silo overflow\n", unit); ! 375: (*linesw[tp->t_line].l_rint)(c, tp); ! 376: } ! 377: ! 378: commint(unit, com) ! 379: register int unit; ! 380: register com; ! 381: { ! 382: register struct tty *tp; ! 383: register int stat; ! 384: ! 385: tp = &com_tty[unit]; ! 386: stat = inb(com+com_msr); ! 387: if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) { ! 388: if (stat & MSR_DCD) ! 389: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 390: else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) ! 391: outb(com+com_mcr, ! 392: inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE); ! 393: } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && ! 394: (tp->t_flags & CRTSCTS)) { ! 395: /* the line is up and we want to do rts/cts flow control */ ! 396: if (stat & MSR_CTS) { ! 397: tp->t_state &=~ TS_TTSTOP; ! 398: ttstart(tp); ! 399: } else ! 400: tp->t_state |= TS_TTSTOP; ! 401: } ! 402: } ! 403: ! 404: comioctl(dev, cmd, data, flag) ! 405: dev_t dev; ! 406: caddr_t data; ! 407: { ! 408: register struct tty *tp; ! 409: register int unit = UNIT(dev); ! 410: register com; ! 411: register int error; ! 412: ! 413: tp = &com_tty[unit]; ! 414: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 415: if (error >= 0) ! 416: return (error); ! 417: error = ttioctl(tp, cmd, data, flag); ! 418: if (error >= 0) ! 419: return (error); ! 420: ! 421: com = com_addr[unit]; ! 422: switch (cmd) { ! 423: ! 424: case TIOCSBRK: ! 425: outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_SBREAK); ! 426: break; ! 427: ! 428: case TIOCCBRK: ! 429: outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK); ! 430: break; ! 431: ! 432: case TIOCSDTR: ! 433: (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIS); ! 434: break; ! 435: ! 436: case TIOCCDTR: ! 437: (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIC); ! 438: break; ! 439: ! 440: case TIOCMSET: ! 441: (void) commctl(dev, *(int *)data, DMSET); ! 442: break; ! 443: ! 444: case TIOCMBIS: ! 445: (void) commctl(dev, *(int *)data, DMBIS); ! 446: break; ! 447: ! 448: case TIOCMBIC: ! 449: (void) commctl(dev, *(int *)data, DMBIC); ! 450: break; ! 451: ! 452: case TIOCMGET: ! 453: *(int *)data = commctl(dev, 0, DMGET); ! 454: break; ! 455: ! 456: default: ! 457: return (ENOTTY); ! 458: } ! 459: return (0); ! 460: } ! 461: ! 462: comparam(tp, t) ! 463: register struct tty *tp; ! 464: register struct termios *t; ! 465: { ! 466: register com; ! 467: register int cfcr, cflag = t->c_cflag; ! 468: int unit = UNIT(tp->t_dev); ! 469: int ospeed = ttspeedtab(t->c_ospeed, comspeedtab); ! 470: ! 471: /* check requested parameters */ ! 472: if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) ! 473: return(EINVAL); ! 474: /* and copy to tty */ ! 475: tp->t_ispeed = t->c_ispeed; ! 476: tp->t_ospeed = t->c_ospeed; ! 477: tp->t_cflag = cflag; ! 478: ! 479: com = com_addr[unit]; ! 480: outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/); ! 481: if (ospeed == 0) { ! 482: (void) commctl(unit, 0, DMSET); /* hang up line */ ! 483: return(0); ! 484: } ! 485: outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB); ! 486: outb(com+com_data, ospeed & 0xFF); ! 487: outb(com+com_ier, ospeed >> 8); ! 488: switch (cflag&CSIZE) { ! 489: case CS5: ! 490: cfcr = CFCR_5BITS; break; ! 491: case CS6: ! 492: cfcr = CFCR_6BITS; break; ! 493: case CS7: ! 494: cfcr = CFCR_7BITS; break; ! 495: case CS8: ! 496: cfcr = CFCR_8BITS; break; ! 497: } ! 498: if (cflag&PARENB) { ! 499: cfcr |= CFCR_PENAB; ! 500: if ((cflag&PARODD) == 0) ! 501: cfcr |= CFCR_PEVEN; ! 502: } ! 503: if (cflag&CSTOPB) ! 504: cfcr |= CFCR_STOPB; ! 505: outb(com+com_cfcr, cfcr); ! 506: ! 507: if (com_hasfifo & (1 << unit)) ! 508: outb(com+com_fifo, FIFO_ENABLE | FIFO_TRIGGER_14); ! 509: ! 510: return(0); ! 511: } ! 512: ! 513: comstart(tp) ! 514: register struct tty *tp; ! 515: { ! 516: register com; ! 517: int s, unit, c; ! 518: ! 519: unit = UNIT(tp->t_dev); ! 520: com = com_addr[unit]; ! 521: s = spltty(); ! 522: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) ! 523: goto out; ! 524: if (tp->t_outq.c_cc <= tp->t_lowat) { ! 525: if (tp->t_state&TS_ASLEEP) { ! 526: tp->t_state &= ~TS_ASLEEP; ! 527: wakeup((caddr_t)&tp->t_outq); ! 528: } ! 529: if (tp->t_wsel) { ! 530: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 531: tp->t_wsel = 0; ! 532: tp->t_state &= ~TS_WCOLL; ! 533: } ! 534: } ! 535: if (tp->t_outq.c_cc == 0) ! 536: goto out; ! 537: if (inb(com+com_lsr) & LSR_TXRDY) { ! 538: c = getc(&tp->t_outq); ! 539: tp->t_state |= TS_BUSY; ! 540: outb(com+com_data, c); ! 541: if (com_hasfifo & (1 << unit)) ! 542: for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) ! 543: outb(com+com_data, getc(&tp->t_outq)); ! 544: } ! 545: out: ! 546: splx(s); ! 547: } ! 548: ! 549: /* ! 550: * Stop output on a line. ! 551: */ ! 552: /*ARGSUSED*/ ! 553: comstop(tp, flag) ! 554: register struct tty *tp; ! 555: { ! 556: register int s; ! 557: ! 558: s = spltty(); ! 559: if (tp->t_state & TS_BUSY) { ! 560: if ((tp->t_state&TS_TTSTOP)==0) ! 561: tp->t_state |= TS_FLUSH; ! 562: } ! 563: splx(s); ! 564: } ! 565: ! 566: commctl(dev, bits, how) ! 567: dev_t dev; ! 568: int bits, how; ! 569: { ! 570: register com; ! 571: register int unit; ! 572: int s; ! 573: ! 574: unit = UNIT(dev); ! 575: com = com_addr[unit]; ! 576: s = spltty(); ! 577: switch (how) { ! 578: ! 579: case DMSET: ! 580: outb(com+com_mcr, bits | MCR_IENABLE); ! 581: break; ! 582: ! 583: case DMBIS: ! 584: outb(com+com_mcr, inb(com+com_mcr) | bits | MCR_IENABLE); ! 585: break; ! 586: ! 587: case DMBIC: ! 588: outb(com+com_mcr, inb(com+com_mcr) & ~bits | MCR_IENABLE); ! 589: break; ! 590: ! 591: case DMGET: ! 592: bits = inb(com+com_msr); ! 593: break; ! 594: } ! 595: (void) splx(s); ! 596: return(bits); ! 597: } ! 598: ! 599: /* ! 600: * Following are all routines needed for COM to act as console ! 601: */ ! 602: #include "i386/i386/cons.h" ! 603: ! 604: comcnprobe(cp) ! 605: struct consdev *cp; ! 606: { ! 607: int unit; ! 608: ! 609: /* locate the major number */ ! 610: for (commajor = 0; commajor < nchrdev; commajor++) ! 611: if (cdevsw[commajor].d_open == comopen) ! 612: break; ! 613: ! 614: /* XXX: ick */ ! 615: unit = CONUNIT; ! 616: com_addr[CONUNIT] = CONADDR; ! 617: ! 618: /* make sure hardware exists? XXX */ ! 619: ! 620: /* initialize required fields */ ! 621: cp->cn_dev = makedev(commajor, unit); ! 622: cp->cn_tp = &com_tty[unit]; ! 623: #ifdef COMCONSOLE ! 624: cp->cn_pri = CN_REMOTE; /* Force a serial port console */ ! 625: #else ! 626: cp->cn_pri = CN_NORMAL; ! 627: #endif ! 628: } ! 629: ! 630: comcninit(cp) ! 631: struct consdev *cp; ! 632: { ! 633: int unit = UNIT(cp->cn_dev); ! 634: ! 635: cominit(unit, comdefaultrate); ! 636: comconsole = unit; ! 637: comconsinit = 1; ! 638: } ! 639: ! 640: cominit(unit, rate) ! 641: int unit, rate; ! 642: { ! 643: register int com; ! 644: int s; ! 645: short stat; ! 646: ! 647: #ifdef lint ! 648: stat = unit; if (stat) return; ! 649: #endif ! 650: com = com_addr[unit]; ! 651: s = splhigh(); ! 652: outb(com+com_cfcr, CFCR_DLAB); ! 653: rate = ttspeedtab(comdefaultrate, comspeedtab); ! 654: outb(com+com_data, rate & 0xFF); ! 655: outb(com+com_ier, rate >> 8); ! 656: outb(com+com_cfcr, CFCR_8BITS); ! 657: outb(com+com_ier, IER_ERXRDY | IER_ETXRDY); ! 658: outb(com+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14); ! 659: stat = inb(com+com_iir); ! 660: splx(s); ! 661: } ! 662: ! 663: comcngetc(dev) ! 664: { ! 665: register com = com_addr[UNIT(dev)]; ! 666: short stat; ! 667: int c, s; ! 668: ! 669: #ifdef lint ! 670: stat = dev; if (stat) return(0); ! 671: #endif ! 672: s = splhigh(); ! 673: while (((stat = inb(com+com_lsr)) & LSR_RXRDY) == 0) ! 674: ; ! 675: c = inb(com+com_data); ! 676: stat = inb(com+com_iir); ! 677: splx(s); ! 678: return(c); ! 679: } ! 680: ! 681: /* ! 682: * Console kernel output character routine. ! 683: */ ! 684: comcnputc(dev, c) ! 685: dev_t dev; ! 686: register int c; ! 687: { ! 688: register com = com_addr[UNIT(dev)]; ! 689: register int timo; ! 690: short stat; ! 691: int s = splhigh(); ! 692: ! 693: #ifdef lint ! 694: stat = dev; if (stat) return; ! 695: #endif ! 696: #ifdef KGDB ! 697: if (dev != kgdb_dev) ! 698: #endif ! 699: if (comconsinit == 0) { ! 700: (void) cominit(UNIT(dev), comdefaultrate); ! 701: comconsinit = 1; ! 702: } ! 703: /* wait for any pending transmission to finish */ ! 704: timo = 50000; ! 705: while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo) ! 706: ; ! 707: outb(com+com_data, c); ! 708: /* wait for this transmission to complete */ ! 709: timo = 1500000; ! 710: while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo) ! 711: ; ! 712: /* clear any interrupts generated by this transmission */ ! 713: stat = inb(com+com_iir); ! 714: splx(s); ! 715: } ! 716: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.