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