1 /* $NetBSD: com.c,v 1.86 1996/09/05 16:42:32 mycroft Exp $ */ 2 3 /*- 4 * Copyright (c) 1993, 1994, 1995, 1996 5 * Charles M. Hannum. All rights reserved. 6 * Copyright (c) 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)com.c 7.5 (Berkeley) 5/16/91 38 */ 39 40 /* 41 * COM driver, based on HP dca driver 42 * uses National Semiconductor NS16450/NS16550AF UART 43 */ 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/ioctl.h> 47 #include <sys/select.h> 48 #include <sys/tty.h> 49 #include <sys/proc.h> 50 #include <sys/user.h> 51 #include <sys/conf.h> 52 #include <sys/file.h> 53 #include <sys/uio.h> 54 #include <sys/kernel.h> 55 #include <sys/syslog.h> 56 #include <sys/types.h> 57 #include <sys/device.h> 58 59 #include <machine/bus.h> 60 #include <machine/intr.h> 61 62 #include <dev/isa/isavar.h> 63 #include <dev/isa/comreg.h> 64 #include <dev/isa/comvar.h> 65 #include <dev/ic/ns16550reg.h> 66 #ifdef COM_HAYESP 67 #include <dev/ic/hayespreg.h> 68 #endif 69 #define com_lcr com_cfcr 70 71 #include "com.h" 72 73 74 #define COM_IBUFSIZE (2 * 512) 75 #define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4) 76 77 struct com_softc { 78 struct device sc_dev; 79 void *sc_ih; 80 struct tty *sc_tty; 81 82 int sc_overflows; 83 int sc_floods; 84 int sc_errors; 85 86 int sc_halt; 87 88 int sc_iobase; 89 #ifdef COM_HAYESP 90 int sc_hayespbase; 91 #endif 92 93 bus_chipset_tag_t sc_bc; 94 bus_io_handle_t sc_ioh; 95 bus_io_handle_t sc_hayespioh; 96 97 u_char sc_hwflags; 98 #define COM_HW_NOIEN 0x01 99 #define COM_HW_FIFO 0x02 100 #define COM_HW_HAYESP 0x04 101 #define COM_HW_CONSOLE 0x40 102 u_char sc_swflags; 103 #define COM_SW_SOFTCAR 0x01 104 #define COM_SW_CLOCAL 0x02 105 #define COM_SW_CRTSCTS 0x04 106 #define COM_SW_MDMBUF 0x08 107 u_char sc_msr, sc_mcr, sc_lcr, sc_ier; 108 u_char sc_dtr; 109 110 u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend; 111 u_char sc_ibufs[2][COM_IBUFSIZE]; 112 }; 113 114 #ifdef COM_HAYESP 115 int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc)); 116 #endif 117 void comdiag __P((void *)); 118 int comspeed __P((long)); 119 int comparam __P((struct tty *, struct termios *)); 120 void comstart __P((struct tty *)); 121 void comsoft __P((void *)); 122 123 /* XXX: These belong elsewhere */ 124 cdev_decl(com); 125 bdev_decl(com); 126 127 struct consdev; 128 void comcnprobe __P((struct consdev *)); 129 void comcninit __P((struct consdev *)); 130 int comcngetc __P((dev_t)); 131 void comcnputc __P((dev_t, int)); 132 void comcnpollc __P((dev_t, int)); 133 134 static u_char tiocm_xxx2mcr __P((int)); 135 136 /* 137 * XXX the following two cfattach structs should be different, and possibly 138 * XXX elsewhere. 139 */ 140 int comprobe __P((struct device *, void *, void *)); 141 void comattach __P((struct device *, struct device *, void *)); 142 143 #if NCOM_ISA 144 struct cfattach com_isa_ca = { 145 sizeof(struct com_softc), comprobe, comattach 146 }; 147 #endif 148 149 #if NCOM_COMMULTI 150 struct cfattach com_commulti_ca = { 151 sizeof(struct com_softc), comprobe, comattach 152 }; 153 #endif 154 155 struct cfdriver com_cd = { 156 NULL, "com", DV_TTY 157 }; 158 159 void cominit __P((bus_chipset_tag_t, bus_io_handle_t, int)); 160 161 #ifdef COMCONSOLE 162 int comdefaultrate = CONSPEED; /* XXX why set default? */ 163 #else 164 int comdefaultrate = TTYDEF_SPEED; 165 #endif 166 int comconsaddr; 167 int comconsinit; 168 int comconsattached; 169 bus_chipset_tag_t comconsbc; 170 bus_io_handle_t comconsioh; 171 tcflag_t comconscflag = TTYDEF_CFLAG; 172 173 int commajor; 174 int comsopen = 0; 175 int comevents = 0; 176 177 #ifdef KGDB 178 #include <machine/remote-sl.h> 179 extern int kgdb_dev; 180 extern int kgdb_rate; 181 extern int kgdb_debug_init; 182 #endif 183 184 #define COMUNIT(x) (minor(x)) 185 186 /* Macros to clear/set/test flags. */ 187 #define SET(t, f) (t) |= (f) 188 #define CLR(t, f) (t) &= ~(f) 189 #define ISSET(t, f) ((t) & (f)) 190 191 int 192 comspeed(speed) 193 long speed; 194 { 195 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 196 197 int x, err; 198 199 if (speed == 0) 200 return 0; 201 if (speed < 0) 202 return -1; 203 x = divrnd((COM_FREQ / 16), speed); 204 if (x <= 0) 205 return -1; 206 err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000; 207 if (err < 0) 208 err = -err; 209 if (err > COM_TOLERANCE) 210 return -1; 211 return x; 212 213 #undef divrnd(n, q) 214 } 215 216 int 217 comprobe1(bc, ioh, iobase) 218 bus_chipset_tag_t bc; 219 bus_io_handle_t ioh; 220 int iobase; 221 { 222 223 /* force access to id reg */ 224 bus_io_write_1(bc, ioh, com_lcr, 0); 225 bus_io_write_1(bc, ioh, com_iir, 0); 226 if (bus_io_read_1(bc, ioh, com_iir) & 0x38) 227 return 0; 228 229 return 1; 230 } 231 232 #ifdef COM_HAYESP 233 int 234 comprobeHAYESP(hayespioh, sc) 235 bus_io_handle_t hayespioh; 236 struct com_softc *sc; 237 { 238 char val, dips; 239 int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; 240 bus_chipset_tag_t bc = sc->sc_bc; 241 242 /* 243 * Hayes ESP cards have two iobases. One is for compatibility with 244 * 16550 serial chips, and at the same ISA PC base addresses. The 245 * other is for ESP-specific enhanced features, and lies at a 246 * different addressing range entirely (0x140, 0x180, 0x280, or 0x300). 247 */ 248 249 /* Test for ESP signature */ 250 if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0) 251 return 0; 252 253 /* 254 * ESP is present at ESP enhanced base address; unknown com port 255 */ 256 257 /* Get the dip-switch configurations */ 258 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS); 259 dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); 260 261 /* Determine which com port this ESP card services: bits 0,1 of */ 262 /* dips is the port # (0-3); combaselist[val] is the com_iobase */ 263 if (sc->sc_iobase != combaselist[dips & 0x03]) 264 return 0; 265 266 printf(": ESP"); 267 268 /* Check ESP Self Test bits. */ 269 /* Check for ESP version 2.0: bits 4,5,6 == 010 */ 270 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST); 271 val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */ 272 val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2); 273 if ((val & 0x70) < 0x20) { 274 printf("-old (%o)", val & 0x70); 275 /* we do not support the necessary features */ 276 return 0; 277 } 278 279 /* Check for ability to emulate 16550: bit 8 == 1 */ 280 if ((dips & 0x80) == 0) { 281 printf(" slave"); 282 /* XXX Does slave really mean no 16550 support?? */ 283 return 0; 284 } 285 286 /* 287 * If we made it this far, we are a full-featured ESP v2.0 (or 288 * better), at the correct com port address. 289 */ 290 291 SET(sc->sc_hwflags, COM_HW_HAYESP); 292 printf(", 1024 byte fifo\n"); 293 return 1; 294 } 295 #endif 296 297 int 298 comprobe(parent, match, aux) 299 struct device *parent; 300 void *match, *aux; 301 { 302 bus_chipset_tag_t bc; 303 bus_io_handle_t ioh; 304 int iobase, needioh; 305 int rv = 1; 306 307 /* 308 * XXX should be broken out into functions for isa probe and 309 * XXX for commulti probe, with a helper function that contains 310 * XXX most of the interesting stuff. 311 */ 312 #if NCOM_ISA 313 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) { 314 struct isa_attach_args *ia = aux; 315 316 bc = ia->ia_bc; 317 iobase = ia->ia_iobase; 318 needioh = 1; 319 } else 320 #endif 321 #if NCOM_COMMULTI 322 if (1) { 323 struct cfdata *cf = match; 324 struct commulti_attach_args *ca = aux; 325 326 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave) 327 return (0); 328 329 bc = ca->ca_bc; 330 iobase = ca->ca_iobase; 331 ioh = ca->ca_ioh; 332 needioh = 0; 333 } else 334 #endif 335 return(0); /* This cannot happen */ 336 337 /* if it's in use as console, it's there. */ 338 if (iobase == comconsaddr && !comconsattached) 339 goto out; 340 341 if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) { 342 rv = 0; 343 goto out; 344 } 345 rv = comprobe1(bc, ioh, iobase); 346 if (needioh) 347 bus_io_unmap(bc, ioh, COM_NPORTS); 348 349 out: 350 #if NCOM_ISA 351 if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) { 352 struct isa_attach_args *ia = aux; 353 354 ia->ia_iosize = COM_NPORTS; 355 ia->ia_msize = 0; 356 } 357 #endif 358 return (rv); 359 } 360 361 void 362 comattach(parent, self, aux) 363 struct device *parent, *self; 364 void *aux; 365 { 366 struct com_softc *sc = (void *)self; 367 int iobase, irq; 368 bus_chipset_tag_t bc; 369 bus_io_handle_t ioh; 370 #ifdef COM_HAYESP 371 int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 }; 372 int *hayespp; 373 #endif 374 375 /* 376 * XXX should be broken out into functions for isa attach and 377 * XXX for commulti attach, with a helper function that contains 378 * XXX most of the interesting stuff. 379 */ 380 sc->sc_hwflags = 0; 381 sc->sc_swflags = 0; 382 #if NCOM_ISA 383 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) { 384 struct isa_attach_args *ia = aux; 385 386 /* 387 * We're living on an isa. 388 */ 389 iobase = ia->ia_iobase; 390 bc = ia->ia_bc; 391 if (iobase != comconsaddr) { 392 if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) 393 panic("comattach: io mapping failed"); 394 } else 395 ioh = comconsioh; 396 irq = ia->ia_irq; 397 } else 398 #endif 399 #if NCOM_COMMULTI 400 if (1) { 401 struct commulti_attach_args *ca = aux; 402 403 /* 404 * We're living on a commulti. 405 */ 406 iobase = ca->ca_iobase; 407 bc = ca->ca_bc; 408 ioh = ca->ca_ioh; 409 irq = IRQUNK; 410 411 if (ca->ca_noien) 412 sc->sc_hwflags |= COM_HW_NOIEN; 413 } else 414 #endif 415 panic("comattach: impossible"); 416 417 sc->sc_bc = bc; 418 sc->sc_ioh = ioh; 419 sc->sc_iobase = iobase; 420 421 if (iobase == comconsaddr) { 422 comconsattached = 1; 423 424 /* 425 * Need to reset baud rate, etc. of next print so reset 426 * comconsinit. Also make sure console is always "hardwired". 427 */ 428 delay(1000); /* wait for output to finish */ 429 comconsinit = 0; 430 SET(sc->sc_hwflags, COM_HW_CONSOLE); 431 SET(sc->sc_swflags, COM_SW_SOFTCAR); 432 } 433 434 #ifdef COM_HAYESP 435 /* Look for a Hayes ESP board. */ 436 for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) { 437 bus_io_handle_t hayespioh; 438 439 #define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */ 440 if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh)) 441 continue; 442 if (comprobeHAYESP(hayespioh, sc)) { 443 sc->sc_hayespbase = *hayespp; 444 sc->sc_hayespioh = hayespioh; 445 break; 446 } 447 bus_io_unmap(bc, hayespioh, HAYESP_NPORTS); 448 } 449 /* No ESP; look for other things. */ 450 if (*hayespp == 0) { 451 #endif 452 453 /* look for a NS 16550AF UART with FIFOs */ 454 bus_io_write_1(bc, ioh, com_fifo, 455 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); 456 delay(100); 457 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK) 458 if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) { 459 SET(sc->sc_hwflags, COM_HW_FIFO); 460 printf(": ns16550a, working fifo\n"); 461 } else 462 printf(": ns16550, broken fifo\n"); 463 else 464 printf(": ns8250 or ns16450, no fifo\n"); 465 bus_io_write_1(bc, ioh, com_fifo, 0); 466 #ifdef COM_HAYESP 467 } 468 #endif 469 470 /* disable interrupts */ 471 bus_io_write_1(bc, ioh, com_ier, 0); 472 bus_io_write_1(bc, ioh, com_mcr, 0); 473 474 if (irq != IRQUNK) { 475 #if NCOM_ISA 476 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) { 477 struct isa_attach_args *ia = aux; 478 479 sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, 480 IST_EDGE, IPL_TTY, comintr, sc); 481 } else 482 #endif 483 panic("comattach: IRQ but can't have one"); 484 } 485 486 #ifdef KGDB 487 if (kgdb_dev == makedev(commajor, unit)) { 488 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 489 kgdb_dev = -1; /* can't debug over console port */ 490 else { 491 cominit(bc, ioh, kgdb_rate); 492 if (kgdb_debug_init) { 493 /* 494 * Print prefix of device name, 495 * let kgdb_connect print the rest. 496 */ 497 printf("%s: ", sc->sc_dev.dv_xname); 498 kgdb_connect(1); 499 } else 500 printf("%s: kgdb enabled\n", 501 sc->sc_dev.dv_xname); 502 } 503 } 504 #endif 505 506 /* XXX maybe move up some? */ 507 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 508 printf("%s: console\n", sc->sc_dev.dv_xname); 509 } 510 511 int 512 comopen(dev, flag, mode, p) 513 dev_t dev; 514 int flag, mode; 515 struct proc *p; 516 { 517 int unit = COMUNIT(dev); 518 struct com_softc *sc; 519 bus_chipset_tag_t bc; 520 bus_io_handle_t ioh; 521 struct tty *tp; 522 int s; 523 int error = 0; 524 525 if (unit >= com_cd.cd_ndevs) 526 return ENXIO; 527 sc = com_cd.cd_devs[unit]; 528 if (!sc) 529 return ENXIO; 530 531 if (!sc->sc_tty) { 532 tp = sc->sc_tty = ttymalloc(); 533 tty_attach(tp); 534 } else 535 tp = sc->sc_tty; 536 537 tp->t_oproc = comstart; 538 tp->t_param = comparam; 539 tp->t_dev = dev; 540 if (!ISSET(tp->t_state, TS_ISOPEN)) { 541 SET(tp->t_state, TS_WOPEN); 542 ttychars(tp); 543 tp->t_iflag = TTYDEF_IFLAG; 544 tp->t_oflag = TTYDEF_OFLAG; 545 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 546 tp->t_cflag = comconscflag; 547 else 548 tp->t_cflag = TTYDEF_CFLAG; 549 if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) 550 SET(tp->t_cflag, CLOCAL); 551 if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) 552 SET(tp->t_cflag, CRTSCTS); 553 if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) 554 SET(tp->t_cflag, MDMBUF); 555 tp->t_lflag = TTYDEF_LFLAG; 556 tp->t_ispeed = tp->t_ospeed = comdefaultrate; 557 558 s = spltty(); 559 560 comparam(tp, &tp->t_termios); 561 ttsetwater(tp); 562 563 if (comsopen++ == 0) 564 timeout(comsoft, NULL, 1); 565 566 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; 567 sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; 568 sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; 569 570 bc = sc->sc_bc; 571 ioh = sc->sc_ioh; 572 #ifdef COM_HAYESP 573 /* Setup the ESP board */ 574 if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { 575 bus_io_handle_t hayespioh = sc->sc_hayespioh; 576 577 bus_io_write_1(bc, ioh, com_fifo, 578 FIFO_DMA_MODE|FIFO_ENABLE| 579 FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8); 580 581 /* Set 16550 compatibility mode */ 582 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE); 583 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 584 HAYESP_MODE_FIFO|HAYESP_MODE_RTS| 585 HAYESP_MODE_SCALE); 586 587 /* Set RTS/CTS flow control */ 588 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE); 589 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS); 590 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS); 591 592 /* Set flow control levels */ 593 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW); 594 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 595 HAYESP_HIBYTE(HAYESP_RXHIWMARK)); 596 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 597 HAYESP_LOBYTE(HAYESP_RXHIWMARK)); 598 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 599 HAYESP_HIBYTE(HAYESP_RXLOWMARK)); 600 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, 601 HAYESP_LOBYTE(HAYESP_RXLOWMARK)); 602 } else 603 #endif 604 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) 605 /* Set the FIFO threshold based on the receive speed. */ 606 bus_io_write_1(bc, ioh, com_fifo, 607 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | 608 (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); 609 /* flush any pending I/O */ 610 while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY)) 611 (void) bus_io_read_1(bc, ioh, com_data); 612 /* you turn me on, baby */ 613 sc->sc_mcr = MCR_DTR | MCR_RTS; 614 if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) 615 SET(sc->sc_mcr, MCR_IENABLE); 616 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 617 sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; 618 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); 619 620 sc->sc_msr = bus_io_read_1(bc, ioh, com_msr); 621 if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || 622 ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) 623 SET(tp->t_state, TS_CARR_ON); 624 else 625 CLR(tp->t_state, TS_CARR_ON); 626 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) 627 return EBUSY; 628 else 629 s = spltty(); 630 631 /* wait for carrier if necessary */ 632 if (!ISSET(flag, O_NONBLOCK)) 633 while (!ISSET(tp->t_cflag, CLOCAL) && 634 !ISSET(tp->t_state, TS_CARR_ON)) { 635 SET(tp->t_state, TS_WOPEN); 636 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 637 ttopen, 0); 638 if (error) { 639 /* XXX should turn off chip if we're the 640 only waiter */ 641 splx(s); 642 return error; 643 } 644 } 645 splx(s); 646 647 return (*linesw[tp->t_line].l_open)(dev, tp); 648 } 649 650 int 651 comclose(dev, flag, mode, p) 652 dev_t dev; 653 int flag, mode; 654 struct proc *p; 655 { 656 int unit = COMUNIT(dev); 657 struct com_softc *sc = com_cd.cd_devs[unit]; 658 struct tty *tp = sc->sc_tty; 659 bus_chipset_tag_t bc = sc->sc_bc; 660 bus_io_handle_t ioh = sc->sc_ioh; 661 int s; 662 663 /* XXX This is for cons.c. */ 664 if (!ISSET(tp->t_state, TS_ISOPEN)) 665 return 0; 666 667 (*linesw[tp->t_line].l_close)(tp, flag); 668 s = spltty(); 669 CLR(sc->sc_lcr, LCR_SBREAK); 670 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); 671 bus_io_write_1(bc, ioh, com_ier, 0); 672 if (ISSET(tp->t_cflag, HUPCL) && 673 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { 674 /* XXX perhaps only clear DTR */ 675 bus_io_write_1(bc, ioh, com_mcr, 0); 676 } 677 CLR(tp->t_state, TS_BUSY | TS_FLUSH); 678 if (--comsopen == 0) 679 untimeout(comsoft, NULL); 680 splx(s); 681 ttyclose(tp); 682 #ifdef notyet /* XXXX */ 683 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 684 ttyfree(tp); 685 sc->sc_tty = 0; 686 } 687 #endif 688 return 0; 689 } 690 691 int 692 comread(dev, uio, flag) 693 dev_t dev; 694 struct uio *uio; 695 int flag; 696 { 697 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; 698 struct tty *tp = sc->sc_tty; 699 700 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 701 } 702 703 int 704 comwrite(dev, uio, flag) 705 dev_t dev; 706 struct uio *uio; 707 int flag; 708 { 709 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; 710 struct tty *tp = sc->sc_tty; 711 712 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 713 } 714 715 struct tty * 716 comtty(dev) 717 dev_t dev; 718 { 719 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; 720 struct tty *tp = sc->sc_tty; 721 722 return (tp); 723 } 724 725 static u_char 726 tiocm_xxx2mcr(data) 727 int data; 728 { 729 u_char m = 0; 730 731 if (ISSET(data, TIOCM_DTR)) 732 SET(m, MCR_DTR); 733 if (ISSET(data, TIOCM_RTS)) 734 SET(m, MCR_RTS); 735 return m; 736 } 737 738 int 739 comioctl(dev, cmd, data, flag, p) 740 dev_t dev; 741 u_long cmd; 742 caddr_t data; 743 int flag; 744 struct proc *p; 745 { 746 int unit = COMUNIT(dev); 747 struct com_softc *sc = com_cd.cd_devs[unit]; 748 struct tty *tp = sc->sc_tty; 749 bus_chipset_tag_t bc = sc->sc_bc; 750 bus_io_handle_t ioh = sc->sc_ioh; 751 int error; 752 753 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 754 if (error >= 0) 755 return error; 756 error = ttioctl(tp, cmd, data, flag, p); 757 if (error >= 0) 758 return error; 759 760 switch (cmd) { 761 case TIOCSBRK: 762 SET(sc->sc_lcr, LCR_SBREAK); 763 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); 764 break; 765 case TIOCCBRK: 766 CLR(sc->sc_lcr, LCR_SBREAK); 767 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); 768 break; 769 case TIOCSDTR: 770 SET(sc->sc_mcr, sc->sc_dtr); 771 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 772 break; 773 case TIOCCDTR: 774 CLR(sc->sc_mcr, sc->sc_dtr); 775 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 776 break; 777 case TIOCMSET: 778 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); 779 case TIOCMBIS: 780 SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); 781 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 782 break; 783 case TIOCMBIC: 784 CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); 785 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 786 break; 787 case TIOCMGET: { 788 u_char m; 789 int bits = 0; 790 791 m = sc->sc_mcr; 792 if (ISSET(m, MCR_DTR)) 793 SET(bits, TIOCM_DTR); 794 if (ISSET(m, MCR_RTS)) 795 SET(bits, TIOCM_RTS); 796 m = sc->sc_msr; 797 if (ISSET(m, MSR_DCD)) 798 SET(bits, TIOCM_CD); 799 if (ISSET(m, MSR_CTS)) 800 SET(bits, TIOCM_CTS); 801 if (ISSET(m, MSR_DSR)) 802 SET(bits, TIOCM_DSR); 803 if (ISSET(m, MSR_RI | MSR_TERI)) 804 SET(bits, TIOCM_RI); 805 if (bus_io_read_1(bc, ioh, com_ier)) 806 SET(bits, TIOCM_LE); 807 *(int *)data = bits; 808 break; 809 } 810 case TIOCGFLAGS: { 811 int driverbits, userbits = 0; 812 813 driverbits = sc->sc_swflags; 814 if (ISSET(driverbits, COM_SW_SOFTCAR)) 815 SET(userbits, TIOCFLAG_SOFTCAR); 816 if (ISSET(driverbits, COM_SW_CLOCAL)) 817 SET(userbits, TIOCFLAG_CLOCAL); 818 if (ISSET(driverbits, COM_SW_CRTSCTS)) 819 SET(userbits, TIOCFLAG_CRTSCTS); 820 if (ISSET(driverbits, COM_SW_MDMBUF)) 821 SET(userbits, TIOCFLAG_MDMBUF); 822 823 *(int *)data = userbits; 824 break; 825 } 826 case TIOCSFLAGS: { 827 int userbits, driverbits = 0; 828 829 error = suser(p->p_ucred, &p->p_acflag); 830 if (error != 0) 831 return(EPERM); 832 833 userbits = *(int *)data; 834 if (ISSET(userbits, TIOCFLAG_SOFTCAR) || 835 ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) 836 SET(driverbits, COM_SW_SOFTCAR); 837 if (ISSET(userbits, TIOCFLAG_CLOCAL)) 838 SET(driverbits, COM_SW_CLOCAL); 839 if (ISSET(userbits, TIOCFLAG_CRTSCTS)) 840 SET(driverbits, COM_SW_CRTSCTS); 841 if (ISSET(userbits, TIOCFLAG_MDMBUF)) 842 SET(driverbits, COM_SW_MDMBUF); 843 844 sc->sc_swflags = driverbits; 845 break; 846 } 847 default: 848 return ENOTTY; 849 } 850 851 return 0; 852 } 853 854 int 855 comparam(tp, t) 856 struct tty *tp; 857 struct termios *t; 858 { 859 struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)]; 860 bus_chipset_tag_t bc = sc->sc_bc; 861 bus_io_handle_t ioh = sc->sc_ioh; 862 int ospeed = comspeed(t->c_ospeed); 863 u_char lcr; 864 tcflag_t oldcflag; 865 int s; 866 867 /* check requested parameters */ 868 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 869 return EINVAL; 870 871 lcr = ISSET(sc->sc_lcr, LCR_SBREAK); 872 873 switch (ISSET(t->c_cflag, CSIZE)) { 874 case CS5: 875 SET(lcr, LCR_5BITS); 876 break; 877 case CS6: 878 SET(lcr, LCR_6BITS); 879 break; 880 case CS7: 881 SET(lcr, LCR_7BITS); 882 break; 883 case CS8: 884 SET(lcr, LCR_8BITS); 885 break; 886 } 887 if (ISSET(t->c_cflag, PARENB)) { 888 SET(lcr, LCR_PENAB); 889 if (!ISSET(t->c_cflag, PARODD)) 890 SET(lcr, LCR_PEVEN); 891 } 892 if (ISSET(t->c_cflag, CSTOPB)) 893 SET(lcr, LCR_STOPB); 894 895 sc->sc_lcr = lcr; 896 897 s = spltty(); 898 899 if (ospeed == 0) { 900 CLR(sc->sc_mcr, MCR_DTR); 901 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 902 } 903 904 /* 905 * Set the FIFO threshold based on the receive speed, if we are 906 * changing it. 907 */ 908 #if 1 909 if (tp->t_ispeed != t->c_ispeed) { 910 #else 911 if (1) { 912 #endif 913 if (ospeed != 0) { 914 /* 915 * Make sure the transmit FIFO is empty before 916 * proceeding. If we don't do this, some revisions 917 * of the UART will hang. Interestingly enough, 918 * even if we do this will the last character is 919 * still being pushed out, they don't hang. This 920 * seems good enough. 921 */ 922 while (ISSET(tp->t_state, TS_BUSY)) { 923 int error; 924 925 ++sc->sc_halt; 926 error = ttysleep(tp, &tp->t_outq, 927 TTOPRI | PCATCH, "comprm", 0); 928 --sc->sc_halt; 929 if (error) { 930 splx(s); 931 comstart(tp); 932 return (error); 933 } 934 } 935 936 bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB); 937 bus_io_write_1(bc, ioh, com_dlbl, ospeed); 938 bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8); 939 bus_io_write_1(bc, ioh, com_lcr, lcr); 940 SET(sc->sc_mcr, MCR_DTR); 941 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 942 } else 943 bus_io_write_1(bc, ioh, com_lcr, lcr); 944 945 if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) && 946 ISSET(sc->sc_hwflags, COM_HW_FIFO)) 947 bus_io_write_1(bc, ioh, com_fifo, 948 FIFO_ENABLE | 949 (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); 950 } else 951 bus_io_write_1(bc, ioh, com_lcr, lcr); 952 953 /* When not using CRTSCTS, RTS follows DTR. */ 954 if (!ISSET(t->c_cflag, CRTSCTS)) { 955 if (ISSET(sc->sc_mcr, MCR_DTR)) { 956 if (!ISSET(sc->sc_mcr, MCR_RTS)) { 957 SET(sc->sc_mcr, MCR_RTS); 958 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 959 } 960 } else { 961 if (ISSET(sc->sc_mcr, MCR_RTS)) { 962 CLR(sc->sc_mcr, MCR_RTS); 963 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 964 } 965 } 966 sc->sc_dtr = MCR_DTR | MCR_RTS; 967 } else 968 sc->sc_dtr = MCR_DTR; 969 970 /* and copy to tty */ 971 tp->t_ispeed = t->c_ispeed; 972 tp->t_ospeed = t->c_ospeed; 973 oldcflag = tp->t_cflag; 974 tp->t_cflag = t->c_cflag; 975 976 /* 977 * If DCD is off and MDMBUF is changed, ask the tty layer if we should 978 * stop the device. 979 */ 980 if (!ISSET(sc->sc_msr, MSR_DCD) && 981 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && 982 ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) && 983 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 984 CLR(sc->sc_mcr, sc->sc_dtr); 985 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 986 } 987 988 /* Just to be sure... */ 989 splx(s); 990 comstart(tp); 991 return 0; 992 } 993 994 void 995 comstart(tp) 996 struct tty *tp; 997 { 998 struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)]; 999 bus_chipset_tag_t bc = sc->sc_bc; 1000 bus_io_handle_t ioh = sc->sc_ioh; 1001 int s; 1002 1003 s = spltty(); 1004 if (ISSET(tp->t_state, TS_BUSY)) 1005 goto out; 1006 if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || 1007 sc->sc_halt > 0) 1008 goto stopped; 1009 if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS)) 1010 goto stopped; 1011 if (tp->t_outq.c_cc <= tp->t_lowat) { 1012 if (ISSET(tp->t_state, TS_ASLEEP)) { 1013 CLR(tp->t_state, TS_ASLEEP); 1014 wakeup(&tp->t_outq); 1015 } 1016 if (tp->t_outq.c_cc == 0) 1017 goto stopped; 1018 selwakeup(&tp->t_wsel); 1019 } 1020 SET(tp->t_state, TS_BUSY); 1021 1022 if (!ISSET(sc->sc_ier, IER_ETXRDY)) { 1023 SET(sc->sc_ier, IER_ETXRDY); 1024 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); 1025 } 1026 #ifdef COM_HAYESP 1027 if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { 1028 u_char buffer[1024], *cp = buffer; 1029 int n = q_to_b(&tp->t_outq, cp, sizeof buffer); 1030 do 1031 bus_io_write_1(bc, ioh, com_data, *cp++); 1032 while (--n); 1033 } 1034 else 1035 #endif 1036 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { 1037 u_char buffer[16], *cp = buffer; 1038 int n = q_to_b(&tp->t_outq, cp, sizeof buffer); 1039 do { 1040 bus_io_write_1(bc, ioh, com_data, *cp++); 1041 } while (--n); 1042 } else 1043 bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq)); 1044 out: 1045 splx(s); 1046 return; 1047 stopped: 1048 if (ISSET(sc->sc_ier, IER_ETXRDY)) { 1049 CLR(sc->sc_ier, IER_ETXRDY); 1050 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); 1051 } 1052 splx(s); 1053 } 1054 1055 /* 1056 * Stop output on a line. 1057 */ 1058 void 1059 comstop(tp, flag) 1060 struct tty *tp; 1061 int flag; 1062 { 1063 int s; 1064 1065 s = spltty(); 1066 if (ISSET(tp->t_state, TS_BUSY)) 1067 if (!ISSET(tp->t_state, TS_TTSTOP)) 1068 SET(tp->t_state, TS_FLUSH); 1069 splx(s); 1070 } 1071 1072 void 1073 comdiag(arg) 1074 void *arg; 1075 { 1076 struct com_softc *sc = arg; 1077 int overflows, floods; 1078 int s; 1079 1080 s = spltty(); 1081 sc->sc_errors = 0; 1082 overflows = sc->sc_overflows; 1083 sc->sc_overflows = 0; 1084 floods = sc->sc_floods; 1085 sc->sc_floods = 0; 1086 splx(s); 1087 1088 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", 1089 sc->sc_dev.dv_xname, 1090 overflows, overflows == 1 ? "" : "s", 1091 floods, floods == 1 ? "" : "s"); 1092 } 1093 1094 void 1095 comsoft(arg) 1096 void *arg; 1097 { 1098 int unit; 1099 struct com_softc *sc; 1100 struct tty *tp; 1101 register u_char *ibufp; 1102 u_char *ibufend; 1103 register int c; 1104 int s; 1105 static int lsrmap[8] = { 1106 0, TTY_PE, 1107 TTY_FE, TTY_PE|TTY_FE, 1108 TTY_FE, TTY_PE|TTY_FE, 1109 TTY_FE, TTY_PE|TTY_FE 1110 }; 1111 1112 s = spltty(); 1113 if (comevents == 0) { 1114 splx(s); 1115 goto out; 1116 } 1117 comevents = 0; 1118 splx(s); 1119 1120 for (unit = 0; unit < com_cd.cd_ndevs; unit++) { 1121 sc = com_cd.cd_devs[unit]; 1122 if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf) 1123 continue; 1124 1125 tp = sc->sc_tty; 1126 1127 s = spltty(); 1128 1129 ibufp = sc->sc_ibuf; 1130 ibufend = sc->sc_ibufp; 1131 1132 if (ibufp == ibufend) { 1133 splx(s); 1134 continue; 1135 } 1136 1137 sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? 1138 sc->sc_ibufs[1] : sc->sc_ibufs[0]; 1139 sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; 1140 sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; 1141 1142 if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) { 1143 splx(s); 1144 continue; 1145 } 1146 1147 if (ISSET(tp->t_cflag, CRTSCTS) && 1148 !ISSET(sc->sc_mcr, MCR_RTS)) { 1149 /* XXX */ 1150 SET(sc->sc_mcr, MCR_RTS); 1151 bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr, 1152 sc->sc_mcr); 1153 } 1154 1155 splx(s); 1156 1157 while (ibufp < ibufend) { 1158 c = *ibufp++; 1159 if (*ibufp & LSR_OE) { 1160 sc->sc_overflows++; 1161 if (sc->sc_errors++ == 0) 1162 timeout(comdiag, sc, 60 * hz); 1163 } 1164 /* This is ugly, but fast. */ 1165 c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2]; 1166 (*linesw[tp->t_line].l_rint)(c, tp); 1167 } 1168 } 1169 1170 out: 1171 timeout(comsoft, NULL, 1); 1172 } 1173 1174 int 1175 comintr(arg) 1176 void *arg; 1177 { 1178 struct com_softc *sc = arg; 1179 bus_chipset_tag_t bc = sc->sc_bc; 1180 bus_io_handle_t ioh = sc->sc_ioh; 1181 struct tty *tp; 1182 u_char lsr, data, msr, delta; 1183 #ifdef COM_DEBUG 1184 int n; 1185 struct { 1186 u_char iir, lsr, msr; 1187 } iter[32]; 1188 #endif 1189 1190 #ifdef COM_DEBUG 1191 n = 0; 1192 if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND)) 1193 return (0); 1194 #else 1195 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND)) 1196 return (0); 1197 #endif 1198 1199 tp = sc->sc_tty; 1200 1201 for (;;) { 1202 #ifdef COM_DEBUG 1203 iter[n].lsr = 1204 #endif 1205 lsr = bus_io_read_1(bc, ioh, com_lsr); 1206 1207 if (ISSET(lsr, LSR_RXRDY)) { 1208 register u_char *p = sc->sc_ibufp; 1209 1210 comevents = 1; 1211 do { 1212 data = bus_io_read_1(bc, ioh, com_data); 1213 if (ISSET(lsr, LSR_BI)) { 1214 #ifdef notdef 1215 printf("break %02x %02x %02x %02x\n", 1216 sc->sc_msr, sc->sc_mcr, sc->sc_lcr, 1217 sc->sc_dtr); 1218 #endif 1219 #ifdef DDB 1220 if (ISSET(sc->sc_hwflags, 1221 COM_HW_CONSOLE)) { 1222 Debugger(); 1223 goto next; 1224 } 1225 #endif 1226 } 1227 if (p >= sc->sc_ibufend) { 1228 sc->sc_floods++; 1229 if (sc->sc_errors++ == 0) 1230 timeout(comdiag, sc, 60 * hz); 1231 } else { 1232 *p++ = data; 1233 *p++ = lsr; 1234 if (p == sc->sc_ibufhigh && 1235 ISSET(tp->t_cflag, CRTSCTS)) { 1236 /* XXX */ 1237 CLR(sc->sc_mcr, MCR_RTS); 1238 bus_io_write_1(bc, ioh, com_mcr, 1239 sc->sc_mcr); 1240 } 1241 } 1242 #ifdef DDB 1243 next: 1244 #endif 1245 #ifdef COM_DEBUG 1246 if (++n >= 32) 1247 goto ohfudge; 1248 iter[n].lsr = 1249 #endif 1250 lsr = bus_io_read_1(bc, ioh, com_lsr); 1251 } while (ISSET(lsr, LSR_RXRDY)); 1252 1253 sc->sc_ibufp = p; 1254 } 1255 #ifdef COM_DEBUG 1256 else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE)) 1257 printf("weird lsr %02x\n", lsr); 1258 #endif 1259 1260 #ifdef COM_DEBUG 1261 iter[n].msr = 1262 #endif 1263 msr = bus_io_read_1(bc, ioh, com_msr); 1264 1265 if (msr != sc->sc_msr) { 1266 delta = msr ^ sc->sc_msr; 1267 sc->sc_msr = msr; 1268 if (ISSET(delta, MSR_DCD) && 1269 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && 1270 (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { 1271 CLR(sc->sc_mcr, sc->sc_dtr); 1272 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); 1273 } 1274 if (ISSET(delta & msr, MSR_CTS) && 1275 ISSET(tp->t_cflag, CRTSCTS)) { 1276 /* the line is up and we want to do rts/cts flow control */ 1277 (*linesw[tp->t_line].l_start)(tp); 1278 } 1279 } 1280 1281 if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) { 1282 CLR(tp->t_state, TS_BUSY | TS_FLUSH); 1283 if (sc->sc_halt > 0) 1284 wakeup(&tp->t_outq); 1285 (*linesw[tp->t_line].l_start)(tp); 1286 } 1287 1288 #ifdef COM_DEBUG 1289 if (++n >= 32) 1290 goto ohfudge; 1291 if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND)) 1292 return (1); 1293 #else 1294 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND)) 1295 return (1); 1296 #endif 1297 } 1298 #ifdef COM_DEBUG 1299 ohfudge: 1300 printf("comintr: too many iterations"); 1301 for (n = 0; n < 32; n++) { 1302 if ((n % 4) == 0) 1303 printf("\ncomintr: iter[%02d]", n); 1304 printf(" %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr); 1305 } 1306 printf("\n"); 1307 printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n", 1308 sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier); 1309 printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state, 1310 sc->sc_tty->t_outq.c_cc); 1311 #endif 1312 } 1313 1314 /* 1315 * Following are all routines needed for COM to act as console 1316 */ 1317 #include <dev/cons.h> 1318 1319 void 1320 comcnprobe(cp) 1321 struct consdev *cp; 1322 { 1323 /* XXX NEEDS TO BE FIXED XXX */ 1324 bus_chipset_tag_t bc = 0; 1325 bus_io_handle_t ioh; 1326 int found; 1327 1328 if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) { 1329 cp->cn_pri = CN_DEAD; 1330 return; 1331 } 1332 found = comprobe1(bc, ioh, CONADDR); 1333 bus_io_unmap(bc, ioh, COM_NPORTS); 1334 if (!found) { 1335 cp->cn_pri = CN_DEAD; 1336 return; 1337 } 1338 1339 /* locate the major number */ 1340 for (commajor = 0; commajor < nchrdev; commajor++) 1341 if (cdevsw[commajor].d_open == comopen) 1342 break; 1343 1344 /* initialize required fields */ 1345 cp->cn_dev = makedev(commajor, CONUNIT); 1346 #ifdef COMCONSOLE 1347 cp->cn_pri = CN_REMOTE; /* Force a serial port console */ 1348 #else 1349 cp->cn_pri = CN_NORMAL; 1350 #endif 1351 } 1352 1353 void 1354 comcninit(cp) 1355 struct consdev *cp; 1356 { 1357 1358 #if 0 1359 XXX NEEDS TO BE FIXED XXX 1360 comconsbc = ???; 1361 #endif 1362 if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh)) 1363 panic("comcninit: mapping failed"); 1364 1365 cominit(comconsbc, comconsioh, comdefaultrate); 1366 comconsaddr = CONADDR; 1367 comconsinit = 0; 1368 } 1369 1370 void 1371 cominit(bc, ioh, rate) 1372 bus_chipset_tag_t bc; 1373 bus_io_handle_t ioh; 1374 int rate; 1375 { 1376 int s = splhigh(); 1377 u_char stat; 1378 1379 bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB); 1380 rate = comspeed(comdefaultrate); 1381 bus_io_write_1(bc, ioh, com_dlbl, rate); 1382 bus_io_write_1(bc, ioh, com_dlbh, rate >> 8); 1383 bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS); 1384 bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY); 1385 bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4); 1386 stat = bus_io_read_1(bc, ioh, com_iir); 1387 splx(s); 1388 } 1389 1390 int 1391 comcngetc(dev) 1392 dev_t dev; 1393 { 1394 int s = splhigh(); 1395 bus_chipset_tag_t bc = comconsbc; 1396 bus_io_handle_t ioh = comconsioh; 1397 u_char stat, c; 1398 1399 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY)) 1400 ; 1401 c = bus_io_read_1(bc, ioh, com_data); 1402 stat = bus_io_read_1(bc, ioh, com_iir); 1403 splx(s); 1404 return c; 1405 } 1406 1407 /* 1408 * Console kernel output character routine. 1409 */ 1410 void 1411 comcnputc(dev, c) 1412 dev_t dev; 1413 int c; 1414 { 1415 int s = splhigh(); 1416 bus_chipset_tag_t bc = comconsbc; 1417 bus_io_handle_t ioh = comconsioh; 1418 u_char stat; 1419 register int timo; 1420 1421 #ifdef KGDB 1422 if (dev != kgdb_dev) 1423 #endif 1424 if (comconsinit == 0) { 1425 cominit(bc, ioh, comdefaultrate); 1426 comconsinit = 1; 1427 } 1428 /* wait for any pending transmission to finish */ 1429 timo = 50000; 1430 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo) 1431 ; 1432 bus_io_write_1(bc, ioh, com_data, c); 1433 /* wait for this transmission to complete */ 1434 timo = 1500000; 1435 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo) 1436 ; 1437 /* clear any interrupts generated by this transmission */ 1438 stat = bus_io_read_1(bc, ioh, com_iir); 1439 splx(s); 1440 } 1441 1442 void 1443 comcnpollc(dev, on) 1444 dev_t dev; 1445 int on; 1446 { 1447 1448 } 1449