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