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