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