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