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