1 1.36 riastrad /* $NetBSD: epcom.c,v 1.36 2022/10/26 23:38:06 riastradh Exp $ */ 2 1.1 joff /* 3 1.1 joff * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc. 4 1.1 joff * All rights reserved. 5 1.1 joff * 6 1.1 joff * This code is derived from software contributed to The NetBSD Foundation 7 1.1 joff * by Jesse Off 8 1.1 joff * 9 1.1 joff * This code is derived from software contributed to The NetBSD Foundation 10 1.1 joff * by Ichiro FUKUHARA and Naoto Shimazaki. 11 1.1 joff * 12 1.1 joff * This code is derived from software contributed to The NetBSD Foundation 13 1.1 joff * by IWAMOTO Toshihiro. 14 1.1 joff * 15 1.1 joff * This code is derived from software contributed to The NetBSD Foundation 16 1.1 joff * by Charles M. Hannum. 17 1.1 joff * 18 1.1 joff * Redistribution and use in source and binary forms, with or without 19 1.1 joff * modification, are permitted provided that the following conditions 20 1.1 joff * are met: 21 1.1 joff * 1. Redistributions of source code must retain the above copyright 22 1.1 joff * notice, this list of conditions and the following disclaimer. 23 1.1 joff * 2. Redistributions in binary form must reproduce the above copyright 24 1.1 joff * notice, this list of conditions and the following disclaimer in the 25 1.1 joff * documentation and/or other materials provided with the distribution. 26 1.1 joff * 27 1.1 joff * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 1.1 joff * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 1.1 joff * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 1.1 joff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 1.1 joff * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 1.1 joff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 1.1 joff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 1.1 joff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 1.1 joff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 1.1 joff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 1.1 joff * POSSIBILITY OF SUCH DAMAGE. 38 1.1 joff */ 39 1.1 joff 40 1.1 joff /* 41 1.1 joff * Copyright (c) 1991 The Regents of the University of California. 42 1.1 joff * All rights reserved. 43 1.1 joff * 44 1.1 joff * Redistribution and use in source and binary forms, with or without 45 1.1 joff * modification, are permitted provided that the following conditions 46 1.1 joff * are met: 47 1.1 joff * 1. Redistributions of source code must retain the above copyright 48 1.1 joff * notice, this list of conditions and the following disclaimer. 49 1.1 joff * 2. Redistributions in binary form must reproduce the above copyright 50 1.1 joff * notice, this list of conditions and the following disclaimer in the 51 1.1 joff * documentation and/or other materials provided with the distribution. 52 1.1 joff * 3. Neither the name of the University nor the names of its contributors 53 1.1 joff * may be used to endorse or promote products derived from this software 54 1.1 joff * without specific prior written permission. 55 1.1 joff * 56 1.1 joff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 1.1 joff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 1.1 joff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 1.1 joff * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 1.1 joff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 1.1 joff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 1.1 joff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 1.1 joff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 1.1 joff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 1.1 joff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 1.1 joff * SUCH DAMAGE. 67 1.1 joff * 68 1.1 joff * @(#)com.c 7.5 (Berkeley) 5/16/91 69 1.1 joff */ 70 1.1 joff 71 1.1 joff /* 72 1.1 joff * TODO: hardware flow control 73 1.1 joff */ 74 1.1 joff 75 1.1 joff #include <sys/cdefs.h> 76 1.36 riastrad __KERNEL_RCSID(0, "$NetBSD: epcom.c,v 1.36 2022/10/26 23:38:06 riastradh Exp $"); 77 1.1 joff 78 1.1 joff #include "opt_kgdb.h" 79 1.1 joff #include "epcom.h" 80 1.1 joff 81 1.22 tls #ifdef RND_COM 82 1.30 riastrad #include <sys/rndsource.h> 83 1.1 joff #endif 84 1.1 joff 85 1.1 joff /* 86 1.1 joff * Override cnmagic(9) macro before including <sys/systm.h>. 87 1.1 joff * We need to know if cn_check_magic triggered debugger, so set a flag. 88 1.1 joff * Callers of cn_check_magic must declare int cn_trapped = 0; 89 1.1 joff * XXX: this is *ugly*! 90 1.1 joff */ 91 1.1 joff #define cn_trap() \ 92 1.1 joff do { \ 93 1.1 joff console_debugger(); \ 94 1.1 joff cn_trapped = 1; \ 95 1.1 joff } while (/* CONSTCOND */ 0) 96 1.1 joff 97 1.1 joff 98 1.1 joff #include <sys/param.h> 99 1.1 joff #include <sys/systm.h> 100 1.1 joff #include <sys/types.h> 101 1.1 joff #include <sys/conf.h> 102 1.1 joff #include <sys/file.h> 103 1.1 joff #include <sys/device.h> 104 1.1 joff #include <sys/kernel.h> 105 1.32 thorpej #include <sys/kmem.h> 106 1.1 joff #include <sys/tty.h> 107 1.1 joff #include <sys/uio.h> 108 1.1 joff #include <sys/vnode.h> 109 1.10 elad #include <sys/kauth.h> 110 1.1 joff 111 1.1 joff #include <machine/intr.h> 112 1.21 dyoung #include <sys/bus.h> 113 1.1 joff 114 1.36 riastrad #include <ddb/db_active.h> 115 1.36 riastrad 116 1.1 joff #include <arm/ep93xx/epcomreg.h> 117 1.1 joff #include <arm/ep93xx/epcomvar.h> 118 1.1 joff #include <arm/ep93xx/ep93xxreg.h> 119 1.1 joff #include <arm/ep93xx/ep93xxvar.h> 120 1.1 joff 121 1.1 joff #include <dev/cons.h> 122 1.1 joff 123 1.1 joff static int epcomparam(struct tty *, struct termios *); 124 1.1 joff static void epcomstart(struct tty *); 125 1.1 joff static int epcomhwiflow(struct tty *, int); 126 1.1 joff 127 1.1 joff static u_int cflag2lcrhi(tcflag_t); 128 1.1 joff static void epcom_iflush(struct epcom_softc *); 129 1.1 joff static void epcom_set(struct epcom_softc *); 130 1.1 joff 131 1.1 joff int epcomcngetc(dev_t); 132 1.1 joff void epcomcnputc(dev_t, int); 133 1.1 joff void epcomcnpollc(dev_t, int); 134 1.1 joff 135 1.1 joff static void epcomsoft(void* arg); 136 1.1 joff inline static void epcom_txsoft(struct epcom_softc *, struct tty *); 137 1.1 joff inline static void epcom_rxsoft(struct epcom_softc *, struct tty *); 138 1.1 joff 139 1.1 joff void epcomcnprobe(struct consdev *); 140 1.1 joff void epcomcninit(struct consdev *); 141 1.1 joff 142 1.1 joff static struct epcom_cons_softc { 143 1.1 joff bus_space_tag_t sc_iot; 144 1.1 joff bus_space_handle_t sc_ioh; 145 1.1 joff bus_addr_t sc_hwbase; 146 1.1 joff int sc_ospeed; 147 1.1 joff tcflag_t sc_cflag; 148 1.1 joff } epcomcn_sc; 149 1.1 joff 150 1.34 skrll static int epcom_common_getc(struct epcom_cons_softc *, dev_t); 151 1.34 skrll static void epcom_common_putc(struct epcom_cons_softc *, int); 152 1.34 skrll static void epcominit(struct epcom_cons_softc *, bus_space_tag_t, 153 1.34 skrll bus_addr_t, bus_space_handle_t, int, tcflag_t); 154 1.34 skrll 155 1.1 joff static struct cnm_state epcom_cnm_state; 156 1.1 joff 157 1.1 joff extern struct cfdriver epcom_cd; 158 1.1 joff 159 1.1 joff dev_type_open(epcomopen); 160 1.1 joff dev_type_close(epcomclose); 161 1.1 joff dev_type_read(epcomread); 162 1.1 joff dev_type_write(epcomwrite); 163 1.1 joff dev_type_ioctl(epcomioctl); 164 1.1 joff dev_type_stop(epcomstop); 165 1.1 joff dev_type_tty(epcomtty); 166 1.1 joff dev_type_poll(epcompoll); 167 1.1 joff 168 1.1 joff const struct cdevsw epcom_cdevsw = { 169 1.26 dholland .d_open = epcomopen, 170 1.26 dholland .d_close = epcomclose, 171 1.26 dholland .d_read = epcomread, 172 1.26 dholland .d_write = epcomwrite, 173 1.26 dholland .d_ioctl = epcomioctl, 174 1.26 dholland .d_stop = epcomstop, 175 1.26 dholland .d_tty = epcomtty, 176 1.26 dholland .d_poll = epcompoll, 177 1.26 dholland .d_mmap = nommap, 178 1.26 dholland .d_kqfilter = ttykqfilter, 179 1.27 dholland .d_discard = nodiscard, 180 1.26 dholland .d_flag = D_TTY 181 1.1 joff }; 182 1.1 joff 183 1.1 joff struct consdev epcomcons = { 184 1.1 joff NULL, NULL, epcomcngetc, epcomcnputc, epcomcnpollc, NULL, 185 1.1 joff NULL, NULL, NODEV, CN_NORMAL 186 1.1 joff }; 187 1.1 joff 188 1.34 skrll #if defined(KGDB) 189 1.34 skrll #include <sys/kgdb.h> 190 1.34 skrll 191 1.34 skrll static int epcom_kgdb_getc(void *); 192 1.34 skrll static void epcom_kgdb_putc(void *, int); 193 1.34 skrll 194 1.34 skrll /* 195 1.34 skrll * Reuse the console softc structure because 196 1.34 skrll * we'll be reusing the console I/O code. 197 1.34 skrll */ 198 1.34 skrll static struct epcom_cons_softc kgdb_sc; 199 1.34 skrll #endif 200 1.34 skrll 201 1.1 joff #ifndef DEFAULT_COMSPEED 202 1.1 joff #define DEFAULT_COMSPEED 115200 203 1.1 joff #endif 204 1.1 joff 205 1.29 christos #define COMUNIT(x) TTUNIT(x) 206 1.29 christos #define COMDIALOUT(x) TTDIALOUT(x) 207 1.1 joff 208 1.1 joff #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \ 209 1.23 chs device_is_active((sc)->sc_dev)) 210 1.1 joff 211 1.1 joff void 212 1.6 christos epcom_attach_subr(struct epcom_softc *sc) 213 1.1 joff { 214 1.1 joff struct tty *tp; 215 1.1 joff 216 1.1 joff if (sc->sc_iot == epcomcn_sc.sc_iot 217 1.1 joff && sc->sc_hwbase == epcomcn_sc.sc_hwbase) { 218 1.1 joff sc->sc_lcrlo = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) & 0xff; 219 1.1 joff sc->sc_lcrmid = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) >> 8; 220 1.1 joff 221 1.1 joff /* Make sure the console is always "hardwired". */ 222 1.1 joff delay(10000); /* wait for output to finish */ 223 1.1 joff SET(sc->sc_hwflags, COM_HW_CONSOLE); 224 1.1 joff SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); 225 1.1 joff } 226 1.1 joff 227 1.20 rmind tp = tty_alloc(); 228 1.1 joff tp->t_oproc = epcomstart; 229 1.1 joff tp->t_param = epcomparam; 230 1.1 joff tp->t_hwiflow = epcomhwiflow; 231 1.1 joff 232 1.1 joff sc->sc_tty = tp; 233 1.32 thorpej sc->sc_rbuf = kmem_alloc(EPCOM_RING_SIZE << 1, KM_SLEEP); 234 1.1 joff sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 235 1.1 joff sc->sc_rbavail = EPCOM_RING_SIZE; 236 1.1 joff sc->sc_ebuf = sc->sc_rbuf + (EPCOM_RING_SIZE << 1); 237 1.1 joff sc->sc_tbc = 0; 238 1.1 joff 239 1.1 joff sc->sc_lcrlo = EPCOMSPEED2BRD(DEFAULT_COMSPEED) & 0xff; 240 1.1 joff sc->sc_lcrmid = EPCOMSPEED2BRD(DEFAULT_COMSPEED) >> 8; 241 1.1 joff sc->sc_lcrhi = cflag2lcrhi(CS8); /* 8N1 */ 242 1.1 joff 243 1.1 joff tty_attach(tp); 244 1.1 joff 245 1.1 joff if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 246 1.1 joff int maj; 247 1.1 joff 248 1.1 joff /* locate the major number */ 249 1.1 joff maj = cdevsw_lookup_major(&epcom_cdevsw); 250 1.1 joff 251 1.23 chs cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); 252 1.1 joff 253 1.23 chs aprint_normal("%s: console\n", device_xname(sc->sc_dev)); 254 1.1 joff } 255 1.1 joff 256 1.34 skrll #ifdef KGDB 257 1.34 skrll /* 258 1.34 skrll * Allow kgdb to "take over" this port. If this is 259 1.34 skrll * the kgdb device, it has exclusive use. 260 1.34 skrll */ 261 1.34 skrll if (sc->sc_iot == kgdb_sc.sc_iot && 262 1.34 skrll sc->sc_hwbase == kgdb_sc.sc_hwbase) { 263 1.34 skrll SET(sc->sc_hwflags, COM_HW_KGDB); 264 1.35 riastrad device_printf(sc->sc_dev, "kgdb\n"); 265 1.34 skrll } 266 1.34 skrll #endif 267 1.34 skrll 268 1.16 matt sc->sc_si = softint_establish(SOFTINT_SERIAL, epcomsoft, sc); 269 1.1 joff 270 1.22 tls #ifdef RND_COM 271 1.23 chs rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 272 1.28 tls RND_TYPE_TTY, RND_FLAG_DEFAULT); 273 1.1 joff #endif 274 1.1 joff 275 1.1 joff /* if there are no enable/disable functions, assume the device 276 1.1 joff is always enabled */ 277 1.1 joff if (!sc->enable) 278 1.1 joff sc->enabled = 1; 279 1.1 joff 280 1.1 joff /* XXX configure register */ 281 1.1 joff /* xxx_config(sc) */ 282 1.1 joff 283 1.1 joff SET(sc->sc_hwflags, COM_HW_DEV_OK); 284 1.1 joff } 285 1.1 joff 286 1.1 joff static int 287 1.6 christos epcomparam(struct tty *tp, struct termios *t) 288 1.1 joff { 289 1.1 joff struct epcom_softc *sc 290 1.18 cegger = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 291 1.1 joff int s; 292 1.1 joff 293 1.1 joff if (COM_ISALIVE(sc) == 0) 294 1.1 joff return (EIO); 295 1.1 joff 296 1.1 joff if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 297 1.1 joff return (EINVAL); 298 1.1 joff 299 1.1 joff /* 300 1.1 joff * For the console, always force CLOCAL and !HUPCL, so that the port 301 1.1 joff * is always active. 302 1.1 joff */ 303 1.1 joff if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || 304 1.1 joff ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 305 1.1 joff SET(t->c_cflag, CLOCAL); 306 1.1 joff CLR(t->c_cflag, HUPCL); 307 1.1 joff } 308 1.1 joff 309 1.1 joff /* 310 1.1 joff * If there were no changes, don't do anything. This avoids dropping 311 1.1 joff * input and improves performance when all we did was frob things like 312 1.1 joff * VMIN and VTIME. 313 1.1 joff */ 314 1.1 joff if (tp->t_ospeed == t->c_ospeed && 315 1.1 joff tp->t_cflag == t->c_cflag) 316 1.1 joff return (0); 317 1.1 joff 318 1.1 joff s = splserial(); 319 1.1 joff 320 1.1 joff sc->sc_lcrhi = cflag2lcrhi(t->c_cflag); 321 1.1 joff sc->sc_lcrlo = EPCOMSPEED2BRD(t->c_ospeed) & 0xff; 322 1.1 joff sc->sc_lcrmid = EPCOMSPEED2BRD(t->c_ospeed) >> 8; 323 1.33 skrll 324 1.1 joff /* And copy to tty. */ 325 1.1 joff tp->t_ispeed = 0; 326 1.1 joff tp->t_ospeed = t->c_ospeed; 327 1.1 joff tp->t_cflag = t->c_cflag; 328 1.2 joff epcom_set(sc); 329 1.1 joff 330 1.1 joff splx(s); 331 1.1 joff 332 1.1 joff /* 333 1.1 joff * Update the tty layer's idea of the carrier bit. 334 1.1 joff * We tell tty the carrier is always on. 335 1.1 joff */ 336 1.1 joff (void) (*tp->t_linesw->l_modem)(tp, 1); 337 1.1 joff 338 1.1 joff #ifdef COM_DEBUG 339 1.1 joff if (com_debug) 340 1.1 joff comstatus(sc, "comparam "); 341 1.1 joff #endif 342 1.1 joff 343 1.1 joff if (!ISSET(t->c_cflag, CHWFLOW)) { 344 1.1 joff if (sc->sc_tx_stopped) { 345 1.1 joff sc->sc_tx_stopped = 0; 346 1.1 joff epcomstart(tp); 347 1.1 joff } 348 1.1 joff } 349 1.1 joff 350 1.1 joff return (0); 351 1.1 joff } 352 1.1 joff 353 1.1 joff static int 354 1.6 christos epcomhwiflow(struct tty *tp, int block) 355 1.1 joff { 356 1.1 joff return (0); 357 1.1 joff } 358 1.1 joff 359 1.1 joff static void 360 1.1 joff epcom_filltx(struct epcom_softc *sc) 361 1.1 joff { 362 1.1 joff bus_space_tag_t iot = sc->sc_iot; 363 1.1 joff bus_space_handle_t ioh = sc->sc_ioh; 364 1.1 joff int n; 365 1.1 joff 366 1.1 joff n = 0; 367 1.1 joff while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) == 0) { 368 1.1 joff if (n >= sc->sc_tbc) 369 1.1 joff break; 370 1.1 joff bus_space_write_4(iot, ioh, EPCOM_Data, 371 1.1 joff 0xff & *(sc->sc_tba + n)); 372 1.1 joff n++; 373 1.1 joff } 374 1.1 joff sc->sc_tbc -= n; 375 1.1 joff sc->sc_tba += n; 376 1.1 joff } 377 1.1 joff 378 1.1 joff static void 379 1.6 christos epcomstart(struct tty *tp) 380 1.1 joff { 381 1.1 joff struct epcom_softc *sc 382 1.18 cegger = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 383 1.1 joff int s; 384 1.1 joff 385 1.1 joff if (COM_ISALIVE(sc) == 0) 386 1.1 joff return; 387 1.1 joff 388 1.1 joff s = spltty(); 389 1.1 joff if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 390 1.1 joff goto out; 391 1.1 joff if (sc->sc_tx_stopped) 392 1.1 joff goto out; 393 1.15 ad if (!ttypull(tp)) 394 1.15 ad goto out; 395 1.1 joff 396 1.1 joff /* Grab the first contiguous region of buffer space. */ 397 1.1 joff { 398 1.1 joff u_char *tba; 399 1.1 joff int tbc; 400 1.1 joff 401 1.1 joff tba = tp->t_outq.c_cf; 402 1.1 joff tbc = ndqb(&tp->t_outq, 0); 403 1.1 joff 404 1.1 joff (void)splserial(); 405 1.1 joff 406 1.1 joff sc->sc_tba = tba; 407 1.1 joff sc->sc_tbc = tbc; 408 1.1 joff } 409 1.1 joff 410 1.1 joff SET(tp->t_state, TS_BUSY); 411 1.1 joff sc->sc_tx_busy = 1; 412 1.1 joff 413 1.2 joff /* Output the first chunk of the contiguous buffer. */ 414 1.2 joff epcom_filltx(sc); 415 1.2 joff 416 1.1 joff if (!ISSET(sc->sc_ctrl, Ctrl_TIE)) { 417 1.1 joff SET(sc->sc_ctrl, Ctrl_TIE); 418 1.1 joff epcom_set(sc); 419 1.1 joff } 420 1.1 joff 421 1.1 joff out: 422 1.1 joff splx(s); 423 1.1 joff return; 424 1.1 joff } 425 1.1 joff 426 1.1 joff static void 427 1.1 joff epcom_break(struct epcom_softc *sc, int onoff) 428 1.1 joff { 429 1.1 joff if (onoff) 430 1.1 joff SET(sc->sc_lcrhi, LinCtrlHigh_BRK); 431 1.1 joff else 432 1.1 joff CLR(sc->sc_lcrhi, LinCtrlHigh_BRK); 433 1.2 joff epcom_set(sc); 434 1.1 joff } 435 1.1 joff 436 1.1 joff static void 437 1.1 joff epcom_shutdown(struct epcom_softc *sc) 438 1.1 joff { 439 1.1 joff int s; 440 1.1 joff 441 1.1 joff s = splserial(); 442 1.1 joff 443 1.1 joff /* Turn off interrupts. */ 444 1.1 joff CLR(sc->sc_ctrl, (Ctrl_TIE|Ctrl_RTIE|Ctrl_RIE)); 445 1.1 joff 446 1.1 joff /* Clear any break condition set with TIOCSBRK. */ 447 1.1 joff epcom_break(sc, 0); 448 1.1 joff epcom_set(sc); 449 1.1 joff 450 1.1 joff if (sc->disable) { 451 1.1 joff #ifdef DIAGNOSTIC 452 1.1 joff if (!sc->enabled) 453 1.1 joff panic("epcom_shutdown: not enabled?"); 454 1.1 joff #endif 455 1.1 joff (*sc->disable)(sc); 456 1.1 joff sc->enabled = 0; 457 1.1 joff } 458 1.1 joff splx(s); 459 1.1 joff } 460 1.1 joff 461 1.1 joff int 462 1.6 christos epcomopen(dev_t dev, int flag, int mode, struct lwp *l) 463 1.1 joff { 464 1.1 joff struct epcom_softc *sc; 465 1.1 joff struct tty *tp; 466 1.1 joff int s, s2; 467 1.1 joff int error; 468 1.1 joff 469 1.18 cegger sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 470 1.1 joff if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) || 471 1.1 joff sc->sc_rbuf == NULL) 472 1.1 joff return (ENXIO); 473 1.1 joff 474 1.23 chs if (!device_is_active(sc->sc_dev)) 475 1.1 joff return (ENXIO); 476 1.1 joff 477 1.1 joff #ifdef KGDB 478 1.1 joff /* 479 1.1 joff * If this is the kgdb port, no other use is permitted. 480 1.1 joff */ 481 1.1 joff if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) 482 1.1 joff return (EBUSY); 483 1.1 joff #endif 484 1.1 joff 485 1.1 joff tp = sc->sc_tty; 486 1.1 joff 487 1.12 elad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 488 1.1 joff return (EBUSY); 489 1.1 joff 490 1.1 joff s = spltty(); 491 1.1 joff 492 1.1 joff /* 493 1.1 joff * Do the following iff this is a first open. 494 1.1 joff */ 495 1.1 joff if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 496 1.1 joff struct termios t; 497 1.1 joff 498 1.1 joff tp->t_dev = dev; 499 1.1 joff 500 1.1 joff s2 = splserial(); 501 1.1 joff 502 1.1 joff if (sc->enable) { 503 1.1 joff if ((*sc->enable)(sc)) { 504 1.1 joff splx(s2); 505 1.1 joff splx(s); 506 1.1 joff printf("%s: device enable failed\n", 507 1.23 chs device_xname(sc->sc_dev)); 508 1.1 joff return (EIO); 509 1.1 joff } 510 1.1 joff sc->enabled = 1; 511 1.1 joff #if 0 512 1.1 joff /* XXXXXXXXXXXXXXX */ 513 1.1 joff com_config(sc); 514 1.1 joff #endif 515 1.1 joff } 516 1.1 joff 517 1.1 joff /* Turn on interrupts. */ 518 1.1 joff SET(sc->sc_ctrl, (Ctrl_UARTE|Ctrl_RIE|Ctrl_RTIE)); 519 1.1 joff epcom_set(sc); 520 1.1 joff 521 1.1 joff #if 0 522 1.1 joff /* Fetch the current modem control status, needed later. */ 523 1.1 joff sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr); 524 1.1 joff 525 1.1 joff /* Clear PPS capture state on first open. */ 526 1.1 joff sc->sc_ppsmask = 0; 527 1.1 joff sc->ppsparam.mode = 0; 528 1.1 joff #endif 529 1.1 joff 530 1.1 joff splx(s2); 531 1.1 joff 532 1.1 joff /* 533 1.1 joff * Initialize the termios status to the defaults. Add in the 534 1.1 joff * sticky bits from TIOCSFLAGS. 535 1.1 joff */ 536 1.1 joff t.c_ispeed = 0; 537 1.1 joff if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { 538 1.1 joff t.c_ospeed = epcomcn_sc.sc_ospeed; 539 1.1 joff t.c_cflag = epcomcn_sc.sc_cflag; 540 1.1 joff } else { 541 1.1 joff t.c_ospeed = TTYDEF_SPEED; 542 1.1 joff t.c_cflag = TTYDEF_CFLAG; 543 1.1 joff } 544 1.1 joff if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 545 1.1 joff SET(t.c_cflag, CLOCAL); 546 1.1 joff if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 547 1.1 joff SET(t.c_cflag, CRTSCTS); 548 1.1 joff if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 549 1.1 joff SET(t.c_cflag, MDMBUF); 550 1.1 joff /* Make sure epcomparam() will do something. */ 551 1.1 joff tp->t_ospeed = 0; 552 1.1 joff (void) epcomparam(tp, &t); 553 1.1 joff tp->t_iflag = TTYDEF_IFLAG; 554 1.1 joff tp->t_oflag = TTYDEF_OFLAG; 555 1.1 joff tp->t_lflag = TTYDEF_LFLAG; 556 1.1 joff ttychars(tp); 557 1.1 joff ttsetwater(tp); 558 1.1 joff 559 1.1 joff s2 = splserial(); 560 1.1 joff 561 1.1 joff /* Clear the input ring, and unblock. */ 562 1.1 joff sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; 563 1.1 joff sc->sc_rbavail = EPCOM_RING_SIZE; 564 1.1 joff epcom_iflush(sc); 565 1.1 joff CLR(sc->sc_rx_flags, RX_ANY_BLOCK); 566 1.1 joff 567 1.1 joff #ifdef COM_DEBUG 568 1.1 joff if (epcom_debug) 569 1.1 joff comstatus(sc, "epcomopen "); 570 1.1 joff #endif 571 1.1 joff 572 1.1 joff splx(s2); 573 1.1 joff } 574 1.33 skrll 575 1.1 joff splx(s); 576 1.1 joff 577 1.1 joff error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 578 1.1 joff if (error) 579 1.1 joff goto bad; 580 1.1 joff 581 1.1 joff error = (*tp->t_linesw->l_open)(dev, tp); 582 1.1 joff if (error) 583 1.1 joff goto bad; 584 1.1 joff 585 1.1 joff return (0); 586 1.1 joff 587 1.1 joff bad: 588 1.1 joff if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 589 1.1 joff /* 590 1.1 joff * We failed to open the device, and nobody else had it opened. 591 1.1 joff * Clean up the state as appropriate. 592 1.1 joff */ 593 1.1 joff epcom_shutdown(sc); 594 1.1 joff } 595 1.1 joff 596 1.1 joff return (error); 597 1.1 joff } 598 1.1 joff 599 1.1 joff int 600 1.6 christos epcomclose(dev_t dev, int flag, int mode, struct lwp *l) 601 1.1 joff { 602 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 603 1.1 joff struct tty *tp = sc->sc_tty; 604 1.1 joff 605 1.1 joff /* XXX This is for cons.c. */ 606 1.1 joff if (!ISSET(tp->t_state, TS_ISOPEN)) 607 1.1 joff return (0); 608 1.1 joff 609 1.1 joff (*tp->t_linesw->l_close)(tp, flag); 610 1.1 joff ttyclose(tp); 611 1.1 joff 612 1.1 joff if (COM_ISALIVE(sc) == 0) 613 1.1 joff return (0); 614 1.1 joff 615 1.1 joff if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 616 1.1 joff /* 617 1.1 joff * Although we got a last close, the device may still be in 618 1.1 joff * use; e.g. if this was the dialout node, and there are still 619 1.1 joff * processes waiting for carrier on the non-dialout node. 620 1.1 joff */ 621 1.1 joff epcom_shutdown(sc); 622 1.1 joff } 623 1.1 joff 624 1.1 joff return (0); 625 1.1 joff } 626 1.1 joff 627 1.1 joff int 628 1.6 christos epcomread(dev_t dev, struct uio *uio, int flag) 629 1.1 joff { 630 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 631 1.1 joff struct tty *tp = sc->sc_tty; 632 1.1 joff 633 1.1 joff if (COM_ISALIVE(sc) == 0) 634 1.1 joff return (EIO); 635 1.33 skrll 636 1.1 joff return ((*tp->t_linesw->l_read)(tp, uio, flag)); 637 1.1 joff } 638 1.1 joff 639 1.1 joff int 640 1.6 christos epcomwrite(dev_t dev, struct uio *uio, int flag) 641 1.1 joff { 642 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 643 1.1 joff struct tty *tp = sc->sc_tty; 644 1.1 joff 645 1.1 joff if (COM_ISALIVE(sc) == 0) 646 1.1 joff return (EIO); 647 1.33 skrll 648 1.1 joff return ((*tp->t_linesw->l_write)(tp, uio, flag)); 649 1.1 joff } 650 1.1 joff 651 1.1 joff int 652 1.6 christos epcompoll(dev_t dev, int events, struct lwp *l) 653 1.1 joff { 654 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 655 1.1 joff struct tty *tp = sc->sc_tty; 656 1.1 joff 657 1.1 joff if (COM_ISALIVE(sc) == 0) 658 1.1 joff return (EIO); 659 1.33 skrll 660 1.6 christos return ((*tp->t_linesw->l_poll)(tp, events, l)); 661 1.1 joff } 662 1.1 joff 663 1.1 joff struct tty * 664 1.6 christos epcomtty(dev_t dev) 665 1.1 joff { 666 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 667 1.1 joff struct tty *tp = sc->sc_tty; 668 1.1 joff 669 1.1 joff return (tp); 670 1.1 joff } 671 1.1 joff 672 1.1 joff int 673 1.14 christos epcomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 674 1.1 joff { 675 1.18 cegger struct epcom_softc *sc = device_lookup_private(&epcom_cd, COMUNIT(dev)); 676 1.1 joff struct tty *tp = sc->sc_tty; 677 1.1 joff int error; 678 1.1 joff int s; 679 1.1 joff 680 1.1 joff if (COM_ISALIVE(sc) == 0) 681 1.1 joff return (EIO); 682 1.1 joff 683 1.6 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 684 1.1 joff if (error != EPASSTHROUGH) 685 1.1 joff return (error); 686 1.1 joff 687 1.6 christos error = ttioctl(tp, cmd, data, flag, l); 688 1.1 joff if (error != EPASSTHROUGH) 689 1.1 joff return (error); 690 1.1 joff 691 1.1 joff error = 0; 692 1.1 joff 693 1.1 joff s = splserial(); 694 1.1 joff 695 1.1 joff switch (cmd) { 696 1.1 joff case TIOCSBRK: 697 1.1 joff epcom_break(sc, 1); 698 1.1 joff break; 699 1.1 joff 700 1.1 joff case TIOCCBRK: 701 1.1 joff epcom_break(sc, 0); 702 1.1 joff break; 703 1.1 joff 704 1.1 joff case TIOCGFLAGS: 705 1.1 joff *(int *)data = sc->sc_swflags; 706 1.1 joff break; 707 1.1 joff 708 1.1 joff case TIOCSFLAGS: 709 1.13 elad error = kauth_authorize_device_tty(l->l_cred, 710 1.33 skrll KAUTH_DEVICE_TTY_PRIVSET, tp); 711 1.1 joff if (error) 712 1.1 joff break; 713 1.1 joff sc->sc_swflags = *(int *)data; 714 1.1 joff break; 715 1.1 joff 716 1.1 joff default: 717 1.1 joff error = EPASSTHROUGH; 718 1.1 joff break; 719 1.1 joff } 720 1.1 joff 721 1.1 joff splx(s); 722 1.1 joff 723 1.1 joff return (error); 724 1.1 joff } 725 1.1 joff 726 1.1 joff /* 727 1.1 joff * Stop output on a line. 728 1.1 joff */ 729 1.1 joff void 730 1.6 christos epcomstop(struct tty *tp, int flag) 731 1.1 joff { 732 1.1 joff struct epcom_softc *sc 733 1.18 cegger = device_lookup_private(&epcom_cd, COMUNIT(tp->t_dev)); 734 1.1 joff int s; 735 1.1 joff 736 1.1 joff s = splserial(); 737 1.1 joff if (ISSET(tp->t_state, TS_BUSY)) { 738 1.1 joff /* Stop transmitting at the next chunk. */ 739 1.1 joff sc->sc_tbc = 0; 740 1.1 joff if (!ISSET(tp->t_state, TS_TTSTOP)) 741 1.1 joff SET(tp->t_state, TS_FLUSH); 742 1.1 joff } 743 1.1 joff splx(s); 744 1.1 joff } 745 1.1 joff 746 1.1 joff static u_int 747 1.6 christos cflag2lcrhi(tcflag_t cflag) 748 1.1 joff { 749 1.1 joff u_int lcrhi; 750 1.1 joff 751 1.1 joff switch (cflag & CSIZE) { 752 1.1 joff case CS7: 753 1.1 joff lcrhi = 0x40; 754 1.1 joff break; 755 1.1 joff case CS6: 756 1.1 joff lcrhi = 0x20; 757 1.1 joff break; 758 1.1 joff case CS8: 759 1.1 joff default: 760 1.1 joff lcrhi = 0x60; 761 1.1 joff break; 762 1.1 joff } 763 1.1 joff lcrhi |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0; 764 1.1 joff lcrhi |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS; 765 1.1 joff lcrhi |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0; 766 1.1 joff lcrhi |= LinCtrlHigh_FEN; /* FIFO always enabled */ 767 1.33 skrll 768 1.1 joff return (lcrhi); 769 1.1 joff } 770 1.1 joff 771 1.1 joff static void 772 1.6 christos epcom_iflush(struct epcom_softc *sc) 773 1.1 joff { 774 1.1 joff bus_space_tag_t iot = sc->sc_iot; 775 1.1 joff bus_space_handle_t ioh = sc->sc_ioh; 776 1.1 joff #ifdef DIAGNOSTIC 777 1.1 joff int reg; 778 1.1 joff #endif 779 1.1 joff int timo; 780 1.1 joff 781 1.1 joff #ifdef DIAGNOSTIC 782 1.1 joff reg = 0xffff; 783 1.1 joff #endif 784 1.1 joff timo = 50000; 785 1.1 joff /* flush any pending I/O */ 786 1.1 joff while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) == 0 787 1.1 joff && --timo) 788 1.1 joff #ifdef DIAGNOSTIC 789 1.1 joff reg = 790 1.1 joff #else 791 1.1 joff (void) 792 1.1 joff #endif 793 1.1 joff bus_space_read_4(iot, ioh, EPCOM_Data); 794 1.1 joff #ifdef DIAGNOSTIC 795 1.1 joff if (!timo) 796 1.23 chs printf("%s: com_iflush timeout %02x\n", device_xname(sc->sc_dev), 797 1.1 joff reg); 798 1.1 joff #endif 799 1.1 joff } 800 1.1 joff 801 1.1 joff static void 802 1.1 joff epcom_set(struct epcom_softc *sc) 803 1.1 joff { 804 1.1 joff bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlLow, 805 1.1 joff sc->sc_lcrlo); 806 1.1 joff bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlMid, 807 1.1 joff sc->sc_lcrmid); 808 1.1 joff bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlHigh, 809 1.1 joff sc->sc_lcrhi); 810 1.1 joff bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_Ctrl, 811 1.1 joff sc->sc_ctrl); 812 1.1 joff } 813 1.1 joff 814 1.1 joff int 815 1.6 christos epcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh, 816 1.6 christos int ospeed, tcflag_t cflag) 817 1.1 joff { 818 1.1 joff cn_tab = &epcomcons; 819 1.1 joff cn_init_magic(&epcom_cnm_state); 820 1.1 joff cn_set_magic("\047\001"); 821 1.1 joff 822 1.34 skrll epcominit(&epcomcn_sc, iot, iobase, ioh, ospeed, cflag); 823 1.1 joff 824 1.1 joff return (0); 825 1.1 joff } 826 1.1 joff 827 1.1 joff void 828 1.6 christos epcomcnprobe(struct consdev *cp) 829 1.1 joff { 830 1.1 joff cp->cn_pri = CN_REMOTE; 831 1.1 joff } 832 1.1 joff 833 1.1 joff void 834 1.6 christos epcomcnpollc(dev_t dev, int on) 835 1.1 joff { 836 1.1 joff } 837 1.1 joff 838 1.1 joff void 839 1.6 christos epcomcnputc(dev_t dev, int c) 840 1.1 joff { 841 1.34 skrll epcom_common_putc(&epcomcn_sc, c); 842 1.34 skrll } 843 1.34 skrll 844 1.34 skrll static void 845 1.34 skrll epcom_common_putc(struct epcom_cons_softc *sc, int c) 846 1.34 skrll { 847 1.1 joff int s; 848 1.34 skrll bus_space_tag_t iot = sc->sc_iot; 849 1.34 skrll bus_space_handle_t ioh = sc->sc_ioh; 850 1.1 joff 851 1.1 joff s = splserial(); 852 1.1 joff 853 1.1 joff while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) != 0) 854 1.1 joff ; 855 1.1 joff 856 1.1 joff bus_space_write_4(iot, ioh, EPCOM_Data, c); 857 1.1 joff 858 1.1 joff #ifdef DEBUG 859 1.1 joff if (c == '\r') { 860 1.1 joff while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFE) == 0) 861 1.1 joff ; 862 1.1 joff } 863 1.1 joff #endif 864 1.1 joff 865 1.1 joff splx(s); 866 1.1 joff } 867 1.1 joff 868 1.1 joff int 869 1.6 christos epcomcngetc(dev_t dev) 870 1.1 joff { 871 1.34 skrll return epcom_common_getc (&epcomcn_sc, dev); 872 1.34 skrll } 873 1.34 skrll 874 1.34 skrll static int 875 1.34 skrll epcom_common_getc(struct epcom_cons_softc *sc, dev_t dev) 876 1.34 skrll { 877 1.1 joff int c, sts; 878 1.1 joff int s; 879 1.34 skrll bus_space_tag_t iot = sc->sc_iot; 880 1.34 skrll bus_space_handle_t ioh = sc->sc_ioh; 881 1.1 joff 882 1.1 joff s = splserial(); 883 1.1 joff 884 1.36 riastrad while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) != 0) 885 1.36 riastrad continue; 886 1.1 joff 887 1.1 joff c = bus_space_read_4(iot, ioh, EPCOM_Data); 888 1.1 joff sts = bus_space_read_4(iot, ioh, EPCOM_RXSts); 889 1.36 riastrad if (ISSET(sts, RXSts_BE)) 890 1.36 riastrad c = CNC_BREAK; 891 1.36 riastrad if (!db_active) { 892 1.25 skrll int cn_trapped __unused = 0; 893 1.1 joff 894 1.1 joff cn_check_magic(dev, c, epcom_cnm_state); 895 1.1 joff } 896 1.1 joff c &= 0xff; 897 1.1 joff splx(s); 898 1.1 joff 899 1.1 joff return (c); 900 1.1 joff } 901 1.1 joff 902 1.1 joff inline static void 903 1.6 christos epcom_txsoft(struct epcom_softc *sc, struct tty *tp) 904 1.1 joff { 905 1.1 joff CLR(tp->t_state, TS_BUSY); 906 1.1 joff if (ISSET(tp->t_state, TS_FLUSH)) 907 1.1 joff CLR(tp->t_state, TS_FLUSH); 908 1.1 joff else 909 1.1 joff ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); 910 1.1 joff (*tp->t_linesw->l_start)(tp); 911 1.1 joff } 912 1.1 joff 913 1.1 joff inline static void 914 1.6 christos epcom_rxsoft(struct epcom_softc *sc, struct tty *tp) 915 1.1 joff { 916 1.19 dsl int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 917 1.1 joff u_char *get, *end; 918 1.1 joff u_int cc, scc; 919 1.1 joff u_char sts; 920 1.1 joff int code; 921 1.1 joff int s; 922 1.1 joff 923 1.1 joff end = sc->sc_ebuf; 924 1.1 joff get = sc->sc_rbget; 925 1.1 joff scc = cc = EPCOM_RING_SIZE - sc->sc_rbavail; 926 1.1 joff #if 0 927 1.1 joff if (cc == EPCOM_RING_SIZE) { 928 1.1 joff sc->sc_floods++; 929 1.1 joff if (sc->sc_errors++ == 0) 930 1.1 joff callout_reset(&sc->sc_diag_callout, 60 * hz, 931 1.1 joff comdiag, sc); 932 1.1 joff } 933 1.1 joff #endif 934 1.1 joff while (cc) { 935 1.1 joff code = get[0]; 936 1.1 joff sts = get[1]; 937 1.1 joff if (ISSET(sts, RXSts_OE | RXSts_FE | RXSts_PE | RXSts_BE)) { 938 1.1 joff #if 0 939 1.1 joff if (ISSET(lsr, DR_ROR)) { 940 1.1 joff sc->sc_overflows++; 941 1.1 joff if (sc->sc_errors++ == 0) 942 1.1 joff callout_reset(&sc->sc_diag_callout, 943 1.1 joff 60 * hz, comdiag, sc); 944 1.1 joff } 945 1.1 joff #endif 946 1.1 joff if (ISSET(sts, (RXSts_FE|RXSts_BE))) 947 1.1 joff SET(code, TTY_FE); 948 1.1 joff if (ISSET(sts, RXSts_PE)) 949 1.1 joff SET(code, TTY_PE); 950 1.1 joff } 951 1.1 joff if ((*rint)(code, tp) == -1) { 952 1.1 joff /* 953 1.1 joff * The line discipline's buffer is out of space. 954 1.1 joff */ 955 1.1 joff if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) { 956 1.1 joff /* 957 1.1 joff * We're either not using flow control, or the 958 1.1 joff * line discipline didn't tell us to block for 959 1.1 joff * some reason. Either way, we have no way to 960 1.1 joff * know when there's more space available, so 961 1.1 joff * just drop the rest of the data. 962 1.1 joff */ 963 1.1 joff get += cc << 1; 964 1.1 joff if (get >= end) 965 1.1 joff get -= EPCOM_RING_SIZE << 1; 966 1.1 joff cc = 0; 967 1.1 joff } else { 968 1.1 joff /* 969 1.1 joff * Don't schedule any more receive processing 970 1.1 joff * until the line discipline tells us there's 971 1.1 joff * space available (through comhwiflow()). 972 1.1 joff * Leave the rest of the data in the input 973 1.1 joff * buffer. 974 1.1 joff */ 975 1.1 joff SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED); 976 1.1 joff } 977 1.1 joff break; 978 1.1 joff } 979 1.1 joff get += 2; 980 1.1 joff if (get >= end) 981 1.1 joff get = sc->sc_rbuf; 982 1.1 joff cc--; 983 1.1 joff } 984 1.1 joff 985 1.1 joff if (cc != scc) { 986 1.1 joff sc->sc_rbget = get; 987 1.1 joff s = splserial(); 988 1.33 skrll 989 1.1 joff cc = sc->sc_rbavail += scc - cc; 990 1.1 joff /* Buffers should be ok again, release possible block. */ 991 1.1 joff if (cc >= 1) { 992 1.1 joff if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 993 1.1 joff CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 994 1.1 joff SET(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 995 1.1 joff epcom_set(sc); 996 1.1 joff } 997 1.1 joff if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) { 998 1.1 joff CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED); 999 1.1 joff #if 0 1000 1.1 joff com_hwiflow(sc); 1001 1.1 joff #endif 1002 1.1 joff } 1003 1.1 joff } 1004 1.1 joff splx(s); 1005 1.1 joff } 1006 1.1 joff } 1007 1.1 joff 1008 1.1 joff static void 1009 1.1 joff epcomsoft(void* arg) 1010 1.1 joff { 1011 1.1 joff struct epcom_softc *sc = arg; 1012 1.1 joff 1013 1.1 joff if (COM_ISALIVE(sc) == 0) 1014 1.1 joff return; 1015 1.1 joff 1016 1.1 joff if (sc->sc_rx_ready) { 1017 1.1 joff sc->sc_rx_ready = 0; 1018 1.1 joff epcom_rxsoft(sc, sc->sc_tty); 1019 1.1 joff } 1020 1.1 joff if (sc->sc_tx_done) { 1021 1.1 joff sc->sc_tx_done = 0; 1022 1.1 joff epcom_txsoft(sc, sc->sc_tty); 1023 1.1 joff } 1024 1.1 joff } 1025 1.1 joff 1026 1.1 joff int 1027 1.1 joff epcomintr(void* arg) 1028 1.1 joff { 1029 1.1 joff struct epcom_softc *sc = arg; 1030 1.1 joff bus_space_tag_t iot = sc->sc_iot; 1031 1.1 joff bus_space_handle_t ioh = sc->sc_ioh; 1032 1.1 joff u_char *put, *end; 1033 1.1 joff u_int cc; 1034 1.1 joff u_int flagr; 1035 1.24 skrll uint32_t c, csts; 1036 1.1 joff 1037 1.25 skrll (void) bus_space_read_4(iot, ioh, EPCOM_IntIDIntClr); 1038 1.1 joff 1039 1.33 skrll if (COM_ISALIVE(sc) == 0) 1040 1.1 joff panic("intr on disabled epcom"); 1041 1.1 joff 1042 1.1 joff flagr = bus_space_read_4(iot, ioh, EPCOM_Flag); 1043 1.1 joff 1044 1.1 joff end = sc->sc_ebuf; 1045 1.1 joff put = sc->sc_rbput; 1046 1.1 joff cc = sc->sc_rbavail; 1047 1.1 joff 1048 1.1 joff if (!(ISSET(flagr, Flag_RXFE))) { 1049 1.1 joff if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { 1050 1.1 joff while (cc > 0) { 1051 1.1 joff if (ISSET(flagr, Flag_RXFE)) 1052 1.1 joff break; 1053 1.1 joff c = bus_space_read_4(iot, ioh, EPCOM_Data); 1054 1.1 joff csts = bus_space_read_4(iot, ioh, EPCOM_RXSts); 1055 1.1 joff if (ISSET(csts, RXSts_BE)) { 1056 1.1 joff int cn_trapped = 0; 1057 1.1 joff 1058 1.1 joff cn_check_magic(sc->sc_tty->t_dev, 1059 1.1 joff CNC_BREAK, epcom_cnm_state); 1060 1.1 joff if (cn_trapped) 1061 1.1 joff goto next; 1062 1.1 joff #if defined(KGDB) && !defined(DDB) 1063 1.1 joff if (ISSET(sc->sc_hwflags, COM_HW_KGDB)){ 1064 1.1 joff kgdb_connect(1); 1065 1.1 joff goto next; 1066 1.1 joff } 1067 1.1 joff #endif 1068 1.1 joff } else { 1069 1.1 joff int cn_trapped = 0; 1070 1.1 joff 1071 1.1 joff cn_check_magic(sc->sc_tty->t_dev, 1072 1.1 joff (c & 0xff), epcom_cnm_state); 1073 1.1 joff if (cn_trapped) 1074 1.1 joff goto next; 1075 1.1 joff } 1076 1.1 joff 1077 1.1 joff 1078 1.1 joff put[0] = c & 0xff; 1079 1.1 joff put[1] = csts & 0xf; 1080 1.1 joff put += 2; 1081 1.1 joff if (put >= end) 1082 1.1 joff put = sc->sc_rbuf; 1083 1.1 joff cc--; 1084 1.1 joff next: 1085 1.1 joff flagr = bus_space_read_4(iot, ioh, EPCOM_Flag); 1086 1.1 joff } 1087 1.1 joff 1088 1.1 joff /* 1089 1.1 joff * Current string of incoming characters ended because 1090 1.1 joff * no more data was available or we ran out of space. 1091 1.1 joff * Schedule a receive event if any data was received. 1092 1.1 joff * If we're out of space, turn off receive interrupts. 1093 1.1 joff */ 1094 1.1 joff sc->sc_rbput = put; 1095 1.1 joff sc->sc_rbavail = cc; 1096 1.1 joff if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) 1097 1.1 joff sc->sc_rx_ready = 1; 1098 1.1 joff 1099 1.1 joff /* 1100 1.1 joff * See if we are in danger of overflowing a buffer. If 1101 1.1 joff * so, use hardware flow control to ease the pressure. 1102 1.1 joff */ 1103 1.1 joff 1104 1.1 joff /* but epcom cannot. X-( */ 1105 1.1 joff 1106 1.1 joff /* 1107 1.1 joff * If we're out of space, disable receive interrupts 1108 1.1 joff * until the queue has drained a bit. 1109 1.1 joff */ 1110 1.1 joff if (!cc) { 1111 1.1 joff SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); 1112 1.1 joff CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 1113 1.1 joff epcom_set(sc); 1114 1.1 joff } 1115 1.1 joff } else { 1116 1.1 joff #ifdef DIAGNOSTIC 1117 1.1 joff panic("epcomintr: we shouldn't reach here"); 1118 1.1 joff #endif 1119 1.1 joff CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE)); 1120 1.1 joff epcom_set(sc); 1121 1.1 joff } 1122 1.1 joff } 1123 1.1 joff 1124 1.1 joff /* 1125 1.1 joff * Done handling any receive interrupts. See if data can be 1126 1.1 joff * transmitted as well. Schedule tx done event if no data left 1127 1.1 joff * and tty was marked busy. 1128 1.1 joff */ 1129 1.2 joff 1130 1.2 joff if (!ISSET(flagr, Flag_TXFF) && sc->sc_tbc > 0) { 1131 1.2 joff /* Output the next chunk of the contiguous buffer, if any. */ 1132 1.2 joff epcom_filltx(sc); 1133 1.2 joff } else { 1134 1.2 joff /* Disable transmit completion interrupts if necessary. */ 1135 1.2 joff if (ISSET(sc->sc_ctrl, Ctrl_TIE)) { 1136 1.2 joff CLR(sc->sc_ctrl, Ctrl_TIE); 1137 1.1 joff epcom_set(sc); 1138 1.1 joff } 1139 1.2 joff if (sc->sc_tx_busy) { 1140 1.2 joff sc->sc_tx_busy = 0; 1141 1.2 joff sc->sc_tx_done = 1; 1142 1.1 joff } 1143 1.1 joff } 1144 1.1 joff 1145 1.1 joff /* Wake up the poller. */ 1146 1.16 matt softint_schedule(sc->sc_si); 1147 1.1 joff 1148 1.1 joff #if 0 /* XXX: broken */ 1149 1.22 tls #ifdef RND_COM 1150 1.1 joff rnd_add_uint32(&sc->rnd_source, intr ^ flagr); 1151 1.1 joff #endif 1152 1.1 joff #endif 1153 1.1 joff return (1); 1154 1.1 joff } 1155 1.34 skrll 1156 1.34 skrll #ifdef KGDB 1157 1.34 skrll int 1158 1.34 skrll epcom_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate, 1159 1.34 skrll tcflag_t cflag) 1160 1.34 skrll { 1161 1.34 skrll bus_space_handle_t ioh; 1162 1.34 skrll 1163 1.34 skrll if (iot == epcomcn_sc.sc_iot && iobase == epcomcn_sc.sc_hwbase) { 1164 1.34 skrll #if !defined(DDB) 1165 1.34 skrll return EBUSY; /* cannot share with console */ 1166 1.34 skrll #else 1167 1.34 skrll /* 1168 1.34 skrll * XXX I have no intention of ever testing and code path 1169 1.34 skrll * implied by getting here 1170 1.34 skrll */ 1171 1.34 skrll kgdb_sc = epcomcn_sc; 1172 1.34 skrll #endif 1173 1.34 skrll } else { 1174 1.34 skrll bus_space_map(iot, iobase, EP93XX_APB_UART_SIZE, 0, &ioh); 1175 1.34 skrll epcominit(&kgdb_sc, iot, iobase, ioh, rate, cflag); 1176 1.34 skrll } 1177 1.34 skrll 1178 1.34 skrll kgdb_attach(epcom_kgdb_getc, epcom_kgdb_putc, &kgdb_sc); 1179 1.34 skrll kgdb_dev = 123; /* unneeded, only to satisfy some tests */ 1180 1.34 skrll 1181 1.34 skrll return 0; 1182 1.34 skrll } 1183 1.34 skrll 1184 1.34 skrll static int 1185 1.34 skrll epcom_kgdb_getc (void *sc) 1186 1.34 skrll { 1187 1.34 skrll return epcom_common_getc(sc, NODEV); 1188 1.34 skrll } 1189 1.34 skrll 1190 1.34 skrll static void 1191 1.34 skrll epcom_kgdb_putc (void *sc, int c) 1192 1.34 skrll { 1193 1.34 skrll epcom_common_putc(sc, c); 1194 1.34 skrll } 1195 1.34 skrll #endif /* KGDB */ 1196 1.34 skrll 1197 1.34 skrll /* 1198 1.34 skrll * Common code used for initialisation of the console or KGDB connection 1199 1.34 skrll */ 1200 1.34 skrll static void 1201 1.34 skrll epcominit(struct epcom_cons_softc *sc, bus_space_tag_t iot, 1202 1.34 skrll bus_addr_t iobase, bus_space_handle_t ioh, int rate, tcflag_t cflag) 1203 1.34 skrll { 1204 1.34 skrll u_int lcrlo, lcrmid, lcrhi, ctrl, pwrcnt; 1205 1.34 skrll bus_space_handle_t syscon_ioh; 1206 1.34 skrll 1207 1.34 skrll sc->sc_iot = iot; 1208 1.34 skrll sc->sc_ioh = ioh; 1209 1.34 skrll sc->sc_hwbase = iobase; 1210 1.34 skrll sc->sc_ospeed = rate; 1211 1.34 skrll sc->sc_cflag = cflag; 1212 1.34 skrll 1213 1.34 skrll lcrhi = cflag2lcrhi(cflag); 1214 1.34 skrll lcrlo = EPCOMSPEED2BRD(rate) & 0xff; 1215 1.34 skrll lcrmid = EPCOMSPEED2BRD(rate) >> 8; 1216 1.34 skrll ctrl = Ctrl_UARTE; 1217 1.34 skrll 1218 1.34 skrll /* Make sure the UARTs are clocked at the system default rate */ 1219 1.34 skrll bus_space_map(iot, EP93XX_APB_HWBASE + EP93XX_APB_SYSCON, 1220 1.34 skrll EP93XX_APB_SYSCON_SIZE, 0, &syscon_ioh); 1221 1.34 skrll pwrcnt = bus_space_read_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt); 1222 1.34 skrll pwrcnt &= ~(PwrCnt_UARTBAUD); 1223 1.34 skrll bus_space_write_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt, pwrcnt); 1224 1.34 skrll bus_space_unmap(iot, syscon_ioh, EP93XX_APB_SYSCON_SIZE); 1225 1.34 skrll 1226 1.34 skrll bus_space_write_4(iot, ioh, EPCOM_LinCtrlLow, lcrlo); 1227 1.34 skrll bus_space_write_4(iot, ioh, EPCOM_LinCtrlMid, lcrmid); 1228 1.34 skrll bus_space_write_4(iot, ioh, EPCOM_LinCtrlHigh, lcrhi); 1229 1.34 skrll bus_space_write_4(iot, ioh, EPCOM_Ctrl, ctrl); 1230 1.34 skrll } 1231