1 /* $NetBSD: plcom.c,v 1.1 2001/10/27 16:22:06 rearnsha Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 ARM Ltd 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the company may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Charles M. Hannum. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the NetBSD 48 * Foundation, Inc. and its contributors. 49 * 4. Neither the name of The NetBSD Foundation nor the names of its 50 * contributors may be used to endorse or promote products derived 51 * from this software without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63 * POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 /* 67 * Copyright (c) 1991 The Regents of the University of California. 68 * All rights reserved. 69 * 70 * Redistribution and use in source and binary forms, with or without 71 * modification, are permitted provided that the following conditions 72 * are met: 73 * 1. Redistributions of source code must retain the above copyright 74 * notice, this list of conditions and the following disclaimer. 75 * 2. Redistributions in binary form must reproduce the above copyright 76 * notice, this list of conditions and the following disclaimer in the 77 * documentation and/or other materials provided with the distribution. 78 * 3. All advertising materials mentioning features or use of this software 79 * must display the following acknowledgement: 80 * This product includes software developed by the University of 81 * California, Berkeley and its contributors. 82 * 4. Neither the name of the University nor the names of its contributors 83 * may be used to endorse or promote products derived from this software 84 * without specific prior written permission. 85 * 86 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 87 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 88 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 89 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 90 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 91 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 92 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 93 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 94 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 95 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 96 * SUCH DAMAGE. 97 * 98 * @(#)com.c 7.5 (Berkeley) 5/16/91 99 */ 100 101 /* 102 * COM driver for the Prime Cell PL010 UART, which is similar to the 16C550, 103 * but has a completely different programmer's model. 104 * Derived from the NS16550AF com driver. 105 */ 106 107 #include "opt_plcom.h" 108 #include "opt_ddb.h" 109 #include "opt_ddbparam.h" 110 #include "opt_kgdb.h" 111 112 #include "rnd.h" 113 #if NRND > 0 && defined(RND_COM) 114 #include <sys/rnd.h> 115 #endif 116 117 /* 118 * Override cnmagic(9) macro before including <sys/systm.h>. 119 * We need to know if cn_check_magic triggered debugger, so set a flag. 120 * Callers of cn_check_magic must declare int cn_trapped = 0; 121 * XXX: this is *ugly*! 122 */ 123 #define cn_trap() \ 124 do { \ 125 console_debugger(); \ 126 cn_trapped = 1; \ 127 } while (/* CONSTCOND */ 0) 128 129 #include <sys/param.h> 130 #include <sys/systm.h> 131 #include <sys/ioctl.h> 132 #include <sys/select.h> 133 #include <sys/tty.h> 134 #include <sys/proc.h> 135 #include <sys/user.h> 136 #include <sys/conf.h> 137 #include <sys/file.h> 138 #include <sys/uio.h> 139 #include <sys/kernel.h> 140 #include <sys/syslog.h> 141 #include <sys/types.h> 142 #include <sys/device.h> 143 #include <sys/malloc.h> 144 #include <sys/timepps.h> 145 #include <sys/vnode.h> 146 147 #include <machine/intr.h> 148 #include <machine/bus.h> 149 150 #include <evbarm/dev/plcomreg.h> 151 #include <evbarm/dev/plcomvar.h> 152 153 #include <dev/cons.h> 154 155 static void plcom_enable_debugport (struct plcom_softc *); 156 157 void plcom_config (struct plcom_softc *); 158 void plcom_shutdown (struct plcom_softc *); 159 int plcomspeed (long, long); 160 static u_char cflag2lcr (tcflag_t); 161 int plcomparam (struct tty *, struct termios *); 162 void plcomstart (struct tty *); 163 int plcomhwiflow (struct tty *, int); 164 165 void plcom_loadchannelregs (struct plcom_softc *); 166 void plcom_hwiflow (struct plcom_softc *); 167 void plcom_break (struct plcom_softc *, int); 168 void plcom_modem (struct plcom_softc *, int); 169 void tiocm_to_plcom (struct plcom_softc *, u_long, int); 170 int plcom_to_tiocm (struct plcom_softc *); 171 void plcom_iflush (struct plcom_softc *); 172 173 int plcom_common_getc (dev_t, bus_space_tag_t, bus_space_handle_t); 174 void plcom_common_putc (dev_t, bus_space_tag_t, bus_space_handle_t, int); 175 176 int plcominit (bus_space_tag_t, bus_addr_t, int, int, tcflag_t, 177 bus_space_handle_t *); 178 179 /* XXX: This belongs elsewhere */ 180 cdev_decl(plcom); 181 182 int plcomcngetc (dev_t); 183 void plcomcnputc (dev_t, int); 184 void plcomcnpollc (dev_t, int); 185 186 #define integrate static inline 187 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 188 void plcomsoft (void *); 189 #else 190 #ifndef __NO_SOFT_SERIAL_INTERRUPT 191 void plcomsoft (void); 192 #else 193 void plcomsoft (void *); 194 struct callout plcomsoft_callout = CALLOUT_INITIALIZER; 195 #endif 196 #endif 197 integrate void plcom_rxsoft (struct plcom_softc *, struct tty *); 198 integrate void plcom_txsoft (struct plcom_softc *, struct tty *); 199 integrate void plcom_stsoft (struct plcom_softc *, struct tty *); 200 integrate void plcom_schedrx (struct plcom_softc *); 201 void plcomdiag (void *); 202 203 extern struct cfdriver plcom_cd; 204 205 /* 206 * Make this an option variable one can patch. 207 * But be warned: this must be a power of 2! 208 */ 209 u_int plcom_rbuf_size = PLCOM_RING_SIZE; 210 211 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 212 u_int plcom_rbuf_hiwat = (PLCOM_RING_SIZE * 1) / 4; 213 u_int plcom_rbuf_lowat = (PLCOM_RING_SIZE * 3) / 4; 214 215 static int plcomconsunit = -1; 216 static bus_space_tag_t plcomconstag; 217 static bus_space_handle_t plcomconsioh; 218 static int plcomconsattached; 219 static int plcomconsrate; 220 static tcflag_t plcomconscflag; 221 static struct cnm_state plcom_cnm_state; 222 223 static int ppscap = 224 PPS_TSFMT_TSPEC | 225 PPS_CAPTUREASSERT | 226 PPS_CAPTURECLEAR | 227 #ifdef PPS_SYNC 228 PPS_HARDPPSONASSERT | PPS_HARDPPSONCLEAR | 229 #endif /* PPS_SYNC */ 230 PPS_OFFSETASSERT | PPS_OFFSETCLEAR; 231 232 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 233 #ifdef __NO_SOFT_SERIAL_INTERRUPT 234 volatile int plcom_softintr_scheduled; 235 #endif 236 #endif 237 238 #ifdef KGDB 239 #include <sys/kgdb.h> 240 241 static int plcom_kgdb_unit; 242 static bus_space_tag_t plcom_kgdb_iot; 243 static bus_space_handle_t plcom_kgdb_ioh; 244 static int plcom_kgdb_attached; 245 246 int plcom_kgdb_getc (void *); 247 void plcom_kgdb_putc (void *, int); 248 #endif /* KGDB */ 249 250 #define PLCOMUNIT_MASK 0x7ffff 251 #define PLCOMDIALOUT_MASK 0x80000 252 253 #define PLCOMUNIT(x) (minor(x) & PLCOMUNIT_MASK) 254 #define PLCOMDIALOUT(x) (minor(x) & PLCOMDIALOUT_MASK) 255 256 #define PLCOM_ISALIVE(sc) ((sc)->enabled != 0 && \ 257 ISSET((sc)->sc_dev.dv_flags, DVF_ACTIVE)) 258 259 #define BR BUS_SPACE_BARRIER_READ 260 #define BW BUS_SPACE_BARRIER_WRITE 261 #define PLCOM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, PLCOM_UART_SIZE, (f)) 262 263 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(PLCOM_MPLOCK) 264 265 #define PLCOM_LOCK(sc) simple_lock(&(sc)->sc_lock) 266 #define PLCOM_UNLOCK(sc) simple_unlock(&(sc)->sc_lock) 267 268 #else 269 270 #define PLCOM_LOCK(sc) 271 #define PLCOM_UNLOCK(sc) 272 273 #endif 274 275 int 276 plcomspeed(long speed, long frequency) 277 { 278 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 279 280 int x, err; 281 282 #if 0 283 if (speed == 0) 284 return 0; 285 #endif 286 if (speed <= 0) 287 return -1; 288 x = divrnd(frequency / 16, speed); 289 if (x <= 0) 290 return -1; 291 err = divrnd(((quad_t)frequency) * 1000 / 16, speed * x) - 1000; 292 if (err < 0) 293 err = -err; 294 if (err > PLCOM_TOLERANCE) 295 return -1; 296 return x; 297 298 #undef divrnd 299 } 300 301 #ifdef PLCOM_DEBUG 302 int plcom_debug = 0; 303 304 void plcomstatus (struct plcom_softc *, char *); 305 void 306 plcomstatus(struct plcom_softc *sc, char *str) 307 { 308 struct tty *tp = sc->sc_tty; 309 310 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n", 311 sc->sc_dev.dv_xname, str, 312 ISSET(tp->t_cflag, CLOCAL) ? "+" : "-", 313 ISSET(sc->sc_msr, MSR_DCD) ? "+" : "-", 314 ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-", 315 ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-", 316 sc->sc_tx_stopped ? "+" : "-"); 317 318 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n", 319 sc->sc_dev.dv_xname, str, 320 ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-", 321 ISSET(sc->sc_msr, MSR_CTS) ? "+" : "-", 322 ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-", 323 ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-", 324 sc->sc_rx_flags); 325 } 326 #endif 327 328 int 329 plcomprobe1(bus_space_tag_t iot, bus_space_handle_t ioh) 330 { 331 int data; 332 333 /* Disable the UART. */ 334 bus_space_write_1(iot, ioh, plcom_cr, 0); 335 /* Make sure the FIFO is off. */ 336 bus_space_write_1(iot, ioh, plcom_lcr, LCR_8BITS); 337 /* Disable interrupts. */ 338 bus_space_write_1(iot, ioh, plcom_iir, 0); 339 340 /* Make sure we swallow anything in the receiving register. */ 341 data = bus_space_read_1(iot, ioh, plcom_dr); 342 343 if (bus_space_read_1(iot, ioh, plcom_lcr) != LCR_8BITS) 344 return 0; 345 346 data = bus_space_read_1(iot, ioh, plcom_fr) & (FR_RXFF | FR_RXFE); 347 348 if (data != FR_RXFE) 349 return 0; 350 351 return 1; 352 } 353 354 static void 355 plcom_enable_debugport(struct plcom_softc *sc) 356 { 357 int s; 358 359 /* Turn on line break interrupt, set carrier. */ 360 s = splserial(); 361 PLCOM_LOCK(sc); 362 sc->sc_cr = CR_RIE | CR_RTIE | CR_UARTEN; 363 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr); 364 SET(sc->sc_mcr, MCR_DTR | MCR_RTS); 365 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit, sc->sc_mcr); 366 PLCOM_UNLOCK(sc); 367 splx(s); 368 } 369 370 void 371 plcom_attach_subr(struct plcom_softc *sc) 372 { 373 int unit = sc->sc_iounit; 374 bus_space_tag_t iot = sc->sc_iot; 375 bus_space_handle_t ioh = sc->sc_ioh; 376 struct tty *tp; 377 378 callout_init(&sc->sc_diag_callout); 379 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(PLCOM_MPLOCK) 380 simple_lock_init(&sc->sc_lock); 381 #endif 382 383 /* Disable interrupts before configuring the device. */ 384 sc->sc_cr = 0; 385 386 if (plcomconstag && unit == plcomconsunit) { 387 plcomconsattached = 1; 388 389 plcomconstag = iot; 390 plcomconsioh = ioh; 391 392 /* Make sure the console is always "hardwired". */ 393 delay(1000); /* wait for output to finish */ 394 SET(sc->sc_hwflags, PLCOM_HW_CONSOLE); 395 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 396 /* Must re-enable the console immediately, or we will 397 hang when trying to print. */ 398 sc->sc_cr = CR_UARTEN; 399 } 400 401 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr); 402 403 /* The PL010 has a 16-byte fifo, but the tx interrupt triggers when 404 there is space for 8 more bytes. */ 405 sc->sc_fifolen = 8; 406 printf("\n"); 407 408 if (ISSET(sc->sc_hwflags, PLCOM_HW_TXFIFO_DISABLE)) { 409 sc->sc_fifolen = 1; 410 printf("%s: txfifo disabled\n", sc->sc_dev.dv_xname); 411 } 412 413 if (sc->sc_fifolen > 1) 414 SET(sc->sc_hwflags, PLCOM_HW_FIFO); 415 416 tp = ttymalloc(); 417 tp->t_oproc = plcomstart; 418 tp->t_param = plcomparam; 419 tp->t_hwiflow = plcomhwiflow; 420 421 sc->sc_tty = tp; 422 sc->sc_rbuf = malloc(plcom_rbuf_size << 1, M_DEVBUF, M_NOWAIT); 423 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 424 sc->sc_rbavail = plcom_rbuf_size; 425 if (sc->sc_rbuf == NULL) { 426 printf("%s: unable to allocate ring buffer\n", 427 sc->sc_dev.dv_xname); 428 return; 429 } 430 sc->sc_ebuf = sc->sc_rbuf + (plcom_rbuf_size << 1); 431 432 tty_attach(tp); 433 434 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) { 435 int maj; 436 437 /* locate the major number */ 438 for (maj = 0; maj < nchrdev; maj++) 439 if (cdevsw[maj].d_open == plcomopen) 440 break; 441 442 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit); 443 444 printf("%s: console\n", sc->sc_dev.dv_xname); 445 } 446 447 #ifdef KGDB 448 /* 449 * Allow kgdb to "take over" this port. If this is 450 * the kgdb device, it has exclusive use. 451 */ 452 if (iot == plcom_kgdb_iot && unit == plcom_kgdb_unit) { 453 plcom_kgdb_attached = 1; 454 455 SET(sc->sc_hwflags, PLCOM_HW_KGDB); 456 printf("%s: kgdb\n", sc->sc_dev.dv_xname); 457 } 458 #endif 459 460 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 461 sc->sc_si = softintr_establish(IPL_SOFTSERIAL, plcomsoft, sc); 462 #endif 463 464 #if NRND > 0 && defined(RND_COM) 465 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 466 RND_TYPE_TTY, 0); 467 #endif 468 469 /* if there are no enable/disable functions, assume the device 470 is always enabled */ 471 if (!sc->enable) 472 sc->enabled = 1; 473 474 plcom_config(sc); 475 476 SET(sc->sc_hwflags, PLCOM_HW_DEV_OK); 477 } 478 479 void 480 plcom_config(struct plcom_softc *sc) 481 { 482 bus_space_tag_t iot = sc->sc_iot; 483 bus_space_handle_t ioh = sc->sc_ioh; 484 485 /* Disable interrupts before configuring the device. */ 486 sc->sc_cr = 0; 487 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr); 488 489 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE|PLCOM_HW_KGDB)) 490 plcom_enable_debugport(sc); 491 } 492 493 int 494 plcom_detach(self, flags) 495 struct device *self; 496 int flags; 497 { 498 struct plcom_softc *sc = (struct plcom_softc *)self; 499 int maj, mn; 500 501 /* locate the major number */ 502 for (maj = 0; maj < nchrdev; maj++) 503 if (cdevsw[maj].d_open == plcomopen) 504 break; 505 506 /* Nuke the vnodes for any open instances. */ 507 mn = self->dv_unit; 508 vdevgone(maj, mn, mn, VCHR); 509 510 mn |= PLCOMDIALOUT_MASK; 511 vdevgone(maj, mn, mn, VCHR); 512 513 /* Free the receive buffer. */ 514 free(sc->sc_rbuf, M_DEVBUF); 515 516 /* Detach and free the tty. */ 517 tty_detach(sc->sc_tty); 518 ttyfree(sc->sc_tty); 519 520 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 521 /* Unhook the soft interrupt handler. */ 522 softintr_disestablish(sc->sc_si); 523 #endif 524 525 #if NRND > 0 && defined(RND_COM) 526 /* Unhook the entropy source. */ 527 rnd_detach_source(&sc->rnd_source); 528 #endif 529 530 return 0; 531 } 532 533 int 534 plcom_activate(struct device *self, enum devact act) 535 { 536 struct plcom_softc *sc = (struct plcom_softc *)self; 537 int s, rv = 0; 538 539 s = splserial(); 540 PLCOM_LOCK(sc); 541 switch (act) { 542 case DVACT_ACTIVATE: 543 rv = EOPNOTSUPP; 544 break; 545 546 case DVACT_DEACTIVATE: 547 if (sc->sc_hwflags & (PLCOM_HW_CONSOLE|PLCOM_HW_KGDB)) { 548 rv = EBUSY; 549 break; 550 } 551 552 if (sc->disable != NULL && sc->enabled != 0) { 553 (*sc->disable)(sc); 554 sc->enabled = 0; 555 } 556 break; 557 } 558 559 PLCOM_UNLOCK(sc); 560 splx(s); 561 return rv; 562 } 563 564 void 565 plcom_shutdown(struct plcom_softc *sc) 566 { 567 struct tty *tp = sc->sc_tty; 568 int s; 569 570 s = splserial(); 571 PLCOM_LOCK(sc); 572 573 /* If we were asserting flow control, then deassert it. */ 574 SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); 575 plcom_hwiflow(sc); 576 577 /* Clear any break condition set with TIOCSBRK. */ 578 plcom_break(sc, 0); 579 580 /* Turn off PPS capture on last close. */ 581 sc->sc_ppsmask = 0; 582 sc->ppsparam.mode = 0; 583 584 /* 585 * Hang up if necessary. Wait a bit, so the other side has time to 586 * notice even if we immediately open the port again. 587 * Avoid tsleeping above splhigh(). 588 */ 589 if (ISSET(tp->t_cflag, HUPCL)) { 590 plcom_modem(sc, 0); 591 PLCOM_UNLOCK(sc); 592 splx(s); 593 /* XXX tsleep will only timeout */ 594 (void) tsleep(sc, TTIPRI, ttclos, hz); 595 s = splserial(); 596 PLCOM_LOCK(sc); 597 } 598 599 /* Turn off interrupts. */ 600 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) 601 /* interrupt on break */ 602 sc->sc_cr = CR_RIE | CR_RTIE | CR_UARTEN; 603 else 604 sc->sc_cr = 0; 605 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr); 606 607 if (sc->disable) { 608 #ifdef DIAGNOSTIC 609 if (!sc->enabled) 610 panic("plcom_shutdown: not enabled?"); 611 #endif 612 (*sc->disable)(sc); 613 sc->enabled = 0; 614 } 615 PLCOM_UNLOCK(sc); 616 splx(s); 617 } 618 619 int 620 plcomopen(dev_t dev, int flag, int mode, struct proc *p) 621 { 622 struct plcom_softc *sc; 623 struct tty *tp; 624 int s, s2; 625 int error; 626 627 sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 628 if (sc == NULL || !ISSET(sc->sc_hwflags, PLCOM_HW_DEV_OK) || 629 sc->sc_rbuf == NULL) 630 return ENXIO; 631 632 if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0) 633 return ENXIO; 634 635 #ifdef KGDB 636 /* 637 * If this is the kgdb port, no other use is permitted. 638 */ 639 if (ISSET(sc->sc_hwflags, PLCOM_HW_KGDB)) 640 return EBUSY; 641 #endif 642 643 tp = sc->sc_tty; 644 645 if (ISSET(tp->t_state, TS_ISOPEN) && 646 ISSET(tp->t_state, TS_XCLUDE) && 647 p->p_ucred->cr_uid != 0) 648 return EBUSY; 649 650 s = spltty(); 651 652 /* 653 * Do the following iff this is a first open. 654 */ 655 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 656 struct termios t; 657 658 tp->t_dev = dev; 659 660 s2 = splserial(); 661 PLCOM_LOCK(sc); 662 663 if (sc->enable) { 664 if ((*sc->enable)(sc)) { 665 PLCOM_UNLOCK(sc); 666 splx(s2); 667 splx(s); 668 printf("%s: device enable failed\n", 669 sc->sc_dev.dv_xname); 670 return EIO; 671 } 672 sc->enabled = 1; 673 plcom_config(sc); 674 } 675 676 /* Turn on interrupts. */ 677 /* IER_ERXRDY | IER_ERLS | IER_EMSC; */ 678 sc->sc_cr = CR_RIE | CR_RTIE | CR_MSIE | CR_UARTEN; 679 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr); 680 681 /* Fetch the current modem control status, needed later. */ 682 sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, plcom_fr); 683 684 /* Clear PPS capture state on first open. */ 685 sc->sc_ppsmask = 0; 686 sc->ppsparam.mode = 0; 687 688 PLCOM_UNLOCK(sc); 689 splx(s2); 690 691 /* 692 * Initialize the termios status to the defaults. Add in the 693 * sticky bits from TIOCSFLAGS. 694 */ 695 t.c_ispeed = 0; 696 if (ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) { 697 t.c_ospeed = plcomconsrate; 698 t.c_cflag = plcomconscflag; 699 } else { 700 t.c_ospeed = TTYDEF_SPEED; 701 t.c_cflag = TTYDEF_CFLAG; 702 } 703 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 704 SET(t.c_cflag, CLOCAL); 705 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 706 SET(t.c_cflag, CRTSCTS); 707 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 708 SET(t.c_cflag, MDMBUF); 709 /* Make sure plcomparam() will do something. */ 710 tp->t_ospeed = 0; 711 (void) plcomparam(tp, &t); 712 tp->t_iflag = TTYDEF_IFLAG; 713 tp->t_oflag = TTYDEF_OFLAG; 714 tp->t_lflag = TTYDEF_LFLAG; 715 ttychars(tp); 716 ttsetwater(tp); 717 718 s2 = splserial(); 719 PLCOM_LOCK(sc); 720 721 /* 722 * Turn on DTR. We must always do this, even if carrier is not 723 * present, because otherwise we'd have to use TIOCSDTR 724 * immediately after setting CLOCAL, which applications do not 725 * expect. We always assert DTR while the device is open 726 * unless explicitly requested to deassert it. 727 */ 728 plcom_modem(sc, 1); 729 730 /* Clear the input ring, and unblock. */ 731 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 732 sc->sc_rbavail = plcom_rbuf_size; 733 plcom_iflush(sc); 734 CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 735 plcom_hwiflow(sc); 736 737 #ifdef PLCOM_DEBUG 738 if (plcom_debug) 739 plcomstatus(sc, "plcomopen "); 740 #endif 741 742 PLCOM_UNLOCK(sc); 743 splx(s2); 744 } 745 746 splx(s); 747 748 error = ttyopen(tp, PLCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 749 if (error) 750 goto bad; 751 752 error = (*tp->t_linesw->l_open)(dev, tp); 753 if (error) 754 goto bad; 755 756 return 0; 757 758 bad: 759 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 760 /* 761 * We failed to open the device, and nobody else had it opened. 762 * Clean up the state as appropriate. 763 */ 764 plcom_shutdown(sc); 765 } 766 767 return error; 768 } 769 770 int 771 plcomclose(dev_t dev, int flag, int mode, struct proc *p) 772 { 773 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 774 struct tty *tp = sc->sc_tty; 775 776 /* XXX This is for cons.c. */ 777 if (!ISSET(tp->t_state, TS_ISOPEN)) 778 return 0; 779 780 (*tp->t_linesw->l_close)(tp, flag); 781 ttyclose(tp); 782 783 if (PLCOM_ISALIVE(sc) == 0) 784 return 0; 785 786 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 787 /* 788 * Although we got a last close, the device may still be in 789 * use; e.g. if this was the dialout node, and there are still 790 * processes waiting for carrier on the non-dialout node. 791 */ 792 plcom_shutdown(sc); 793 } 794 795 return 0; 796 } 797 798 int 799 plcomread(dev_t dev, struct uio *uio, int flag) 800 { 801 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 802 struct tty *tp = sc->sc_tty; 803 804 if (PLCOM_ISALIVE(sc) == 0) 805 return EIO; 806 807 return (*tp->t_linesw->l_read)(tp, uio, flag); 808 } 809 810 int 811 plcomwrite(dev_t dev, struct uio *uio, int flag) 812 { 813 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 814 struct tty *tp = sc->sc_tty; 815 816 if (PLCOM_ISALIVE(sc) == 0) 817 return EIO; 818 819 return (*tp->t_linesw->l_write)(tp, uio, flag); 820 } 821 822 int 823 plcompoll(dev_t dev, int events, struct proc *p) 824 { 825 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 826 struct tty *tp = sc->sc_tty; 827 828 if (PLCOM_ISALIVE(sc) == 0) 829 return EIO; 830 831 return (*tp->t_linesw->l_poll)(tp, events, p); 832 } 833 834 struct tty * 835 plcomtty(dev_t dev) 836 { 837 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 838 struct tty *tp = sc->sc_tty; 839 840 return tp; 841 } 842 843 int 844 plcomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 845 { 846 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(dev)); 847 struct tty *tp = sc->sc_tty; 848 int error; 849 int s; 850 851 if (PLCOM_ISALIVE(sc) == 0) 852 return EIO; 853 854 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 855 if (error >= 0) 856 return error; 857 858 error = ttioctl(tp, cmd, data, flag, p); 859 if (error >= 0) 860 return error; 861 862 error = 0; 863 864 s = splserial(); 865 PLCOM_LOCK(sc); 866 867 switch (cmd) { 868 case TIOCSBRK: 869 plcom_break(sc, 1); 870 break; 871 872 case TIOCCBRK: 873 plcom_break(sc, 0); 874 break; 875 876 case TIOCSDTR: 877 plcom_modem(sc, 1); 878 break; 879 880 case TIOCCDTR: 881 plcom_modem(sc, 0); 882 break; 883 884 case TIOCGFLAGS: 885 *(int *)data = sc->sc_swflags; 886 break; 887 888 case TIOCSFLAGS: 889 error = suser(p->p_ucred, &p->p_acflag); 890 if (error) 891 break; 892 sc->sc_swflags = *(int *)data; 893 break; 894 895 case TIOCMSET: 896 case TIOCMBIS: 897 case TIOCMBIC: 898 tiocm_to_plcom(sc, cmd, *(int *)data); 899 break; 900 901 case TIOCMGET: 902 *(int *)data = plcom_to_tiocm(sc); 903 break; 904 905 case PPS_IOC_CREATE: 906 break; 907 908 case PPS_IOC_DESTROY: 909 break; 910 911 case PPS_IOC_GETPARAMS: { 912 pps_params_t *pp; 913 pp = (pps_params_t *)data; 914 *pp = sc->ppsparam; 915 break; 916 } 917 918 case PPS_IOC_SETPARAMS: { 919 pps_params_t *pp; 920 int mode; 921 pp = (pps_params_t *)data; 922 if (pp->mode & ~ppscap) { 923 error = EINVAL; 924 break; 925 } 926 sc->ppsparam = *pp; 927 /* 928 * Compute msr masks from user-specified timestamp state. 929 */ 930 mode = sc->ppsparam.mode; 931 #ifdef PPS_SYNC 932 if (mode & PPS_HARDPPSONASSERT) { 933 mode |= PPS_CAPTUREASSERT; 934 /* XXX revoke any previous HARDPPS source */ 935 } 936 if (mode & PPS_HARDPPSONCLEAR) { 937 mode |= PPS_CAPTURECLEAR; 938 /* XXX revoke any previous HARDPPS source */ 939 } 940 #endif /* PPS_SYNC */ 941 switch (mode & PPS_CAPTUREBOTH) { 942 case 0: 943 sc->sc_ppsmask = 0; 944 break; 945 946 case PPS_CAPTUREASSERT: 947 sc->sc_ppsmask = MSR_DCD; 948 sc->sc_ppsassert = MSR_DCD; 949 sc->sc_ppsclear = -1; 950 break; 951 952 case PPS_CAPTURECLEAR: 953 sc->sc_ppsmask = MSR_DCD; 954 sc->sc_ppsassert = -1; 955 sc->sc_ppsclear = 0; 956 break; 957 958 case PPS_CAPTUREBOTH: 959 sc->sc_ppsmask = MSR_DCD; 960 sc->sc_ppsassert = MSR_DCD; 961 sc->sc_ppsclear = 0; 962 break; 963 964 default: 965 error = EINVAL; 966 break; 967 } 968 break; 969 } 970 971 case PPS_IOC_GETCAP: 972 *(int*)data = ppscap; 973 break; 974 975 case PPS_IOC_FETCH: { 976 pps_info_t *pi; 977 pi = (pps_info_t *)data; 978 *pi = sc->ppsinfo; 979 break; 980 } 981 982 case TIOCDCDTIMESTAMP: /* XXX old, overloaded API used by xntpd v3 */ 983 /* 984 * Some GPS clocks models use the falling rather than 985 * rising edge as the on-the-second signal. 986 * The old API has no way to specify PPS polarity. 987 */ 988 sc->sc_ppsmask = MSR_DCD; 989 #ifndef PPS_TRAILING_EDGE 990 sc->sc_ppsassert = MSR_DCD; 991 sc->sc_ppsclear = -1; 992 TIMESPEC_TO_TIMEVAL((struct timeval *)data, 993 &sc->ppsinfo.assert_timestamp); 994 #else 995 sc->sc_ppsassert = -1 996 sc->sc_ppsclear = 0; 997 TIMESPEC_TO_TIMEVAL((struct timeval *)data, 998 &sc->ppsinfo.clear_timestamp); 999 #endif 1000 break; 1001 1002 default: 1003 error = ENOTTY; 1004 break; 1005 } 1006 1007 PLCOM_UNLOCK(sc); 1008 splx(s); 1009 1010 #ifdef PLCOM_DEBUG 1011 if (plcom_debug) 1012 plcomstatus(sc, "plcomioctl "); 1013 #endif 1014 1015 return error; 1016 } 1017 1018 integrate void 1019 plcom_schedrx(struct plcom_softc *sc) 1020 { 1021 1022 sc->sc_rx_ready = 1; 1023 1024 /* Wake up the poller. */ 1025 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1026 softintr_schedule(sc->sc_si); 1027 #else 1028 #ifndef __NO_SOFT_SERIAL_INTERRUPT 1029 setsoftserial(); 1030 #else 1031 if (!plcom_softintr_scheduled) { 1032 plcom_softintr_scheduled = 1; 1033 callout_reset(&plcomsoft_callout, 1, plcomsoft, NULL); 1034 } 1035 #endif 1036 #endif 1037 } 1038 1039 void 1040 plcom_break(struct plcom_softc *sc, int onoff) 1041 { 1042 1043 if (onoff) 1044 SET(sc->sc_lcr, LCR_BRK); 1045 else 1046 CLR(sc->sc_lcr, LCR_BRK); 1047 1048 if (!sc->sc_heldchange) { 1049 if (sc->sc_tx_busy) { 1050 sc->sc_heldtbc = sc->sc_tbc; 1051 sc->sc_tbc = 0; 1052 sc->sc_heldchange = 1; 1053 } else 1054 plcom_loadchannelregs(sc); 1055 } 1056 } 1057 1058 void 1059 plcom_modem(struct plcom_softc *sc, int onoff) 1060 { 1061 1062 if (sc->sc_mcr_dtr == 0) 1063 return; 1064 1065 if (onoff) 1066 SET(sc->sc_mcr, sc->sc_mcr_dtr); 1067 else 1068 CLR(sc->sc_mcr, sc->sc_mcr_dtr); 1069 1070 if (!sc->sc_heldchange) { 1071 if (sc->sc_tx_busy) { 1072 sc->sc_heldtbc = sc->sc_tbc; 1073 sc->sc_tbc = 0; 1074 sc->sc_heldchange = 1; 1075 } else 1076 plcom_loadchannelregs(sc); 1077 } 1078 } 1079 1080 void 1081 tiocm_to_plcom(struct plcom_softc *sc, u_long how, int ttybits) 1082 { 1083 u_char plcombits; 1084 1085 plcombits = 0; 1086 if (ISSET(ttybits, TIOCM_DTR)) 1087 SET(plcombits, MCR_DTR); 1088 if (ISSET(ttybits, TIOCM_RTS)) 1089 SET(plcombits, MCR_RTS); 1090 1091 switch (how) { 1092 case TIOCMBIC: 1093 CLR(sc->sc_mcr, plcombits); 1094 break; 1095 1096 case TIOCMBIS: 1097 SET(sc->sc_mcr, plcombits); 1098 break; 1099 1100 case TIOCMSET: 1101 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); 1102 SET(sc->sc_mcr, plcombits); 1103 break; 1104 } 1105 1106 if (!sc->sc_heldchange) { 1107 if (sc->sc_tx_busy) { 1108 sc->sc_heldtbc = sc->sc_tbc; 1109 sc->sc_tbc = 0; 1110 sc->sc_heldchange = 1; 1111 } else 1112 plcom_loadchannelregs(sc); 1113 } 1114 } 1115 1116 int 1117 plcom_to_tiocm(struct plcom_softc *sc) 1118 { 1119 u_char plcombits; 1120 int ttybits = 0; 1121 1122 plcombits = sc->sc_mcr; 1123 if (ISSET(plcombits, MCR_DTR)) 1124 SET(ttybits, TIOCM_DTR); 1125 if (ISSET(plcombits, MCR_RTS)) 1126 SET(ttybits, TIOCM_RTS); 1127 1128 plcombits = sc->sc_msr; 1129 if (ISSET(plcombits, MSR_DCD)) 1130 SET(ttybits, TIOCM_CD); 1131 if (ISSET(plcombits, MSR_CTS)) 1132 SET(ttybits, TIOCM_CTS); 1133 if (ISSET(plcombits, MSR_DSR)) 1134 SET(ttybits, TIOCM_DSR); 1135 1136 if (sc->sc_cr != 0) 1137 SET(ttybits, TIOCM_LE); 1138 1139 return ttybits; 1140 } 1141 1142 static u_char 1143 cflag2lcr(tcflag_t cflag) 1144 { 1145 u_char lcr = 0; 1146 1147 switch (ISSET(cflag, CSIZE)) { 1148 case CS5: 1149 SET(lcr, LCR_5BITS); 1150 break; 1151 case CS6: 1152 SET(lcr, LCR_6BITS); 1153 break; 1154 case CS7: 1155 SET(lcr, LCR_7BITS); 1156 break; 1157 case CS8: 1158 SET(lcr, LCR_8BITS); 1159 break; 1160 } 1161 if (ISSET(cflag, PARENB)) { 1162 SET(lcr, LCR_PEN); 1163 if (!ISSET(cflag, PARODD)) 1164 SET(lcr, LCR_EPS); 1165 } 1166 if (ISSET(cflag, CSTOPB)) 1167 SET(lcr, LCR_STP2); 1168 1169 return lcr; 1170 } 1171 1172 int 1173 plcomparam(struct tty *tp, struct termios *t) 1174 { 1175 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev)); 1176 int ospeed; 1177 u_char lcr; 1178 int s; 1179 1180 if (PLCOM_ISALIVE(sc) == 0) 1181 return EIO; 1182 1183 ospeed = plcomspeed(t->c_ospeed, sc->sc_frequency); 1184 1185 /* Check requested parameters. */ 1186 if (ospeed < 0) 1187 return EINVAL; 1188 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 1189 return EINVAL; 1190 1191 /* 1192 * For the console, always force CLOCAL and !HUPCL, so that the port 1193 * is always active. 1194 */ 1195 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 1196 ISSET(sc->sc_hwflags, PLCOM_HW_CONSOLE)) { 1197 SET(t->c_cflag, CLOCAL); 1198 CLR(t->c_cflag, HUPCL); 1199 } 1200 1201 /* 1202 * If there were no changes, don't do anything. This avoids dropping 1203 * input and improves performance when all we did was frob things like 1204 * VMIN and VTIME. 1205 */ 1206 if (tp->t_ospeed == t->c_ospeed && 1207 tp->t_cflag == t->c_cflag) 1208 return 0; 1209 1210 lcr = ISSET(sc->sc_lcr, LCR_BRK) | cflag2lcr(t->c_cflag); 1211 1212 s = splserial(); 1213 PLCOM_LOCK(sc); 1214 1215 sc->sc_lcr = lcr; 1216 1217 /* 1218 * PL010 has a fixed-length FIFO trigger point. 1219 */ 1220 if (ISSET(sc->sc_hwflags, PLCOM_HW_FIFO)) 1221 sc->sc_fifo = 1; 1222 else 1223 sc->sc_fifo = 0; 1224 1225 if (sc->sc_fifo) 1226 SET(sc->sc_lcr, LCR_FEN); 1227 1228 /* 1229 * If we're not in a mode that assumes a connection is present, then 1230 * ignore carrier changes. 1231 */ 1232 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 1233 sc->sc_msr_dcd = 0; 1234 else 1235 sc->sc_msr_dcd = MSR_DCD; 1236 /* 1237 * Set the flow control pins depending on the current flow control 1238 * mode. 1239 */ 1240 if (ISSET(t->c_cflag, CRTSCTS)) { 1241 sc->sc_mcr_dtr = MCR_DTR; 1242 sc->sc_mcr_rts = MCR_RTS; 1243 sc->sc_msr_cts = MSR_CTS; 1244 } else if (ISSET(t->c_cflag, MDMBUF)) { 1245 /* 1246 * For DTR/DCD flow control, make sure we don't toggle DTR for 1247 * carrier detection. 1248 */ 1249 sc->sc_mcr_dtr = 0; 1250 sc->sc_mcr_rts = MCR_DTR; 1251 sc->sc_msr_cts = MSR_DCD; 1252 } else { 1253 /* 1254 * If no flow control, then always set RTS. This will make 1255 * the other side happy if it mistakenly thinks we're doing 1256 * RTS/CTS flow control. 1257 */ 1258 sc->sc_mcr_dtr = MCR_DTR | MCR_RTS; 1259 sc->sc_mcr_rts = 0; 1260 sc->sc_msr_cts = 0; 1261 if (ISSET(sc->sc_mcr, MCR_DTR)) 1262 SET(sc->sc_mcr, MCR_RTS); 1263 else 1264 CLR(sc->sc_mcr, MCR_RTS); 1265 } 1266 sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd; 1267 1268 #if 0 1269 if (ospeed == 0) 1270 CLR(sc->sc_mcr, sc->sc_mcr_dtr); 1271 else 1272 SET(sc->sc_mcr, sc->sc_mcr_dtr); 1273 #endif 1274 1275 sc->sc_dlbl = ospeed; 1276 sc->sc_dlbh = ospeed >> 8; 1277 1278 /* And copy to tty. */ 1279 tp->t_ispeed = 0; 1280 tp->t_ospeed = t->c_ospeed; 1281 tp->t_cflag = t->c_cflag; 1282 1283 if (!sc->sc_heldchange) { 1284 if (sc->sc_tx_busy) { 1285 sc->sc_heldtbc = sc->sc_tbc; 1286 sc->sc_tbc = 0; 1287 sc->sc_heldchange = 1; 1288 } else 1289 plcom_loadchannelregs(sc); 1290 } 1291 1292 if (!ISSET(t->c_cflag, CHWFLOW)) { 1293 /* Disable the high water mark. */ 1294 sc->sc_r_hiwat = 0; 1295 sc->sc_r_lowat = 0; 1296 if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { 1297 CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 1298 plcom_schedrx(sc); 1299 } 1300 if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 1301 CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 1302 plcom_hwiflow(sc); 1303 } 1304 } else { 1305 sc->sc_r_hiwat = plcom_rbuf_hiwat; 1306 sc->sc_r_lowat = plcom_rbuf_lowat; 1307 } 1308 1309 PLCOM_UNLOCK(sc); 1310 splx(s); 1311 1312 /* 1313 * Update the tty layer's idea of the carrier bit, in case we changed 1314 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 1315 * explicit request. 1316 */ 1317 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD)); 1318 1319 #ifdef PLCOM_DEBUG 1320 if (plcom_debug) 1321 plcomstatus(sc, "plcomparam "); 1322 #endif 1323 1324 if (!ISSET(t->c_cflag, CHWFLOW)) { 1325 if (sc->sc_tx_stopped) { 1326 sc->sc_tx_stopped = 0; 1327 plcomstart(tp); 1328 } 1329 } 1330 1331 return 0; 1332 } 1333 1334 void 1335 plcom_iflush(struct plcom_softc *sc) 1336 { 1337 bus_space_tag_t iot = sc->sc_iot; 1338 bus_space_handle_t ioh = sc->sc_ioh; 1339 #ifdef DIAGNOSTIC 1340 int reg; 1341 #endif 1342 int timo; 1343 1344 #ifdef DIAGNOSTIC 1345 reg = 0xffff; 1346 #endif 1347 timo = 50000; 1348 /* flush any pending I/O */ 1349 while (! ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE) 1350 && --timo) 1351 #ifdef DIAGNOSTIC 1352 reg = 1353 #else 1354 (void) 1355 #endif 1356 bus_space_read_1(iot, ioh, plcom_dr); 1357 #ifdef DIAGNOSTIC 1358 if (!timo) 1359 printf("%s: plcom_iflush timeout %02x\n", sc->sc_dev.dv_xname, 1360 reg); 1361 #endif 1362 } 1363 1364 void 1365 plcom_loadchannelregs(struct plcom_softc *sc) 1366 { 1367 bus_space_tag_t iot = sc->sc_iot; 1368 bus_space_handle_t ioh = sc->sc_ioh; 1369 1370 /* XXXXX necessary? */ 1371 plcom_iflush(sc); 1372 1373 bus_space_write_1(iot, ioh, plcom_cr, 0); 1374 1375 bus_space_write_1(iot, ioh, plcom_dlbl, sc->sc_dlbl); 1376 bus_space_write_1(iot, ioh, plcom_dlbh, sc->sc_dlbh); 1377 bus_space_write_1(iot, ioh, plcom_lcr, sc->sc_lcr); 1378 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit, 1379 sc->sc_mcr_active = sc->sc_mcr); 1380 1381 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr); 1382 } 1383 1384 int 1385 plcomhwiflow(struct tty *tp, int block) 1386 { 1387 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev)); 1388 int s; 1389 1390 if (PLCOM_ISALIVE(sc) == 0) 1391 return 0; 1392 1393 if (sc->sc_mcr_rts == 0) 1394 return 0; 1395 1396 s = splserial(); 1397 PLCOM_LOCK(sc); 1398 1399 if (block) { 1400 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 1401 SET(sc->sc_rx_flags, RX_TTY_BLOCKED); 1402 plcom_hwiflow(sc); 1403 } 1404 } else { 1405 if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { 1406 CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 1407 plcom_schedrx(sc); 1408 } 1409 if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 1410 CLR(sc->sc_rx_flags, RX_TTY_BLOCKED); 1411 plcom_hwiflow(sc); 1412 } 1413 } 1414 1415 PLCOM_UNLOCK(sc); 1416 splx(s); 1417 return 1; 1418 } 1419 1420 /* 1421 * (un)block input via hw flowcontrol 1422 */ 1423 void 1424 plcom_hwiflow(struct plcom_softc *sc) 1425 { 1426 if (sc->sc_mcr_rts == 0) 1427 return; 1428 1429 if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) { 1430 CLR(sc->sc_mcr, sc->sc_mcr_rts); 1431 CLR(sc->sc_mcr_active, sc->sc_mcr_rts); 1432 } else { 1433 SET(sc->sc_mcr, sc->sc_mcr_rts); 1434 SET(sc->sc_mcr_active, sc->sc_mcr_rts); 1435 } 1436 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit, 1437 sc->sc_mcr_active); 1438 } 1439 1440 1441 void 1442 plcomstart(struct tty *tp) 1443 { 1444 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev)); 1445 bus_space_tag_t iot = sc->sc_iot; 1446 bus_space_handle_t ioh = sc->sc_ioh; 1447 int s; 1448 1449 if (PLCOM_ISALIVE(sc) == 0) 1450 return; 1451 1452 s = spltty(); 1453 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 1454 goto out; 1455 if (sc->sc_tx_stopped) 1456 goto out; 1457 1458 if (tp->t_outq.c_cc <= tp->t_lowat) { 1459 if (ISSET(tp->t_state, TS_ASLEEP)) { 1460 CLR(tp->t_state, TS_ASLEEP); 1461 wakeup(&tp->t_outq); 1462 } 1463 selwakeup(&tp->t_wsel); 1464 if (tp->t_outq.c_cc == 0) 1465 goto out; 1466 } 1467 1468 /* Grab the first contiguous region of buffer space. */ 1469 { 1470 u_char *tba; 1471 int tbc; 1472 1473 tba = tp->t_outq.c_cf; 1474 tbc = ndqb(&tp->t_outq, 0); 1475 1476 (void)splserial(); 1477 PLCOM_LOCK(sc); 1478 1479 sc->sc_tba = tba; 1480 sc->sc_tbc = tbc; 1481 } 1482 1483 SET(tp->t_state, TS_BUSY); 1484 sc->sc_tx_busy = 1; 1485 1486 /* Enable transmit completion interrupts if necessary. */ 1487 if (!ISSET(sc->sc_cr, CR_TIE)) { 1488 SET(sc->sc_cr, CR_TIE); 1489 bus_space_write_1(iot, ioh, plcom_cr, sc->sc_cr); 1490 } 1491 1492 /* Output the first chunk of the contiguous buffer. */ 1493 { 1494 int n; 1495 1496 n = sc->sc_tbc; 1497 if (n > sc->sc_fifolen) 1498 n = sc->sc_fifolen; 1499 bus_space_write_multi_1(iot, ioh, plcom_dr, sc->sc_tba, n); 1500 sc->sc_tbc -= n; 1501 sc->sc_tba += n; 1502 } 1503 PLCOM_UNLOCK(sc); 1504 out: 1505 splx(s); 1506 return; 1507 } 1508 1509 /* 1510 * Stop output on a line. 1511 */ 1512 void 1513 plcomstop(struct tty *tp, int flag) 1514 { 1515 struct plcom_softc *sc = device_lookup(&plcom_cd, PLCOMUNIT(tp->t_dev)); 1516 int s; 1517 1518 s = splserial(); 1519 PLCOM_LOCK(sc); 1520 if (ISSET(tp->t_state, TS_BUSY)) { 1521 /* Stop transmitting at the next chunk. */ 1522 sc->sc_tbc = 0; 1523 sc->sc_heldtbc = 0; 1524 if (!ISSET(tp->t_state, TS_TTSTOP)) 1525 SET(tp->t_state, TS_FLUSH); 1526 } 1527 PLCOM_UNLOCK(sc); 1528 splx(s); 1529 } 1530 1531 void 1532 plcomdiag(void *arg) 1533 { 1534 struct plcom_softc *sc = arg; 1535 int overflows, floods; 1536 int s; 1537 1538 s = splserial(); 1539 PLCOM_LOCK(sc); 1540 overflows = sc->sc_overflows; 1541 sc->sc_overflows = 0; 1542 floods = sc->sc_floods; 1543 sc->sc_floods = 0; 1544 sc->sc_errors = 0; 1545 PLCOM_UNLOCK(sc); 1546 splx(s); 1547 1548 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", 1549 sc->sc_dev.dv_xname, 1550 overflows, overflows == 1 ? "" : "s", 1551 floods, floods == 1 ? "" : "s"); 1552 } 1553 1554 integrate void 1555 plcom_rxsoft(struct plcom_softc *sc, struct tty *tp) 1556 { 1557 int (*rint) (int, struct tty *) = tp->t_linesw->l_rint; 1558 u_char *get, *end; 1559 u_int cc, scc; 1560 u_char rsr; 1561 int code; 1562 int s; 1563 1564 end = sc->sc_ebuf; 1565 get = sc->sc_rbget; 1566 scc = cc = plcom_rbuf_size - sc->sc_rbavail; 1567 1568 if (cc == plcom_rbuf_size) { 1569 sc->sc_floods++; 1570 if (sc->sc_errors++ == 0) 1571 callout_reset(&sc->sc_diag_callout, 60 * hz, 1572 plcomdiag, sc); 1573 } 1574 1575 while (cc) { 1576 code = get[0]; 1577 rsr = get[1]; 1578 if (ISSET(rsr, RSR_OE | RSR_BE | RSR_FE | RSR_PE)) { 1579 if (ISSET(rsr, RSR_OE)) { 1580 sc->sc_overflows++; 1581 if (sc->sc_errors++ == 0) 1582 callout_reset(&sc->sc_diag_callout, 1583 60 * hz, plcomdiag, sc); 1584 } 1585 if (ISSET(rsr, RSR_BE | RSR_FE)) 1586 SET(code, TTY_FE); 1587 if (ISSET(rsr, RSR_PE)) 1588 SET(code, TTY_PE); 1589 } 1590 if ((*rint)(code, tp) == -1) { 1591 /* 1592 * The line discipline's buffer is out of space. 1593 */ 1594 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 1595 /* 1596 * We're either not using flow control, or the 1597 * line discipline didn't tell us to block for 1598 * some reason. Either way, we have no way to 1599 * know when there's more space available, so 1600 * just drop the rest of the data. 1601 */ 1602 get += cc << 1; 1603 if (get >= end) 1604 get -= plcom_rbuf_size << 1; 1605 cc = 0; 1606 } else { 1607 /* 1608 * Don't schedule any more receive processing 1609 * until the line discipline tells us there's 1610 * space available (through plcomhwiflow()). 1611 * Leave the rest of the data in the input 1612 * buffer. 1613 */ 1614 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 1615 } 1616 break; 1617 } 1618 get += 2; 1619 if (get >= end) 1620 get = sc->sc_rbuf; 1621 cc--; 1622 } 1623 1624 if (cc != scc) { 1625 sc->sc_rbget = get; 1626 s = splserial(); 1627 PLCOM_LOCK(sc); 1628 1629 cc = sc->sc_rbavail += scc - cc; 1630 /* Buffers should be ok again, release possible block. */ 1631 if (cc >= sc->sc_r_lowat) { 1632 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1633 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1634 SET(sc->sc_cr, CR_RIE | CR_RTIE); 1635 bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr); 1636 } 1637 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 1638 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1639 plcom_hwiflow(sc); 1640 } 1641 } 1642 PLCOM_UNLOCK(sc); 1643 splx(s); 1644 } 1645 } 1646 1647 integrate void 1648 plcom_txsoft(struct plcom_softc *sc, struct tty *tp) 1649 { 1650 1651 CLR(tp->t_state, TS_BUSY); 1652 if (ISSET(tp->t_state, TS_FLUSH)) 1653 CLR(tp->t_state, TS_FLUSH); 1654 else 1655 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 1656 (*tp->t_linesw->l_start)(tp); 1657 } 1658 1659 integrate void 1660 plcom_stsoft(struct plcom_softc *sc, struct tty *tp) 1661 { 1662 u_char msr, delta; 1663 int s; 1664 1665 s = splserial(); 1666 PLCOM_LOCK(sc); 1667 msr = sc->sc_msr; 1668 delta = sc->sc_msr_delta; 1669 sc->sc_msr_delta = 0; 1670 PLCOM_UNLOCK(sc); 1671 splx(s); 1672 1673 if (ISSET(delta, sc->sc_msr_dcd)) { 1674 /* 1675 * Inform the tty layer that carrier detect changed. 1676 */ 1677 (void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSR_DCD)); 1678 } 1679 1680 if (ISSET(delta, sc->sc_msr_cts)) { 1681 /* Block or unblock output according to flow control. */ 1682 if (ISSET(msr, sc->sc_msr_cts)) { 1683 sc->sc_tx_stopped = 0; 1684 (*tp->t_linesw->l_start)(tp); 1685 } else { 1686 sc->sc_tx_stopped = 1; 1687 } 1688 } 1689 1690 #ifdef PLCOM_DEBUG 1691 if (plcom_debug) 1692 plcomstatus(sc, "plcom_stsoft"); 1693 #endif 1694 } 1695 1696 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1697 void 1698 plcomsoft(void *arg) 1699 { 1700 struct plcom_softc *sc = arg; 1701 struct tty *tp; 1702 1703 if (PLCOM_ISALIVE(sc) == 0) 1704 return; 1705 1706 { 1707 #else 1708 void 1709 #ifndef __NO_SOFT_SERIAL_INTERRUPT 1710 plcomsoft(void) 1711 #else 1712 plcomsoft(void *arg) 1713 #endif 1714 { 1715 struct plcom_softc *sc; 1716 struct tty *tp; 1717 int unit; 1718 #ifdef __NO_SOFT_SERIAL_INTERRUPT 1719 int s; 1720 1721 s = splsoftserial(); 1722 plcom_softintr_scheduled = 0; 1723 #endif 1724 1725 for (unit = 0; unit < plcom_cd.cd_ndevs; unit++) { 1726 sc = device_lookup(&plcom_cd, unit); 1727 if (sc == NULL || !ISSET(sc->sc_hwflags, PLCOM_HW_DEV_OK)) 1728 continue; 1729 1730 if (PLCOM_ISALIVE(sc) == 0) 1731 continue; 1732 1733 tp = sc->sc_tty; 1734 if (tp == NULL) 1735 continue; 1736 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1737 continue; 1738 #endif 1739 tp = sc->sc_tty; 1740 1741 if (sc->sc_rx_ready) { 1742 sc->sc_rx_ready = 0; 1743 plcom_rxsoft(sc, tp); 1744 } 1745 1746 if (sc->sc_st_check) { 1747 sc->sc_st_check = 0; 1748 plcom_stsoft(sc, tp); 1749 } 1750 1751 if (sc->sc_tx_done) { 1752 sc->sc_tx_done = 0; 1753 plcom_txsoft(sc, tp); 1754 } 1755 } 1756 1757 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1758 #ifdef __NO_SOFT_SERIAL_INTERRUPT 1759 splx(s); 1760 #endif 1761 #endif 1762 } 1763 1764 #ifdef __ALIGN_BRACKET_LEVEL_FOR_CTAGS 1765 /* there has got to be a better way to do plcomsoft() */ 1766 }} 1767 #endif 1768 1769 int 1770 plcomintr(void *arg) 1771 { 1772 struct plcom_softc *sc = arg; 1773 bus_space_tag_t iot = sc->sc_iot; 1774 bus_space_handle_t ioh = sc->sc_ioh; 1775 u_char *put, *end; 1776 u_int cc; 1777 u_char rsr, iir; 1778 1779 if (PLCOM_ISALIVE(sc) == 0) 1780 return 0; 1781 1782 PLCOM_LOCK(sc); 1783 iir = bus_space_read_1(iot, ioh, plcom_iir); 1784 if (! ISSET(iir, IIR_IMASK)) { 1785 PLCOM_UNLOCK(sc); 1786 return 0; 1787 } 1788 1789 end = sc->sc_ebuf; 1790 put = sc->sc_rbput; 1791 cc = sc->sc_rbavail; 1792 1793 do { 1794 u_char msr, delta, fr; 1795 1796 fr = bus_space_read_1(iot, ioh, plcom_fr); 1797 1798 if (!ISSET(fr, FR_RXFE) && 1799 !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1800 while (cc > 0) { 1801 int cn_trapped = 0; 1802 put[0] = bus_space_read_1(iot, ioh, 1803 plcom_dr); 1804 rsr = bus_space_read_1(iot, ioh, plcom_rsr); 1805 /* Clear any error status. */ 1806 if (ISSET(rsr, 1807 (RSR_BE | RSR_OE | RSR_PE | RSR_FE))) 1808 bus_space_write_1(iot, ioh, plcom_ecr, 1809 0); 1810 if (ISSET(rsr, RSR_BE)) { 1811 int cn_trapped = 0; 1812 cn_check_magic(sc->sc_tty->t_dev, 1813 CNC_BREAK, plcom_cnm_state); 1814 if (cn_trapped) 1815 continue; 1816 #if defined(KGDB) 1817 if (ISSET(sc->sc_hwflags, 1818 PLCOM_HW_KGDB)) { 1819 kgdb_connect(1); 1820 continue; 1821 } 1822 #endif 1823 } 1824 1825 put[1] = rsr; 1826 cn_check_magic(sc->sc_tty->t_dev, 1827 put[0], plcom_cnm_state); 1828 if (cn_trapped) { 1829 fr = bus_space_read_1(iot, ioh, 1830 plcom_fr); 1831 if (ISSET(fr, FR_RXFE)) 1832 break; 1833 1834 continue; 1835 } 1836 put += 2; 1837 if (put >= end) 1838 put = sc->sc_rbuf; 1839 cc--; 1840 1841 fr = bus_space_read_1(iot, ioh, plcom_fr); 1842 if (ISSET(fr, FR_RXFE)) 1843 break; 1844 } 1845 1846 /* 1847 * Current string of incoming characters ended because 1848 * no more data was available or we ran out of space. 1849 * Schedule a receive event if any data was received. 1850 * If we're out of space, turn off receive interrupts. 1851 */ 1852 sc->sc_rbput = put; 1853 sc->sc_rbavail = cc; 1854 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 1855 sc->sc_rx_ready = 1; 1856 1857 /* 1858 * See if we are in danger of overflowing a buffer. If 1859 * so, use hardware flow control to ease the pressure. 1860 */ 1861 if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && 1862 cc < sc->sc_r_hiwat) { 1863 SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); 1864 plcom_hwiflow(sc); 1865 } 1866 1867 /* 1868 * If we're out of space, disable receive interrupts 1869 * until the queue has drained a bit. 1870 */ 1871 if (!cc) { 1872 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1873 CLR(sc->sc_cr, CR_RIE | CR_RTIE); 1874 bus_space_write_1(iot, ioh, plcom_cr, 1875 sc->sc_cr); 1876 } 1877 } else { 1878 if (ISSET(iir, IIR_RIS)) { 1879 bus_space_write_1(iot, ioh, plcom_cr, 0); 1880 delay(10); 1881 bus_space_write_1(iot, ioh, plcom_cr, 1882 sc->sc_cr); 1883 continue; 1884 } 1885 } 1886 1887 msr = bus_space_read_1(iot, ioh, plcom_fr); 1888 delta = msr ^ sc->sc_msr; 1889 sc->sc_msr = msr; 1890 /* Clear any pending modem status interrupt. */ 1891 if (iir & IIR_MIS) 1892 bus_space_write_1(iot, ioh, plcom_icr, 0); 1893 /* 1894 * Pulse-per-second (PSS) signals on edge of DCD? 1895 * Process these even if line discipline is ignoring DCD. 1896 */ 1897 if (delta & sc->sc_ppsmask) { 1898 struct timeval tv; 1899 if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) { 1900 /* XXX nanotime() */ 1901 microtime(&tv); 1902 TIMEVAL_TO_TIMESPEC(&tv, 1903 &sc->ppsinfo.assert_timestamp); 1904 if (sc->ppsparam.mode & PPS_OFFSETASSERT) { 1905 timespecadd(&sc->ppsinfo.assert_timestamp, 1906 &sc->ppsparam.assert_offset, 1907 &sc->ppsinfo.assert_timestamp); 1908 } 1909 1910 #ifdef PPS_SYNC 1911 if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) 1912 hardpps(&tv, tv.tv_usec); 1913 #endif 1914 sc->ppsinfo.assert_sequence++; 1915 sc->ppsinfo.current_mode = sc->ppsparam.mode; 1916 1917 } else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) { 1918 /* XXX nanotime() */ 1919 microtime(&tv); 1920 TIMEVAL_TO_TIMESPEC(&tv, 1921 &sc->ppsinfo.clear_timestamp); 1922 if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { 1923 timespecadd(&sc->ppsinfo.clear_timestamp, 1924 &sc->ppsparam.clear_offset, 1925 &sc->ppsinfo.clear_timestamp); 1926 } 1927 1928 #ifdef PPS_SYNC 1929 if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) 1930 hardpps(&tv, tv.tv_usec); 1931 #endif 1932 sc->ppsinfo.clear_sequence++; 1933 sc->ppsinfo.current_mode = sc->ppsparam.mode; 1934 } 1935 } 1936 1937 /* 1938 * Process normal status changes 1939 */ 1940 if (ISSET(delta, sc->sc_msr_mask)) { 1941 SET(sc->sc_msr_delta, delta); 1942 1943 /* 1944 * Stop output immediately if we lose the output 1945 * flow control signal or carrier detect. 1946 */ 1947 if (ISSET(~msr, sc->sc_msr_mask)) { 1948 sc->sc_tbc = 0; 1949 sc->sc_heldtbc = 0; 1950 #ifdef PLCOM_DEBUG 1951 if (plcom_debug) 1952 plcomstatus(sc, "plcomintr "); 1953 #endif 1954 } 1955 1956 sc->sc_st_check = 1; 1957 } 1958 1959 /* 1960 * Done handling any receive interrupts. See if data 1961 * can be * transmitted as well. Schedule tx done 1962 * event if no data left * and tty was marked busy. 1963 */ 1964 if (ISSET(iir, IIR_TIS)) { 1965 /* 1966 * If we've delayed a parameter change, do it 1967 * now, and restart * output. 1968 */ 1969 if (sc->sc_heldchange) { 1970 plcom_loadchannelregs(sc); 1971 sc->sc_heldchange = 0; 1972 sc->sc_tbc = sc->sc_heldtbc; 1973 sc->sc_heldtbc = 0; 1974 } 1975 1976 /* 1977 * Output the next chunk of the contiguous 1978 * buffer, if any. 1979 */ 1980 if (sc->sc_tbc > 0) { 1981 int n; 1982 1983 n = sc->sc_tbc; 1984 if (n > sc->sc_fifolen) 1985 n = sc->sc_fifolen; 1986 bus_space_write_multi_1(iot, ioh, plcom_dr, 1987 sc->sc_tba, n); 1988 sc->sc_tbc -= n; 1989 sc->sc_tba += n; 1990 } else { 1991 /* 1992 * Disable transmit plcompletion 1993 * interrupts if necessary. 1994 */ 1995 if (ISSET(sc->sc_cr, CR_TIE)) { 1996 CLR(sc->sc_cr, CR_TIE); 1997 bus_space_write_1(iot, ioh, plcom_cr, 1998 sc->sc_cr); 1999 } 2000 if (sc->sc_tx_busy) { 2001 sc->sc_tx_busy = 0; 2002 sc->sc_tx_done = 1; 2003 } 2004 } 2005 } 2006 } while (ISSET((iir = bus_space_read_1(iot, ioh, plcom_iir)), 2007 IIR_IMASK)); 2008 2009 PLCOM_UNLOCK(sc); 2010 2011 /* Wake up the poller. */ 2012 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 2013 softintr_schedule(sc->sc_si); 2014 #else 2015 #ifndef __NO_SOFT_SERIAL_INTERRUPT 2016 setsoftserial(); 2017 #else 2018 if (!plcom_softintr_scheduled) { 2019 plcom_softintr_scheduled = 1; 2020 callout_reset(&plcomsoft_callout, 1, plcomsoft, NULL); 2021 } 2022 #endif 2023 #endif 2024 2025 #if NRND > 0 && defined(RND_COM) 2026 rnd_add_uint32(&sc->rnd_source, iir | rsr); 2027 #endif 2028 2029 return 1; 2030 } 2031 2032 /* 2033 * The following functions are polled getc and putc routines, shared 2034 * by the console and kgdb glue. 2035 * 2036 * The read-ahead code is so that you can detect pending in-band 2037 * cn_magic in polled mode while doing output rather than having to 2038 * wait until the kernel decides it needs input. 2039 */ 2040 2041 #define MAX_READAHEAD 20 2042 static int plcom_readahead[MAX_READAHEAD]; 2043 static int plcom_readaheadcount = 0; 2044 2045 int 2046 plcom_common_getc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh) 2047 { 2048 int s = splserial(); 2049 u_char stat, c; 2050 2051 /* got a character from reading things earlier */ 2052 if (plcom_readaheadcount > 0) { 2053 int i; 2054 2055 c = plcom_readahead[0]; 2056 for (i = 1; i < plcom_readaheadcount; i++) { 2057 plcom_readahead[i-1] = plcom_readahead[i]; 2058 } 2059 plcom_readaheadcount--; 2060 splx(s); 2061 return c; 2062 } 2063 2064 /* block until a character becomes available */ 2065 while (ISSET(stat = bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE)) 2066 ; 2067 2068 c = bus_space_read_1(iot, ioh, plcom_dr); 2069 stat = bus_space_read_1(iot, ioh, plcom_iir); 2070 { 2071 int cn_trapped = 0; /* unused */ 2072 #ifdef DDB 2073 extern int db_active; 2074 if (!db_active) 2075 #endif 2076 cn_check_magic(dev, c, plcom_cnm_state); 2077 } 2078 splx(s); 2079 return c; 2080 } 2081 2082 void 2083 plcom_common_putc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh, 2084 int c) 2085 { 2086 int s = splserial(); 2087 int timo; 2088 2089 int cin, stat; 2090 if (plcom_readaheadcount < MAX_READAHEAD 2091 && !ISSET(stat = bus_space_read_1(iot, ioh, plcom_fr), FR_RXFE)) { 2092 int cn_trapped = 0; 2093 cin = bus_space_read_1(iot, ioh, plcom_dr); 2094 stat = bus_space_read_1(iot, ioh, plcom_iir); 2095 cn_check_magic(dev, cin, plcom_cnm_state); 2096 plcom_readahead[plcom_readaheadcount++] = cin; 2097 } 2098 2099 /* wait for any pending transmission to finish */ 2100 timo = 150000; 2101 while (!ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_TXFE) && --timo) 2102 continue; 2103 2104 bus_space_write_1(iot, ioh, plcom_dr, c); 2105 PLCOM_BARRIER(iot, ioh, BR | BW); 2106 2107 /* wait for this transmission to complete */ 2108 timo = 1500000; 2109 while (!ISSET(bus_space_read_1(iot, ioh, plcom_fr), FR_TXFE) && --timo) 2110 continue; 2111 2112 splx(s); 2113 } 2114 2115 /* 2116 * Initialize UART for use as console or KGDB line. 2117 */ 2118 int 2119 plcominit(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency, 2120 tcflag_t cflag, bus_space_handle_t *iohp) 2121 { 2122 bus_space_handle_t ioh; 2123 2124 if (bus_space_map(iot, iobase, PLCOM_UART_SIZE, 0, &ioh)) 2125 return ENOMEM; /* ??? */ 2126 2127 rate = plcomspeed(rate, frequency); 2128 bus_space_write_1(iot, ioh, plcom_cr, 0); 2129 bus_space_write_1(iot, ioh, plcom_dlbl, rate); 2130 bus_space_write_1(iot, ioh, plcom_dlbh, rate >> 8); 2131 bus_space_write_1(iot, ioh, plcom_lcr, cflag2lcr(cflag) | LCR_FEN); 2132 bus_space_write_1(iot, ioh, plcom_cr, CR_UARTEN); 2133 2134 #if 0 2135 /* Ought to do something like this, but we have no sc to 2136 dereference. */ 2137 sc->sc_set_mcr(sc->sc_set_mcr_arg, sc->sc_dev.dv_unit, 2138 MCR_DTR | MCR_RTS); 2139 #endif 2140 2141 *iohp = ioh; 2142 return 0; 2143 } 2144 2145 /* 2146 * Following are all routines needed for PLCOM to act as console 2147 */ 2148 struct consdev plcomcons = { 2149 NULL, NULL, plcomcngetc, plcomcnputc, plcomcnpollc, NULL, 2150 NODEV, CN_NORMAL 2151 }; 2152 2153 2154 int 2155 plcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency, 2156 tcflag_t cflag, int unit) 2157 { 2158 int res; 2159 2160 res = plcominit(iot, iobase, rate, frequency, cflag, &plcomconsioh); 2161 if (res) 2162 return res; 2163 2164 cn_tab = &plcomcons; 2165 cn_init_magic(&plcom_cnm_state); 2166 cn_set_magic("\047\001"); /* default magic is BREAK */ 2167 2168 plcomconstag = iot; 2169 plcomconsunit = unit; 2170 plcomconsrate = rate; 2171 plcomconscflag = cflag; 2172 2173 return 0; 2174 } 2175 2176 void 2177 plcomcndetach(void) 2178 { 2179 bus_space_unmap(plcomconstag, plcomconsioh, PLCOM_UART_SIZE); 2180 plcomconstag = NULL; 2181 2182 cn_tab = NULL; 2183 } 2184 2185 int 2186 plcomcngetc(dev_t dev) 2187 { 2188 return plcom_common_getc(dev, plcomconstag, plcomconsioh); 2189 } 2190 2191 /* 2192 * Console kernel output character routine. 2193 */ 2194 void 2195 plcomcnputc(dev_t dev, int c) 2196 { 2197 plcom_common_putc(dev, plcomconstag, plcomconsioh, c); 2198 } 2199 2200 void 2201 plcomcnpollc(dev_t dev, int on) 2202 { 2203 2204 } 2205 2206 #ifdef KGDB 2207 int 2208 plcom_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate, 2209 int frequency, tcflag_t cflag, int unit) 2210 { 2211 int res; 2212 2213 if (iot == plcomconstag && iobase == plcomconsunit) 2214 return EBUSY; /* cannot share with console */ 2215 2216 res = plcominit(iot, iobase, rate, frequency, cflag, &plcom_kgdb_ioh); 2217 if (res) 2218 return res; 2219 2220 kgdb_attach(plcom_kgdb_getc, plcom_kgdb_putc, NULL); 2221 kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 2222 2223 plcom_kgdb_iot = iot; 2224 plcom_kgdb_unit = unit; 2225 2226 return 0; 2227 } 2228 2229 /* ARGSUSED */ 2230 int 2231 plcom_kgdb_getc(void *arg) 2232 { 2233 return plcom_common_getc(NODEV, plcom_kgdb_iot, plcom_kgdb_ioh); 2234 } 2235 2236 /* ARGSUSED */ 2237 void 2238 plcom_kgdb_putc(void *arg, int c) 2239 { 2240 plcom_common_putc(NODEV, plcom_kgdb_iot, plcom_kgdb_ioh, c); 2241 } 2242 #endif /* KGDB */ 2243 2244 /* helper function to identify the plcom ports used by 2245 console or KGDB (and not yet autoconf attached) */ 2246 int 2247 plcom_is_console(bus_space_tag_t iot, int unit, 2248 bus_space_handle_t *ioh) 2249 { 2250 bus_space_handle_t help; 2251 2252 if (!plcomconsattached && 2253 iot == plcomconstag && unit == plcomconsunit) 2254 help = plcomconsioh; 2255 #ifdef KGDB 2256 else if (!plcom_kgdb_attached && 2257 iot == plcom_kgdb_iot && unit == plcom_kgdb_unit) 2258 help = plcom_kgdb_ioh; 2259 #endif 2260 else 2261 return 0; 2262 2263 if (ioh) 2264 *ioh = help; 2265 return 1; 2266 } 2267