1 1.33 andvar /* $NetBSD: cd18xx.c,v 1.33 2024/06/02 13:28:44 andvar Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 1998, 2001 Matthew R. Green 5 1.1 mrg * All rights reserved. 6 1.1 mrg * 7 1.1 mrg * Redistribution and use in source and binary forms, with or without 8 1.1 mrg * modification, are permitted provided that the following conditions 9 1.1 mrg * are met: 10 1.1 mrg * 1. Redistributions of source code must retain the above copyright 11 1.1 mrg * notice, this list of conditions and the following disclaimer. 12 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mrg * notice, this list of conditions and the following disclaimer in the 14 1.1 mrg * documentation and/or other materials provided with the distribution. 15 1.1 mrg * 16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 mrg * SUCH DAMAGE. 27 1.1 mrg */ 28 1.1 mrg 29 1.1 mrg /*- 30 1.1 mrg * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 31 1.1 mrg * All rights reserved. 32 1.1 mrg * 33 1.1 mrg * This code is derived from software contributed to The NetBSD Foundation 34 1.1 mrg * by Charles M. Hannum. 35 1.1 mrg * 36 1.1 mrg * Redistribution and use in source and binary forms, with or without 37 1.1 mrg * modification, are permitted provided that the following conditions 38 1.1 mrg * are met: 39 1.1 mrg * 1. Redistributions of source code must retain the above copyright 40 1.1 mrg * notice, this list of conditions and the following disclaimer. 41 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 mrg * notice, this list of conditions and the following disclaimer in the 43 1.1 mrg * documentation and/or other materials provided with the distribution. 44 1.1 mrg * 45 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46 1.1 mrg * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47 1.1 mrg * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 1.1 mrg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49 1.1 mrg * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 1.1 mrg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51 1.1 mrg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52 1.1 mrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53 1.1 mrg * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 1.1 mrg * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55 1.1 mrg * POSSIBILITY OF SUCH DAMAGE. 56 1.1 mrg */ 57 1.1 mrg 58 1.1 mrg /* 59 1.1 mrg * Copyright (c) 1991 The Regents of the University of California. 60 1.1 mrg * All rights reserved. 61 1.1 mrg * 62 1.1 mrg * Redistribution and use in source and binary forms, with or without 63 1.1 mrg * modification, are permitted provided that the following conditions 64 1.1 mrg * are met: 65 1.1 mrg * 1. Redistributions of source code must retain the above copyright 66 1.1 mrg * notice, this list of conditions and the following disclaimer. 67 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 68 1.1 mrg * notice, this list of conditions and the following disclaimer in the 69 1.1 mrg * documentation and/or other materials provided with the distribution. 70 1.9 agc * 3. Neither the name of the University nor the names of its contributors 71 1.1 mrg * may be used to endorse or promote products derived from this software 72 1.1 mrg * without specific prior written permission. 73 1.1 mrg * 74 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 75 1.1 mrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 76 1.1 mrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 77 1.1 mrg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 78 1.1 mrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 79 1.1 mrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 80 1.1 mrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 81 1.1 mrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 82 1.1 mrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 83 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 84 1.1 mrg * SUCH DAMAGE. 85 1.1 mrg * 86 1.1 mrg * @(#)com.c 7.5 (Berkeley) 5/16/91 87 1.1 mrg */ 88 1.1 mrg 89 1.1 mrg /* 90 1.1 mrg * cirrus logic CL-CD180/CD1864/CD1865 driver, based in (large) parts on 91 1.1 mrg * the com and z8530 drivers. thanks charles. 92 1.1 mrg */ 93 1.2 lukem 94 1.2 lukem #include <sys/cdefs.h> 95 1.33 andvar __KERNEL_RCSID(0, "$NetBSD: cd18xx.c,v 1.33 2024/06/02 13:28:44 andvar Exp $"); 96 1.1 mrg 97 1.1 mrg #include <sys/param.h> 98 1.1 mrg #include <sys/conf.h> 99 1.1 mrg #include <sys/device.h> 100 1.1 mrg #include <sys/systm.h> 101 1.1 mrg #include <sys/malloc.h> 102 1.1 mrg #include <sys/proc.h> 103 1.1 mrg #include <sys/kernel.h> 104 1.1 mrg #include <sys/tty.h> 105 1.1 mrg #include <sys/fcntl.h> 106 1.14 elad #include <sys/kauth.h> 107 1.20 ad #include <sys/intr.h> 108 1.1 mrg 109 1.21 ad #include <sys/bus.h> 110 1.1 mrg 111 1.1 mrg #include <dev/ic/cd18xxvar.h> 112 1.1 mrg #include <dev/ic/cd18xxreg.h> 113 1.1 mrg 114 1.1 mrg #include "ioconf.h" 115 1.1 mrg 116 1.1 mrg /* 117 1.1 mrg * some helpers 118 1.1 mrg */ 119 1.1 mrg 120 1.1 mrg static void cdtty_attach(struct cd18xx_softc *, int); 121 1.1 mrg 122 1.13 perry static inline void cd18xx_rint(struct cd18xx_softc *, int *); 123 1.13 perry static inline void cd18xx_tint(struct cd18xx_softc *, int *); 124 1.13 perry static inline void cd18xx_mint(struct cd18xx_softc *, int *); 125 1.1 mrg 126 1.1 mrg void cdtty_rxsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 127 1.1 mrg void cdtty_txsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 128 1.1 mrg void cdtty_stsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 129 1.1 mrg void cd18xx_softintr(void *); 130 1.1 mrg 131 1.4 gehenna dev_type_open(cdttyopen); 132 1.4 gehenna dev_type_close(cdttyclose); 133 1.4 gehenna dev_type_read(cdttyread); 134 1.4 gehenna dev_type_write(cdttywrite); 135 1.4 gehenna dev_type_ioctl(cdttyioctl); 136 1.4 gehenna dev_type_stop(cdttystop); 137 1.4 gehenna dev_type_tty(cdttytty); 138 1.4 gehenna dev_type_poll(cdttypoll); 139 1.4 gehenna 140 1.4 gehenna const struct cdevsw cdtty_cdevsw = { 141 1.30 dholland .d_open = cdttyopen, 142 1.30 dholland .d_close = cdttyclose, 143 1.30 dholland .d_read = cdttyread, 144 1.30 dholland .d_write = cdttywrite, 145 1.30 dholland .d_ioctl = cdttyioctl, 146 1.30 dholland .d_stop = cdttystop, 147 1.30 dholland .d_tty = cdttytty, 148 1.30 dholland .d_poll = cdttypoll, 149 1.30 dholland .d_mmap = nommap, 150 1.30 dholland .d_kqfilter = ttykqfilter, 151 1.31 dholland .d_discard = nodiscard, 152 1.30 dholland .d_flag = D_TTY 153 1.4 gehenna }; 154 1.1 mrg 155 1.6 mrg static void cdtty_shutdown(struct cd18xx_softc *, struct cdtty_port *); 156 1.1 mrg static void cdttystart(struct tty *); 157 1.1 mrg static int cdttyparam(struct tty *, struct termios *); 158 1.1 mrg static void cdtty_break(struct cd18xx_softc *, struct cdtty_port *, int); 159 1.1 mrg static void cdtty_modem(struct cd18xx_softc *, struct cdtty_port *, int); 160 1.1 mrg static int cdttyhwiflow(struct tty *, int); 161 1.1 mrg static void cdtty_hwiflow(struct cd18xx_softc *, struct cdtty_port *); 162 1.1 mrg 163 1.1 mrg static void cdtty_loadchannelregs(struct cd18xx_softc *, 164 1.1 mrg struct cdtty_port *); 165 1.1 mrg 166 1.1 mrg /* default read buffer size */ 167 1.1 mrg u_int cdtty_rbuf_size = CDTTY_RING_SIZE; 168 1.1 mrg 169 1.1 mrg /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 170 1.1 mrg u_int cdtty_rbuf_hiwat = (CDTTY_RING_SIZE * 1) / 4; 171 1.1 mrg u_int cdtty_rbuf_lowat = (CDTTY_RING_SIZE * 3) / 4; 172 1.1 mrg 173 1.1 mrg #define CD18XXDEBUG 174 1.1 mrg #ifdef CD18XXDEBUG 175 1.1 mrg #define CDD_INFO 0x0001 176 1.1 mrg #define CDD_INTR 0x0002 177 1.1 mrg int cd18xx_debug = CDD_INTR|CDD_INFO; 178 1.1 mrg # define DPRINTF(l, x) if (cd18xx_debug & l) printf x 179 1.1 mrg #else 180 1.1 mrg # define DPRINTF(l, x) /* nothing */ 181 1.1 mrg #endif 182 1.1 mrg 183 1.1 mrg /* Known supported revisions. */ 184 1.1 mrg struct cd18xx_revs { 185 1.29 chs u_char revision; 186 1.29 chs u_char onehundred_pin; 187 1.29 chs const char *name; 188 1.1 mrg } cd18xx_revs[] = { 189 1.1 mrg { CD180_GFRCR_REV_B, 0, "CL-CD180 rev. B" }, 190 1.1 mrg { CD180_GFRCR_REV_C, 0, "CL-CD180 rev. C" }, 191 1.1 mrg { CD1864_GFRCR_REVISION_A, 1, "CL-CD1864 rev. A" }, 192 1.1 mrg { CD1865_GFRCR_REVISION_A, 1, "CL-CD1865 rev. A" }, 193 1.1 mrg { CD1865_GFRCR_REVISION_B, 1, "CL-CD1865 rev. B" }, 194 1.1 mrg { CD1865_GFRCR_REVISION_C, 1, "CL-CD1865 rev. C" }, 195 1.1 mrg { 0, 0, 0 } 196 1.1 mrg }; 197 1.1 mrg 198 1.1 mrg /* wait for the CCR to go to zero */ 199 1.13 perry static inline int cd18xx_wait_ccr(struct cd18xx_softc *); 200 1.13 perry static inline int 201 1.27 dsl cd18xx_wait_ccr(struct cd18xx_softc *sc) 202 1.1 mrg { 203 1.1 mrg int i = 100000; 204 1.1 mrg 205 1.1 mrg while (--i && 206 1.7 mrg bus_space_read_1(sc->sc_tag, sc->sc_handle, CD18xx_CCR) != 0) 207 1.7 mrg ; 208 1.1 mrg return (i == 0); 209 1.1 mrg } 210 1.1 mrg 211 1.1 mrg /* 212 1.1 mrg * device attach routine, high-end portion 213 1.1 mrg */ 214 1.10 perry void 215 1.27 dsl cd18xx_attach(struct cd18xx_softc *sc) 216 1.1 mrg { 217 1.1 mrg static int chip_id_next = 1; 218 1.1 mrg int onehundred_pin, revision, i, port; 219 1.1 mrg 220 1.1 mrg /* read and print the revision */ 221 1.1 mrg revision = cd18xx_read(sc, CD18xx_GFRCR); 222 1.1 mrg onehundred_pin = ISSET(cd18xx_read(sc, CD18xx_SRCR),CD18xx_SRCR_PKGTYP); 223 1.1 mrg for (i = 0; cd18xx_revs[i].name; i++) 224 1.1 mrg if (revision == cd18xx_revs[i].revision || 225 1.1 mrg onehundred_pin == cd18xx_revs[i].onehundred_pin) { 226 1.1 mrg printf(": %s", cd18xx_revs[i].name); 227 1.1 mrg break; 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg if (cd18xx_revs[i].name == NULL) { 231 1.29 chs aprint_error_dev(sc->sc_dev, "unknown revision, bailing.\n"); 232 1.1 mrg return; 233 1.1 mrg } 234 1.1 mrg 235 1.1 mrg /* prepare for reset */ 236 1.1 mrg cd18xx_set_car(sc, 0); 237 1.1 mrg cd18xx_write(sc, CD18xx_GSVR, CD18xx_GSVR_CLEAR); 238 1.1 mrg 239 1.1 mrg /* wait for CCR to go to zero */ 240 1.1 mrg if (cd18xx_wait_ccr(sc)) { 241 1.1 mrg printf("cd18xx_attach: reset change command timed out\n"); 242 1.1 mrg return; 243 1.1 mrg } 244 1.1 mrg 245 1.1 mrg /* full reset of all channels */ 246 1.10 perry cd18xx_write(sc, CD18xx_CCR, 247 1.1 mrg CD18xx_CCR_RESET|CD18xx_CCR_RESET_HARD); 248 1.1 mrg 249 1.1 mrg /* loop until the GSVR is ready */ 250 1.1 mrg i = 100000; 251 1.1 mrg while (--i && cd18xx_read(sc, CD18xx_GSVR) == CD18xx_GSVR_READY) 252 1.1 mrg ; 253 1.1 mrg if (i == 0) { 254 1.23 cegger aprint_normal("\n"); 255 1.29 chs aprint_error_dev(sc->sc_dev, "did not reset!\n"); 256 1.1 mrg return; 257 1.1 mrg } 258 1.1 mrg 259 1.1 mrg /* write the chip_id */ 260 1.1 mrg sc->sc_chip_id = chip_id_next++; 261 1.1 mrg #ifdef DIAGNOSTIC 262 1.1 mrg if (sc->sc_chip_id > 31) 263 1.1 mrg panic("more than 31 cd18xx's? help."); 264 1.1 mrg #endif 265 1.1 mrg cd18xx_write(sc, CD18xx_GSVR, CD18xx_GSVR_SETID(sc)); 266 1.1 mrg 267 1.32 andvar /* rx/tx/modem service match vectors, initialised by higher level */ 268 1.1 mrg cd18xx_write(sc, CD18xx_MSMR, sc->sc_msmr | 0x80); 269 1.1 mrg cd18xx_write(sc, CD18xx_TSMR, sc->sc_tsmr | 0x80); 270 1.1 mrg cd18xx_write(sc, CD18xx_RSMR, sc->sc_rsmr | 0x80); 271 1.1 mrg 272 1.1 mrg printf(", gsvr %x msmr %x tsmr %x rsmr %x", 273 1.1 mrg cd18xx_read(sc, CD18xx_GSVR), 274 1.1 mrg cd18xx_read(sc, CD18xx_MSMR), 275 1.1 mrg cd18xx_read(sc, CD18xx_TSMR), 276 1.1 mrg cd18xx_read(sc, CD18xx_RSMR)); 277 1.1 mrg 278 1.1 mrg /* prescale registers */ 279 1.1 mrg sc->sc_pprh = 0xf0; 280 1.1 mrg sc->sc_pprl = 0; 281 1.1 mrg cd18xx_write(sc, CD18xx_PPRH, sc->sc_pprh); 282 1.1 mrg cd18xx_write(sc, CD18xx_PPRL, sc->sc_pprl); 283 1.1 mrg 284 1.1 mrg /* establish our soft interrupt. */ 285 1.20 ad sc->sc_si = softint_establish(SOFTINT_SERIAL, cd18xx_softintr, sc); 286 1.1 mrg 287 1.1 mrg printf(", 8 ports ready (chip id %d)\n", sc->sc_chip_id); 288 1.1 mrg 289 1.1 mrg /* 290 1.10 perry * finally, we loop over all 8 channels initialising them 291 1.1 mrg */ 292 1.1 mrg for (port = 0; port < 8; port++) 293 1.1 mrg cdtty_attach(sc, port); 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg /* tty portion of the code */ 297 1.1 mrg 298 1.1 mrg /* 299 1.1 mrg * tty portion attach routine 300 1.1 mrg */ 301 1.10 perry void 302 1.27 dsl cdtty_attach(struct cd18xx_softc *sc, int port) 303 1.1 mrg { 304 1.1 mrg struct cdtty_port *p = &sc->sc_ports[port]; 305 1.1 mrg 306 1.1 mrg /* load CAR with channel number */ 307 1.1 mrg cd18xx_set_car(sc, port); 308 1.1 mrg 309 1.1 mrg /* wait for CCR to go to zero */ 310 1.1 mrg if (cd18xx_wait_ccr(sc)) { 311 1.1 mrg printf("cd18xx_attach: change command timed out setting " 312 1.29 chs "CAR for port %d\n", port); 313 1.1 mrg return; 314 1.1 mrg } 315 1.1 mrg 316 1.1 mrg /* set the RPTR to (arbitrary) 8 */ 317 1.1 mrg cd18xx_write(sc, CD18xx_RTPR, 8); 318 1.1 mrg 319 1.1 mrg /* reset the modem signal value register */ 320 1.1 mrg sc->sc_ports[port].p_msvr = CD18xx_MSVR_RESET; 321 1.1 mrg 322 1.1 mrg /* zero the service request enable register */ 323 1.1 mrg cd18xx_write(sc, CD18xx_SRER, 0); 324 1.1 mrg 325 1.1 mrg /* enable the transmitter & receiver */ 326 1.1 mrg SET(p->p_chanctl, CD18xx_CCR_CHANCTL | 327 1.1 mrg CD18xx_CCR_CHANCTL_TxEN | 328 1.1 mrg CD18xx_CCR_CHANCTL_RxEN); 329 1.1 mrg 330 1.1 mrg /* XXX no console or kgdb support yet! */ 331 1.1 mrg 332 1.1 mrg /* get a tty structure */ 333 1.28 rmind p->p_tty = tty_alloc(); 334 1.1 mrg p->p_tty->t_oproc = cdttystart; 335 1.1 mrg p->p_tty->t_param = cdttyparam; 336 1.1 mrg p->p_tty->t_hwiflow = cdttyhwiflow; 337 1.1 mrg 338 1.1 mrg p->p_rbuf = malloc(cdtty_rbuf_size << 1, M_DEVBUF, M_WAITOK); 339 1.1 mrg p->p_rbput = p->p_rbget = p->p_rbuf; 340 1.1 mrg p->p_rbavail = cdtty_rbuf_size; 341 1.1 mrg if (p->p_rbuf == NULL) { 342 1.29 chs aprint_error_dev(sc->sc_dev, "unable to allocate ring buffer for tty %d\n", port); 343 1.1 mrg return; 344 1.1 mrg } 345 1.1 mrg p->p_ebuf = p->p_rbuf + (cdtty_rbuf_size << 1); 346 1.1 mrg 347 1.1 mrg tty_attach(p->p_tty); 348 1.1 mrg } 349 1.1 mrg 350 1.1 mrg /* 351 1.6 mrg * cdtty_shutdown: called when the device is last closed. 352 1.1 mrg */ 353 1.1 mrg void 354 1.27 dsl cdtty_shutdown(struct cd18xx_softc *sc, struct cdtty_port *p) 355 1.1 mrg { 356 1.1 mrg struct tty *tp = p->p_tty; 357 1.1 mrg int s; 358 1.1 mrg 359 1.1 mrg s = splserial(); 360 1.1 mrg 361 1.1 mrg /* If we were asserting flow control, then deassert it. */ 362 1.1 mrg SET(p->p_rx_flags, RX_IBUF_BLOCKED); 363 1.1 mrg cdtty_hwiflow(sc, p); 364 1.1 mrg 365 1.1 mrg /* Clear any break condition set with TIOCSBRK. */ 366 1.1 mrg cdtty_break(sc, p, 0); 367 1.1 mrg 368 1.1 mrg /* 369 1.1 mrg * Hang up if necessary. Wait a bit, so the other side has time to 370 1.1 mrg * notice even if we immediately open the port again. 371 1.1 mrg * Avoid tsleeping above splhigh(). 372 1.1 mrg */ 373 1.1 mrg if (ISSET(tp->t_cflag, HUPCL)) { 374 1.1 mrg cdtty_modem(sc, p, 0); 375 1.1 mrg splx(s); 376 1.1 mrg /* XXX tsleep will only timeout */ 377 1.1 mrg (void) tsleep(sc, TTIPRI, ttclos, hz); 378 1.1 mrg s = splserial(); 379 1.1 mrg } 380 1.1 mrg 381 1.1 mrg /* Turn off interrupts. */ 382 1.1 mrg p->p_srer = 0; 383 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 384 1.1 mrg 385 1.1 mrg splx(s); 386 1.1 mrg } 387 1.1 mrg 388 1.1 mrg /* 389 1.1 mrg * cdttyopen: open syscall for cdtty terminals.. 390 1.1 mrg */ 391 1.1 mrg int 392 1.29 chs cdttyopen(dev_t dev, int flag, int mode, struct lwp *l) 393 1.1 mrg { 394 1.1 mrg struct tty *tp; 395 1.1 mrg struct cd18xx_softc *sc; 396 1.1 mrg struct cdtty_port *port; 397 1.1 mrg int channel, instance, s, error; 398 1.1 mrg 399 1.1 mrg channel = CD18XX_CHANNEL(dev); 400 1.1 mrg instance = CD18XX_INSTANCE(dev); 401 1.1 mrg 402 1.1 mrg /* ensure instance is valid */ 403 1.1 mrg if (instance >= clcd_cd.cd_ndevs) 404 1.1 mrg return (ENXIO); 405 1.1 mrg 406 1.1 mrg /* get softc and port */ 407 1.26 cegger sc = device_lookup_private(&clcd_cd, instance); 408 1.1 mrg if (sc == NULL) 409 1.1 mrg return (ENXIO); 410 1.1 mrg port = &sc->sc_ports[channel]; 411 1.1 mrg if (port == NULL || port->p_rbuf == NULL) 412 1.1 mrg return (ENXIO); 413 1.1 mrg 414 1.1 mrg /* kgdb support? maybe later... */ 415 1.1 mrg 416 1.1 mrg tp = port->p_tty; 417 1.1 mrg 418 1.17 elad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 419 1.1 mrg return (EBUSY); 420 1.1 mrg 421 1.1 mrg s = spltty(); 422 1.1 mrg 423 1.1 mrg /* 424 1.1 mrg * Do the following iff this is a first open. 425 1.1 mrg */ 426 1.1 mrg if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 427 1.1 mrg struct termios t; 428 1.1 mrg 429 1.1 mrg /* set up things in tp as necessary */ 430 1.1 mrg tp->t_dev = dev; 431 1.1 mrg 432 1.1 mrg /* 433 1.1 mrg * Initialize the termios status to the defaults. Add in the 434 1.1 mrg * sticky bits from TIOCSFLAGS. 435 1.1 mrg */ 436 1.1 mrg t.c_ispeed = 0; 437 1.1 mrg t.c_ospeed = TTYDEF_SPEED; 438 1.1 mrg t.c_cflag = TTYDEF_CFLAG; 439 1.1 mrg 440 1.1 mrg if (ISSET(port->p_swflags, TIOCFLAG_CLOCAL)) 441 1.1 mrg SET(t.c_cflag, CLOCAL); 442 1.1 mrg if (ISSET(port->p_swflags, TIOCFLAG_CRTSCTS)) 443 1.1 mrg SET(t.c_cflag, CRTSCTS); 444 1.1 mrg if (ISSET(port->p_swflags, TIOCFLAG_CDTRCTS)) 445 1.1 mrg SET(t.c_cflag, CDTRCTS); 446 1.1 mrg if (ISSET(port->p_swflags, TIOCFLAG_MDMBUF)) 447 1.1 mrg SET(t.c_cflag, MDMBUF); 448 1.1 mrg 449 1.1 mrg /* Make sure param will see changes. */ 450 1.6 mrg tp->t_ospeed = 0; /* XXX set above ignored? */ 451 1.1 mrg (void)cdttyparam(tp, &t); 452 1.1 mrg 453 1.1 mrg tp->t_iflag = TTYDEF_IFLAG; 454 1.1 mrg tp->t_oflag = TTYDEF_OFLAG; 455 1.1 mrg tp->t_lflag = TTYDEF_LFLAG; 456 1.1 mrg ttychars(tp); 457 1.1 mrg ttsetwater(tp); 458 1.1 mrg 459 1.1 mrg (void)splserial(); 460 1.1 mrg 461 1.1 mrg /* turn on rx and modem interrupts */ 462 1.1 mrg cd18xx_set_car(sc, CD18XX_CHANNEL(dev)); 463 1.1 mrg SET(port->p_srer, CD18xx_SRER_Rx | 464 1.1 mrg CD18xx_SRER_RxSC | 465 1.1 mrg CD18xx_SRER_CD); 466 1.1 mrg cd18xx_write(sc, CD18xx_SRER, port->p_srer); 467 1.1 mrg 468 1.1 mrg /* always turn on DTR when open */ 469 1.1 mrg cdtty_modem(sc, port, 1); 470 1.1 mrg 471 1.1 mrg /* initialise ring buffer */ 472 1.1 mrg port->p_rbget = port->p_rbput = port->p_rbuf; 473 1.1 mrg port->p_rbavail = cdtty_rbuf_size; 474 1.1 mrg CLR(port->p_rx_flags, RX_ANY_BLOCK); 475 1.1 mrg cdtty_hwiflow(sc, port); 476 1.1 mrg } 477 1.1 mrg 478 1.1 mrg /* drop spl back before going into the line open */ 479 1.1 mrg splx(s); 480 1.1 mrg 481 1.1 mrg error = ttyopen(tp, CD18XX_DIALOUT(dev), ISSET(flag, O_NONBLOCK)); 482 1.1 mrg if (error == 0) 483 1.1 mrg error = (*tp->t_linesw->l_open)(dev, tp); 484 1.1 mrg 485 1.1 mrg return (error); 486 1.1 mrg } 487 1.1 mrg 488 1.1 mrg /* 489 1.1 mrg * cdttyclose: close syscall for cdtty terminals.. 490 1.1 mrg */ 491 1.1 mrg int 492 1.29 chs cdttyclose(dev_t dev, int flag, int mode, struct lwp *l) 493 1.1 mrg { 494 1.1 mrg struct cd18xx_softc *sc; 495 1.1 mrg struct cdtty_port *port; 496 1.1 mrg struct tty *tp; 497 1.1 mrg int channel, instance; 498 1.1 mrg 499 1.1 mrg channel = CD18XX_CHANNEL(dev); 500 1.1 mrg instance = CD18XX_INSTANCE(dev); 501 1.1 mrg 502 1.1 mrg /* ensure instance is valid */ 503 1.1 mrg if (instance >= clcd_cd.cd_ndevs) 504 1.1 mrg return (ENXIO); 505 1.1 mrg 506 1.1 mrg /* get softc and port */ 507 1.26 cegger sc = device_lookup_private(&clcd_cd, instance); 508 1.1 mrg if (sc == NULL) 509 1.1 mrg return (ENXIO); 510 1.1 mrg port = &sc->sc_ports[channel]; 511 1.1 mrg 512 1.1 mrg tp = port->p_tty; 513 1.1 mrg 514 1.1 mrg (*tp->t_linesw->l_close)(tp, flag); 515 1.1 mrg ttyclose(tp); 516 1.1 mrg 517 1.1 mrg if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 518 1.1 mrg /* 519 1.1 mrg * Although we got a last close, the device may still be in 520 1.1 mrg * use; e.g. if this was the dialout node, and there are still 521 1.1 mrg * processes waiting for carrier on the non-dialout node. 522 1.1 mrg */ 523 1.1 mrg cdtty_shutdown(sc, port); 524 1.1 mrg } 525 1.1 mrg 526 1.1 mrg return (0); 527 1.1 mrg } 528 1.1 mrg 529 1.1 mrg /* 530 1.1 mrg * cdttyread: read syscall for cdtty terminals.. 531 1.1 mrg */ 532 1.1 mrg int 533 1.26 cegger cdttyread(dev_t dev, struct uio *uio, int flag) 534 1.1 mrg { 535 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(dev)); 536 1.1 mrg struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 537 1.1 mrg struct tty *tp = port->p_tty; 538 1.1 mrg 539 1.1 mrg return ((*tp->t_linesw->l_read)(tp, uio, flag)); 540 1.1 mrg } 541 1.1 mrg 542 1.1 mrg /* 543 1.1 mrg * cdttywrite: write syscall for cdtty terminals.. 544 1.1 mrg */ 545 1.1 mrg int 546 1.26 cegger cdttywrite(dev_t dev, struct uio *uio, int flag) 547 1.1 mrg { 548 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(dev)); 549 1.1 mrg struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 550 1.1 mrg struct tty *tp = port->p_tty; 551 1.1 mrg 552 1.1 mrg return ((*tp->t_linesw->l_write)(tp, uio, flag)); 553 1.1 mrg } 554 1.1 mrg 555 1.1 mrg int 556 1.29 chs cdttypoll(dev_t dev, int events, struct lwp *l) 557 1.1 mrg { 558 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(dev)); 559 1.1 mrg struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 560 1.1 mrg struct tty *tp = port->p_tty; 561 1.1 mrg 562 1.29 chs return ((*tp->t_linesw->l_poll)(tp, events, l)); 563 1.1 mrg } 564 1.1 mrg 565 1.1 mrg /* 566 1.1 mrg * cdttytty: return a pointer to our (cdtty) tp. 567 1.1 mrg */ 568 1.1 mrg struct tty * 569 1.26 cegger cdttytty(dev_t dev) 570 1.1 mrg { 571 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(dev)); 572 1.1 mrg struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 573 1.1 mrg 574 1.1 mrg return (port->p_tty); 575 1.1 mrg } 576 1.1 mrg 577 1.1 mrg /* 578 1.1 mrg * cdttyioctl: ioctl syscall for cdtty terminals.. 579 1.1 mrg */ 580 1.1 mrg int 581 1.29 chs cdttyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 582 1.1 mrg { 583 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(dev)); 584 1.1 mrg struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 585 1.1 mrg struct tty *tp = port->p_tty; 586 1.1 mrg int error, s; 587 1.1 mrg 588 1.29 chs error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 589 1.3 atatat if (error != EPASSTHROUGH) 590 1.1 mrg return (error); 591 1.1 mrg 592 1.29 chs error = ttioctl(tp, cmd, data, flag, l); 593 1.3 atatat if (error != EPASSTHROUGH) 594 1.1 mrg return (error); 595 1.1 mrg 596 1.1 mrg s = splserial(); 597 1.1 mrg 598 1.1 mrg switch (cmd) { 599 1.1 mrg case TIOCSBRK: 600 1.1 mrg cdtty_break(sc, port, 1); 601 1.1 mrg break; 602 1.1 mrg 603 1.1 mrg case TIOCCBRK: 604 1.1 mrg cdtty_break(sc, port, 0); 605 1.1 mrg break; 606 1.1 mrg 607 1.1 mrg case TIOCSDTR: 608 1.1 mrg cdtty_modem(sc, port, 1); 609 1.1 mrg break; 610 1.1 mrg 611 1.1 mrg case TIOCCDTR: 612 1.1 mrg cdtty_modem(sc, port, 0); 613 1.1 mrg break; 614 1.1 mrg 615 1.1 mrg case TIOCGFLAGS: 616 1.1 mrg *(int *)data = port->p_swflags; 617 1.1 mrg break; 618 1.1 mrg 619 1.1 mrg case TIOCSFLAGS: 620 1.18 elad error = kauth_authorize_device_tty(l->l_cred, 621 1.18 elad KAUTH_DEVICE_TTY_PRIVSET, tp); 622 1.1 mrg if (error) 623 1.1 mrg return (error); 624 1.1 mrg port->p_swflags = *(int *)data; 625 1.1 mrg break; 626 1.1 mrg 627 1.1 mrg case TIOCMSET: 628 1.1 mrg case TIOCMBIS: 629 1.1 mrg case TIOCMBIC: 630 1.1 mrg case TIOCMGET: 631 1.1 mrg default: 632 1.3 atatat return (EPASSTHROUGH); 633 1.1 mrg } 634 1.1 mrg 635 1.1 mrg splx(s); 636 1.1 mrg return (0); 637 1.1 mrg } 638 1.1 mrg 639 1.1 mrg /* 640 1.1 mrg * Start or restart transmission. 641 1.1 mrg */ 642 1.1 mrg static void 643 1.26 cegger cdttystart(struct tty *tp) 644 1.1 mrg { 645 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(tp->t_dev)); 646 1.1 mrg struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 647 1.1 mrg int s; 648 1.1 mrg 649 1.1 mrg s = spltty(); 650 1.1 mrg if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 651 1.1 mrg goto out; 652 1.1 mrg if (p->p_tx_stopped) 653 1.1 mrg goto out; 654 1.1 mrg 655 1.22 ad if (!ttypull(tp)) 656 1.22 ad goto out; 657 1.1 mrg 658 1.1 mrg /* Grab the first contiguous region of buffer space. */ 659 1.1 mrg { 660 1.1 mrg u_char *tba; 661 1.1 mrg int tbc; 662 1.1 mrg 663 1.1 mrg tba = tp->t_outq.c_cf; 664 1.1 mrg tbc = ndqb(&tp->t_outq, 0); 665 1.10 perry 666 1.1 mrg (void)splserial(); 667 1.1 mrg 668 1.1 mrg p->p_tba = tba; 669 1.1 mrg p->p_tbc = tbc; 670 1.1 mrg } 671 1.1 mrg 672 1.1 mrg SET(tp->t_state, TS_BUSY); 673 1.1 mrg p->p_tx_busy = 1; 674 1.1 mrg 675 1.1 mrg /* turn on tx interrupts */ 676 1.1 mrg if ((p->p_srer & CD18xx_SRER_Tx) == 0) { 677 1.1 mrg cd18xx_set_car(sc, CD18XX_CHANNEL(tp->t_dev)); 678 1.1 mrg SET(p->p_srer, CD18xx_SRER_Tx); 679 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 680 1.1 mrg } 681 1.1 mrg 682 1.1 mrg /* 683 1.1 mrg * Now bail; we can't actually transmit bytes until we're in a 684 1.1 mrg * transmit interrupt service routine. 685 1.1 mrg */ 686 1.1 mrg out: 687 1.1 mrg splx(s); 688 1.1 mrg return; 689 1.1 mrg } 690 1.1 mrg 691 1.1 mrg /* 692 1.1 mrg * cdttystop: handing ^S or other stop signals, for a cdtty 693 1.1 mrg */ 694 1.1 mrg void 695 1.26 cegger cdttystop(struct tty *tp, int flag) 696 1.1 mrg { 697 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(tp->t_dev)); 698 1.1 mrg struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 699 1.1 mrg int s; 700 1.1 mrg 701 1.1 mrg s = splserial(); 702 1.1 mrg if (ISSET(tp->t_state, TS_BUSY)) { 703 1.1 mrg /* Stop transmitting at the next chunk. */ 704 1.1 mrg p->p_tbc = 0; 705 1.1 mrg p->p_heldtbc = 0; 706 1.1 mrg if (!ISSET(tp->t_state, TS_TTSTOP)) 707 1.1 mrg SET(tp->t_state, TS_FLUSH); 708 1.1 mrg } 709 1.1 mrg splx(s); 710 1.1 mrg } 711 1.1 mrg 712 1.1 mrg /* 713 1.1 mrg * load a channel's registers. 714 1.1 mrg */ 715 1.1 mrg void 716 1.27 dsl cdtty_loadchannelregs(struct cd18xx_softc *sc, struct cdtty_port *p) 717 1.1 mrg { 718 1.1 mrg 719 1.1 mrg cd18xx_set_car(sc, CD18XX_CHANNEL(p->p_tty->t_dev)); 720 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 721 1.1 mrg cd18xx_write(sc, CD18xx_MSVR, p->p_msvr_active = p->p_msvr); 722 1.1 mrg cd18xx_write(sc, CD18xx_COR1, p->p_cor1); 723 1.1 mrg cd18xx_write(sc, CD18xx_COR2, p->p_cor2); 724 1.1 mrg cd18xx_write(sc, CD18xx_COR3, p->p_cor3); 725 1.1 mrg /* 726 1.10 perry * COR2 and COR3 change commands are not required here for 727 1.1 mrg * the CL-CD1865 but we do them anyway for simplicity. 728 1.1 mrg */ 729 1.1 mrg cd18xx_write(sc, CD18xx_CCR, CD18xx_CCR_CORCHG | 730 1.1 mrg CD18xx_CCR_CORCHG_COR1 | 731 1.1 mrg CD18xx_CCR_CORCHG_COR2 | 732 1.1 mrg CD18xx_CCR_CORCHG_COR3); 733 1.1 mrg cd18xx_write(sc, CD18xx_RBPRH, p->p_rbprh); 734 1.1 mrg cd18xx_write(sc, CD18xx_RBPRL, p->p_rbprl); 735 1.1 mrg cd18xx_write(sc, CD18xx_TBPRH, p->p_tbprh); 736 1.1 mrg cd18xx_write(sc, CD18xx_TBPRL, p->p_tbprl); 737 1.1 mrg if (cd18xx_wait_ccr(sc)) { 738 1.1 mrg DPRINTF(CDD_INFO, 739 1.1 mrg ("%s: cdtty_loadchannelregs ccr wait timed out\n", 740 1.29 chs device_xname(sc->sc_dev))); 741 1.1 mrg } 742 1.1 mrg cd18xx_write(sc, CD18xx_CCR, p->p_chanctl); 743 1.1 mrg } 744 1.1 mrg 745 1.1 mrg /* 746 1.1 mrg * Set tty parameters from termios. 747 1.1 mrg * XXX - Should just copy the whole termios after 748 1.1 mrg * making sure all the changes could be done. 749 1.1 mrg */ 750 1.1 mrg static int 751 1.26 cegger cdttyparam(struct tty *tp, struct termios *t) 752 1.1 mrg { 753 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(tp->t_dev)); 754 1.1 mrg struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 755 1.1 mrg int s; 756 1.1 mrg 757 1.1 mrg /* Check requested parameters. */ 758 1.1 mrg if (t->c_ospeed < 0) 759 1.1 mrg return (EINVAL); 760 1.1 mrg if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 761 1.1 mrg return (EINVAL); 762 1.1 mrg 763 1.1 mrg /* 764 1.1 mrg * For the console, always force CLOCAL and !HUPCL, so that the port 765 1.1 mrg * is always active. 766 1.1 mrg */ 767 1.1 mrg if (ISSET(p->p_swflags, TIOCFLAG_SOFTCAR)) { 768 1.1 mrg SET(t->c_cflag, CLOCAL); 769 1.1 mrg CLR(t->c_cflag, HUPCL); 770 1.1 mrg } 771 1.1 mrg 772 1.1 mrg /* 773 1.1 mrg * If there were no changes, don't do anything. This avoids dropping 774 1.1 mrg * input and improves performance when all we did was frob things like 775 1.1 mrg * VMIN and VTIME. 776 1.1 mrg */ 777 1.1 mrg if (tp->t_ospeed == t->c_ospeed && 778 1.1 mrg tp->t_cflag == t->c_cflag) 779 1.1 mrg return (0); 780 1.1 mrg 781 1.1 mrg /* 782 1.1 mrg * Block interrupts so that state will not 783 1.1 mrg * be altered until we are done setting it up. 784 1.1 mrg */ 785 1.1 mrg s = splserial(); 786 1.1 mrg 787 1.1 mrg /* 788 1.1 mrg * Copy across the size, parity and stop bit info. 789 1.1 mrg */ 790 1.1 mrg switch (t->c_cflag & CSIZE) { 791 1.1 mrg case CS5: 792 1.1 mrg p->p_cor1 = CD18xx_COR1_CS5; 793 1.1 mrg break; 794 1.1 mrg case CS6: 795 1.1 mrg p->p_cor1 = CD18xx_COR1_CS6; 796 1.1 mrg break; 797 1.1 mrg case CS7: 798 1.1 mrg p->p_cor1 = CD18xx_COR1_CS7; 799 1.1 mrg break; 800 1.1 mrg default: 801 1.1 mrg p->p_cor1 = CD18xx_COR1_CS8; 802 1.1 mrg break; 803 1.1 mrg } 804 1.1 mrg if (ISSET(t->c_cflag, PARENB)) { 805 1.1 mrg SET(p->p_cor1, CD18xx_COR1_PARITY_NORMAL); 806 1.1 mrg if (ISSET(t->c_cflag, PARODD)) 807 1.1 mrg SET(p->p_cor1, CD18xx_COR1_PARITY_ODD); 808 1.1 mrg } 809 1.1 mrg if (!ISSET(t->c_iflag, INPCK)) 810 1.1 mrg SET(p->p_cor1, CD18xx_COR1_IGNORE); 811 1.1 mrg if (ISSET(t->c_cflag, CSTOPB)) 812 1.1 mrg SET(p->p_cor1, CD18xx_COR1_STOPBIT_2); 813 1.1 mrg 814 1.1 mrg /* 815 1.1 mrg * If we're not in a mode that assumes a connection is present, then 816 1.1 mrg * ignore carrier changes. 817 1.1 mrg */ 818 1.1 mrg if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 819 1.1 mrg p->p_msvr_dcd = 0; 820 1.1 mrg else 821 1.1 mrg p->p_msvr_dcd = CD18xx_MSVR_CD; 822 1.1 mrg 823 1.1 mrg /* 824 1.1 mrg * Set the flow control pins depending on the current flow control 825 1.1 mrg * mode. 826 1.1 mrg */ 827 1.1 mrg if (ISSET(t->c_cflag, CRTSCTS)) { 828 1.1 mrg p->p_mcor1_dtr = CD18xx_MCOR1_DTR; 829 1.1 mrg p->p_msvr_rts = CD18xx_MSVR_RTS; 830 1.1 mrg p->p_msvr_cts = CD18xx_MSVR_CTS; 831 1.1 mrg p->p_cor2 = CD18xx_COR2_RTSAOE|CD18xx_COR2_CTSAE; 832 1.1 mrg } else if (ISSET(t->c_cflag, MDMBUF)) { 833 1.1 mrg /* 834 1.1 mrg * For DTR/DCD flow control, make sure we don't toggle DTR for 835 1.1 mrg * carrier detection. 836 1.1 mrg */ 837 1.1 mrg p->p_mcor1_dtr = 0; 838 1.1 mrg p->p_msvr_rts = CD18xx_MSVR_DTR; 839 1.1 mrg p->p_msvr_cts = CD18xx_MSVR_CD; 840 1.1 mrg p->p_cor2 = 0; 841 1.1 mrg } else { 842 1.1 mrg /* 843 1.1 mrg * If no flow control, then always set RTS. This will make 844 1.1 mrg * the other side happy if it mistakenly thinks we're doing 845 1.1 mrg * RTS/CTS flow control. 846 1.1 mrg */ 847 1.1 mrg p->p_mcor1_dtr = CD18xx_MSVR_DTR; 848 1.1 mrg p->p_msvr_rts = 0; 849 1.1 mrg p->p_msvr_cts = 0; 850 1.1 mrg p->p_cor2 = 0; 851 1.1 mrg } 852 1.1 mrg p->p_msvr_mask = p->p_msvr_cts | p->p_msvr_dcd; 853 1.1 mrg 854 1.1 mrg /* 855 1.1 mrg * Set the FIFO threshold based on the receive speed. 856 1.1 mrg * 857 1.1 mrg * * If it's a low speed, it's probably a mouse or some other 858 1.1 mrg * interactive device, so set the threshold low. 859 1.1 mrg * * If it's a high speed, trim the trigger level down to prevent 860 1.1 mrg * overflows. 861 1.1 mrg * * Otherwise set it a bit higher. 862 1.1 mrg */ 863 1.15 simonb p->p_cor3 = (t->c_ospeed <= 1200 ? 1 : t->c_ospeed <= 38400 ? 8 : 4); 864 1.1 mrg 865 1.1 mrg #define PORT_RATE(o, s) \ 866 1.1 mrg (((((o) + (s)/2) / (s)) + CD18xx_xBRPR_TPC/2) / CD18xx_xBRPR_TPC) 867 1.1 mrg /* Compute BPS for the requested speeds */ 868 1.1 mrg if (t->c_ospeed) { 869 1.1 mrg u_int32_t tbpr = PORT_RATE(sc->sc_osc, t->c_ospeed); 870 1.1 mrg 871 1.1 mrg if (tbpr == 0 || tbpr > 0xffff) 872 1.1 mrg return (EINVAL); 873 1.1 mrg 874 1.1 mrg p->p_tbprh = tbpr >> 8; 875 1.1 mrg p->p_tbprl = tbpr & 0xff; 876 1.1 mrg } 877 1.1 mrg 878 1.1 mrg if (t->c_ispeed) { 879 1.1 mrg u_int32_t rbpr = PORT_RATE(sc->sc_osc, t->c_ispeed); 880 1.1 mrg 881 1.1 mrg if (rbpr == 0 || rbpr > 0xffff) 882 1.1 mrg return (EINVAL); 883 1.1 mrg 884 1.1 mrg p->p_rbprh = rbpr >> 8; 885 1.1 mrg p->p_rbprl = rbpr & 0xff; 886 1.1 mrg } 887 1.1 mrg 888 1.1 mrg /* And copy to tty. */ 889 1.1 mrg tp->t_ispeed = 0; 890 1.1 mrg tp->t_ospeed = t->c_ospeed; 891 1.1 mrg tp->t_cflag = t->c_cflag; 892 1.1 mrg 893 1.1 mrg if (!p->p_heldchange) { 894 1.1 mrg if (p->p_tx_busy) { 895 1.1 mrg p->p_heldtbc = p->p_tbc; 896 1.1 mrg p->p_tbc = 0; 897 1.1 mrg p->p_heldchange = 1; 898 1.1 mrg } else 899 1.1 mrg cdtty_loadchannelregs(sc, p); 900 1.1 mrg } 901 1.1 mrg 902 1.1 mrg if (!ISSET(t->c_cflag, CHWFLOW)) { 903 1.1 mrg /* Disable the high water mark. */ 904 1.1 mrg p->p_r_hiwat = 0; 905 1.1 mrg p->p_r_lowat = 0; 906 1.1 mrg if (ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 907 1.1 mrg CLR(p->p_rx_flags, RX_TTY_OVERFLOWED); 908 1.20 ad softint_schedule(sc->sc_si); 909 1.1 mrg } 910 1.1 mrg if (ISSET(p->p_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 911 1.1 mrg CLR(p->p_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 912 1.1 mrg cdtty_hwiflow(sc, p); 913 1.1 mrg } 914 1.1 mrg } else { 915 1.1 mrg p->p_r_hiwat = cdtty_rbuf_hiwat; 916 1.1 mrg p->p_r_lowat = cdtty_rbuf_lowat; 917 1.1 mrg } 918 1.1 mrg 919 1.1 mrg splx(s); 920 1.1 mrg 921 1.1 mrg /* 922 1.1 mrg * Update the tty layer's idea of the carrier bit, in case we changed 923 1.1 mrg * CLOCAL or MDMBUF. We don't hang up here; we only do that by 924 1.1 mrg * explicit request. 925 1.1 mrg */ 926 1.1 mrg (void) (*tp->t_linesw->l_modem)(tp, ISSET(p->p_msvr, CD18xx_MSVR_CD)); 927 1.1 mrg 928 1.1 mrg if (!ISSET(t->c_cflag, CHWFLOW)) { 929 1.1 mrg if (p->p_tx_stopped) { 930 1.1 mrg p->p_tx_stopped = 0; 931 1.1 mrg cdttystart(tp); 932 1.1 mrg } 933 1.1 mrg } 934 1.1 mrg 935 1.1 mrg return (0); 936 1.1 mrg } 937 1.1 mrg 938 1.1 mrg static void 939 1.27 dsl cdtty_break(struct cd18xx_softc *sc, struct cdtty_port *p, int onoff) 940 1.1 mrg { 941 1.1 mrg 942 1.1 mrg /* tell tx intr handler we need a break */ 943 1.1 mrg p->p_needbreak = !!onoff; 944 1.1 mrg 945 1.1 mrg /* turn on tx interrupts if break has changed */ 946 1.1 mrg if (p->p_needbreak != p->p_break) 947 1.1 mrg SET(p->p_srer, CD18xx_SRER_Tx); 948 1.1 mrg 949 1.1 mrg if (!p->p_heldchange) { 950 1.1 mrg if (p->p_tx_busy) { 951 1.1 mrg p->p_heldtbc = p->p_tbc; 952 1.1 mrg p->p_tbc = 0; 953 1.1 mrg p->p_heldchange = 1; 954 1.1 mrg } else 955 1.1 mrg cdtty_loadchannelregs(sc, p); 956 1.1 mrg } 957 1.1 mrg } 958 1.1 mrg 959 1.1 mrg /* 960 1.1 mrg * Raise or lower modem control (DTR/RTS) signals. If a character is 961 1.1 mrg * in transmission, the change is deferred. 962 1.1 mrg */ 963 1.1 mrg static void 964 1.27 dsl cdtty_modem(struct cd18xx_softc *sc, struct cdtty_port *p, int onoff) 965 1.1 mrg { 966 1.1 mrg 967 1.1 mrg if (p->p_mcor1_dtr == 0) 968 1.1 mrg return; 969 1.1 mrg 970 1.1 mrg if (onoff) 971 1.1 mrg CLR(p->p_mcor1, p->p_mcor1_dtr); 972 1.1 mrg else 973 1.1 mrg SET(p->p_mcor1, p->p_mcor1_dtr); 974 1.1 mrg 975 1.1 mrg if (!p->p_heldchange) { 976 1.1 mrg if (p->p_tx_busy) { 977 1.1 mrg p->p_heldtbc = p->p_tbc; 978 1.1 mrg p->p_tbc = 0; 979 1.1 mrg p->p_heldchange = 1; 980 1.1 mrg } else 981 1.1 mrg cdtty_loadchannelregs(sc, p); 982 1.1 mrg } 983 1.1 mrg } 984 1.1 mrg 985 1.1 mrg /* 986 1.1 mrg * Try to block or unblock input using hardware flow-control. 987 1.1 mrg * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and 988 1.1 mrg * if this function returns non-zero, the TS_TBLOCK flag will 989 1.1 mrg * be set or cleared according to the "block" arg passed. 990 1.1 mrg */ 991 1.1 mrg int 992 1.26 cegger cdttyhwiflow(struct tty *tp, int block) 993 1.1 mrg { 994 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, CD18XX_INSTANCE(tp->t_dev)); 995 1.1 mrg struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 996 1.1 mrg int s; 997 1.1 mrg 998 1.1 mrg if (p->p_msvr_rts == 0) 999 1.1 mrg return (0); 1000 1.1 mrg 1001 1.1 mrg s = splserial(); 1002 1.1 mrg if (block) { 1003 1.1 mrg if (!ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1004 1.1 mrg SET(p->p_rx_flags, RX_TTY_BLOCKED); 1005 1.1 mrg cdtty_hwiflow(sc, p); 1006 1.1 mrg } 1007 1.1 mrg } else { 1008 1.1 mrg if (ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 1009 1.1 mrg CLR(p->p_rx_flags, RX_TTY_OVERFLOWED); 1010 1.20 ad softint_schedule(sc->sc_si); 1011 1.1 mrg } 1012 1.1 mrg if (ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1013 1.1 mrg CLR(p->p_rx_flags, RX_TTY_BLOCKED); 1014 1.1 mrg cdtty_hwiflow(sc, p); 1015 1.1 mrg } 1016 1.1 mrg } 1017 1.1 mrg splx(s); 1018 1.1 mrg return (1); 1019 1.1 mrg } 1020 1.1 mrg 1021 1.1 mrg /* 1022 1.1 mrg * Internal version of cdttyhwiflow, called at cdtty's priority. 1023 1.1 mrg */ 1024 1.1 mrg static void 1025 1.27 dsl cdtty_hwiflow(struct cd18xx_softc *sc, struct cdtty_port *p) 1026 1.1 mrg { 1027 1.1 mrg 1028 1.1 mrg if (p->p_msvr_rts == 0) 1029 1.1 mrg return; 1030 1.1 mrg 1031 1.1 mrg if (ISSET(p->p_rx_flags, RX_ANY_BLOCK)) { 1032 1.1 mrg CLR(p->p_msvr, p->p_msvr_rts); 1033 1.1 mrg CLR(p->p_msvr_active, p->p_msvr_rts); 1034 1.1 mrg } else { 1035 1.1 mrg SET(p->p_msvr, p->p_msvr_rts); 1036 1.1 mrg SET(p->p_msvr_active, p->p_msvr_rts); 1037 1.1 mrg } 1038 1.1 mrg cd18xx_set_car(sc, CD18XX_CHANNEL(p->p_tty->t_dev)); 1039 1.1 mrg cd18xx_write(sc, CD18xx_MSVR, p->p_msvr_active); 1040 1.1 mrg } 1041 1.1 mrg 1042 1.1 mrg /* 1043 1.1 mrg * indiviual interrupt routines. 1044 1.1 mrg */ 1045 1.1 mrg 1046 1.1 mrg /* 1047 1.1 mrg * this is the number of interrupts allowed, total. set it to 0 1048 1.33 andvar * to allow unlimited interrupts 1049 1.1 mrg */ 1050 1.1 mrg #define INTR_MAX_ALLOWED 0 1051 1.1 mrg 1052 1.1 mrg #if INTR_MAX_ALLOWED == 0 1053 1.1 mrg #define GOTINTR(sc, p) /* nothing */ 1054 1.1 mrg #else 1055 1.1 mrg int intrcount; 1056 1.1 mrg #define GOTINTR(sc, p) \ 1057 1.1 mrg do { \ 1058 1.1 mrg if (intrcount++ == INTR_MAX_ALLOWED) { \ 1059 1.1 mrg CLR(p->p_srer, CD18xx_SRER_Tx); \ 1060 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); \ 1061 1.1 mrg } \ 1062 1.1 mrg DPRINTF(CDD_INTR, (", intrcount %d srer %x", intrcount, p->p_srer)); \ 1063 1.1 mrg } while (0) 1064 1.1 mrg #endif 1065 1.1 mrg 1066 1.1 mrg /* receiver interrupt */ 1067 1.13 perry static inline void 1068 1.27 dsl cd18xx_rint(struct cd18xx_softc *sc, int *ns) 1069 1.1 mrg { 1070 1.1 mrg struct cdtty_port *p; 1071 1.1 mrg u_int channel, count; 1072 1.1 mrg u_char *put, *end; 1073 1.1 mrg u_int cc; 1074 1.1 mrg 1075 1.1 mrg /* work out the channel and softc */ 1076 1.1 mrg channel = cd18xx_get_gscr1_channel(sc); 1077 1.1 mrg p = &sc->sc_ports[channel]; 1078 1.29 chs DPRINTF(CDD_INTR, ("%s: rint: channel %d", device_xname(sc->sc_dev), channel)); 1079 1.1 mrg GOTINTR(sc, p); 1080 1.1 mrg 1081 1.1 mrg end = p->p_ebuf; 1082 1.1 mrg put = p->p_rbput; 1083 1.1 mrg cc = p->p_rbavail; 1084 1.1 mrg 1085 1.1 mrg /* read as many bytes as necessary */ 1086 1.1 mrg count = cd18xx_read(sc, CD18xx_RDCR); 1087 1.1 mrg DPRINTF(CDD_INTR, (", %d bytes available: ", count)); 1088 1.1 mrg 1089 1.1 mrg while (cc > 0 && count > 0) { 1090 1.1 mrg u_char rcsr = cd18xx_read(sc, CD18xx_RCSR); 1091 1.1 mrg 1092 1.1 mrg put[0] = cd18xx_read(sc, CD18xx_RDR); 1093 1.1 mrg put[1] = rcsr; 1094 1.1 mrg 1095 1.1 mrg if (rcsr) 1096 1.1 mrg *ns = 1; 1097 1.1 mrg 1098 1.1 mrg put += 2; 1099 1.1 mrg if (put >= end) 1100 1.1 mrg put = p->p_rbuf; 1101 1.1 mrg 1102 1.1 mrg DPRINTF(CDD_INTR, (".")); 1103 1.1 mrg cc--; 1104 1.1 mrg count--; 1105 1.1 mrg } 1106 1.1 mrg 1107 1.1 mrg DPRINTF(CDD_INTR, (" finished reading")); 1108 1.1 mrg 1109 1.1 mrg /* 1110 1.1 mrg * Current string of incoming characters ended because 1111 1.1 mrg * no more data was available or we ran out of space. 1112 1.1 mrg * If we're out of space, turn off receive interrupts. 1113 1.1 mrg */ 1114 1.1 mrg p->p_rbput = put; 1115 1.1 mrg p->p_rbavail = cc; 1116 1.1 mrg if (!ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 1117 1.1 mrg p->p_rx_ready = 1; 1118 1.1 mrg } 1119 1.1 mrg 1120 1.1 mrg /* 1121 1.1 mrg * If we're out of space, disable receive interrupts 1122 1.1 mrg * until the queue has drained a bit. 1123 1.1 mrg */ 1124 1.1 mrg if (!cc) { 1125 1.1 mrg SET(p->p_rx_flags, RX_IBUF_OVERFLOWED); 1126 1.1 mrg CLR(p->p_srer, CD18xx_SRER_Rx | 1127 1.1 mrg CD18xx_SRER_RxSC | 1128 1.1 mrg CD18xx_SRER_CD); 1129 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1130 1.1 mrg } 1131 1.1 mrg 1132 1.1 mrg /* finish the interrupt transaction with the IC */ 1133 1.1 mrg cd18xx_write(sc, CD18xx_EOSRR, 0); 1134 1.1 mrg DPRINTF(CDD_INTR, (", done\n")); 1135 1.1 mrg } 1136 1.1 mrg 1137 1.1 mrg /* 1138 1.1 mrg * transmitter interrupt 1139 1.1 mrg * 1140 1.1 mrg * note this relys on the fact that we allow the transmitter FIFO to 1141 1.1 mrg * drain completely 1142 1.1 mrg */ 1143 1.13 perry static inline void 1144 1.27 dsl cd18xx_tint(struct cd18xx_softc *sc, int *ns) 1145 1.1 mrg { 1146 1.1 mrg struct cdtty_port *p; 1147 1.1 mrg u_int channel; 1148 1.1 mrg 1149 1.1 mrg /* work out the channel and softc */ 1150 1.1 mrg channel = cd18xx_get_gscr1_channel(sc); 1151 1.1 mrg p = &sc->sc_ports[channel]; 1152 1.29 chs DPRINTF(CDD_INTR, ("%s: tint: channel %d", device_xname(sc->sc_dev), 1153 1.1 mrg channel)); 1154 1.1 mrg GOTINTR(sc, p); 1155 1.1 mrg 1156 1.1 mrg /* if the current break condition is wrong, fix it */ 1157 1.1 mrg if (p->p_break != p->p_needbreak) { 1158 1.1 mrg u_char buf[2]; 1159 1.10 perry 1160 1.1 mrg DPRINTF(CDD_INTR, (", changing break to %d", p->p_needbreak)); 1161 1.1 mrg 1162 1.1 mrg /* turn on ETC processing */ 1163 1.1 mrg cd18xx_write(sc, CD18xx_COR2, p->p_cor2 | CD18xx_COR2_ETC); 1164 1.1 mrg 1165 1.1 mrg buf[0] = CD18xx_TDR_ETC_BYTE; 1166 1.1 mrg buf[1] = p->p_needbreak ? CD18xx_TDR_BREAK_BYTE : 1167 1.1 mrg CD18xx_TDR_NOBREAK_BYTE; 1168 1.1 mrg cd18xx_write_multi(sc, CD18xx_TDR, buf, 2); 1169 1.1 mrg 1170 1.1 mrg p->p_break = p->p_needbreak; 1171 1.1 mrg 1172 1.1 mrg /* turn off ETC processing */ 1173 1.1 mrg cd18xx_write(sc, CD18xx_COR2, p->p_cor2); 1174 1.1 mrg } 1175 1.1 mrg 1176 1.1 mrg /* 1177 1.1 mrg * If we've delayed a parameter change, do it now, and restart 1178 1.1 mrg * output. 1179 1.1 mrg */ 1180 1.1 mrg if (p->p_heldchange) { 1181 1.1 mrg cdtty_loadchannelregs(sc, p); 1182 1.1 mrg p->p_heldchange = 0; 1183 1.1 mrg p->p_tbc = p->p_heldtbc; 1184 1.1 mrg p->p_heldtbc = 0; 1185 1.1 mrg } 1186 1.1 mrg 1187 1.1 mrg /* Output the next chunk of the contiguous buffer, if any. */ 1188 1.1 mrg if (p->p_tbc > 0) { 1189 1.1 mrg int n; 1190 1.1 mrg 1191 1.1 mrg n = p->p_tbc; 1192 1.1 mrg if (n > 8) /* write up to 8 entries */ 1193 1.1 mrg n = 8; 1194 1.1 mrg DPRINTF(CDD_INTR, (", writing %d bytes to TDR", n)); 1195 1.1 mrg cd18xx_write_multi(sc, CD18xx_TDR, p->p_tba, n); 1196 1.1 mrg p->p_tbc -= n; 1197 1.1 mrg p->p_tba += n; 1198 1.1 mrg } 1199 1.1 mrg 1200 1.1 mrg /* Disable transmit completion interrupts if we ran out of bytes. */ 1201 1.1 mrg if (p->p_tbc == 0) { 1202 1.8 wiz /* Note that Tx interrupts should already be enabled */ 1203 1.1 mrg if (ISSET(p->p_srer, CD18xx_SRER_Tx)) { 1204 1.1 mrg DPRINTF(CDD_INTR, (", disabling tx interrupts")); 1205 1.1 mrg CLR(p->p_srer, CD18xx_SRER_Tx); 1206 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1207 1.1 mrg } 1208 1.1 mrg if (p->p_tx_busy) { 1209 1.1 mrg p->p_tx_busy = 0; 1210 1.1 mrg p->p_tx_done = 1; 1211 1.1 mrg } 1212 1.1 mrg } 1213 1.1 mrg *ns = 1; 1214 1.1 mrg 1215 1.1 mrg /* finish the interrupt transaction with the IC */ 1216 1.1 mrg cd18xx_write(sc, CD18xx_EOSRR, 0); 1217 1.1 mrg DPRINTF(CDD_INTR, (", done\n")); 1218 1.1 mrg } 1219 1.1 mrg 1220 1.1 mrg /* modem signal change interrupt */ 1221 1.13 perry static inline void 1222 1.27 dsl cd18xx_mint(struct cd18xx_softc *sc, int *ns) 1223 1.1 mrg { 1224 1.1 mrg struct cdtty_port *p; 1225 1.1 mrg u_int channel; 1226 1.1 mrg u_char msvr, delta; 1227 1.1 mrg 1228 1.1 mrg /* work out the channel and softc */ 1229 1.1 mrg channel = cd18xx_get_gscr1_channel(sc); 1230 1.1 mrg p = &sc->sc_ports[channel]; 1231 1.29 chs DPRINTF(CDD_INTR, ("%s: mint: channel %d", device_xname(sc->sc_dev), channel)); 1232 1.1 mrg GOTINTR(sc, p); 1233 1.1 mrg 1234 1.1 mrg /* 1235 1.1 mrg * We ignore the MCR register, and handle detecting deltas 1236 1.1 mrg * via software, like many other serial drivers. 1237 1.1 mrg */ 1238 1.1 mrg msvr = cd18xx_read(sc, CD18xx_MSVR); 1239 1.1 mrg delta = msvr ^ p->p_msvr; 1240 1.1 mrg DPRINTF(CDD_INTR, (", msvr %d", msvr)); 1241 1.1 mrg 1242 1.1 mrg /* 1243 1.1 mrg * Process normal status changes 1244 1.1 mrg */ 1245 1.1 mrg if (ISSET(delta, p->p_msvr_mask)) { 1246 1.1 mrg SET(p->p_msvr_delta, delta); 1247 1.1 mrg 1248 1.1 mrg DPRINTF(CDD_INTR, (", status changed delta %d", delta)); 1249 1.1 mrg /* 1250 1.1 mrg * Stop output immediately if we lose the output 1251 1.1 mrg * flow control signal or carrier detect. 1252 1.1 mrg */ 1253 1.1 mrg if (ISSET(~msvr, p->p_msvr_mask)) { 1254 1.1 mrg p->p_tbc = 0; 1255 1.1 mrg p->p_heldtbc = 0; 1256 1.1 mrg /* Stop modem interrupt processing */ 1257 1.1 mrg } 1258 1.1 mrg p->p_st_check = 1; 1259 1.1 mrg *ns = 1; 1260 1.1 mrg } 1261 1.1 mrg 1262 1.1 mrg /* reset the modem signal register */ 1263 1.1 mrg cd18xx_write(sc, CD18xx_MCR, 0); 1264 1.1 mrg 1265 1.1 mrg /* finish the interrupt transaction with the IC */ 1266 1.1 mrg cd18xx_write(sc, CD18xx_EOSRR, 0); 1267 1.1 mrg DPRINTF(CDD_INTR, (", done\n")); 1268 1.1 mrg } 1269 1.1 mrg 1270 1.1 mrg /* 1271 1.1 mrg * hardware interrupt routine. call the relevant interrupt routines until 1272 1.1 mrg * no interrupts are pending. 1273 1.1 mrg * 1274 1.1 mrg * note: we do receive interrupts before all others (as we'd rather lose 1275 1.1 mrg * a chance to transmit, than lose a character). and we do transmit 1276 1.1 mrg * interrupts before modem interrupts. 1277 1.1 mrg * 1278 1.1 mrg * we have to traverse all of the cd18xx's attached, unfortunately. 1279 1.1 mrg */ 1280 1.1 mrg int 1281 1.26 cegger cd18xx_hardintr(void *v) 1282 1.1 mrg { 1283 1.1 mrg int i, rv = 0; 1284 1.1 mrg u_char ack; 1285 1.1 mrg 1286 1.1 mrg DPRINTF(CDD_INTR, ("cd18xx_hardintr (ndevs %d):\n", clcd_cd.cd_ndevs)); 1287 1.1 mrg for (i = 0; i < clcd_cd.cd_ndevs; i++) 1288 1.1 mrg { 1289 1.26 cegger struct cd18xx_softc *sc = device_lookup_private(&clcd_cd, i); 1290 1.1 mrg int status, ns = 0; 1291 1.1 mrg int count = 1; /* process only 1 interrupts at a time for now */ 1292 1.1 mrg 1293 1.1 mrg if (sc == NULL) 1294 1.1 mrg continue; 1295 1.1 mrg 1296 1.29 chs DPRINTF(CDD_INTR, ("%s:", device_xname(sc->sc_dev))); 1297 1.1 mrg while (count-- && 1298 1.1 mrg (status = (cd18xx_read(sc, CD18xx_SRSR) & 1299 1.1 mrg CD18xx_SRSR_PENDING))) { 1300 1.1 mrg rv = 1; 1301 1.1 mrg 1302 1.1 mrg DPRINTF(CDD_INTR, (" status %x:", status)); 1303 1.1 mrg if (ISSET(status, CD18xx_SRSR_RxPEND)) { 1304 1.1 mrg ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1305 1.1 mrg CD18xx_INTRACK_RxINT); 1306 1.1 mrg DPRINTF(CDD_INTR, (" rx: ack1 %x\n", ack)); 1307 1.1 mrg cd18xx_rint(sc, &ns); 1308 1.1 mrg } 1309 1.1 mrg if (ISSET(status, CD18xx_SRSR_TxPEND)) { 1310 1.1 mrg ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1311 1.1 mrg CD18xx_INTRACK_TxINT); 1312 1.1 mrg DPRINTF(CDD_INTR, (" tx: ack1 %x\n", ack)); 1313 1.1 mrg cd18xx_tint(sc, &ns); 1314 1.1 mrg 1315 1.1 mrg } 1316 1.1 mrg if (ISSET(status, CD18xx_SRSR_MxPEND)) { 1317 1.1 mrg ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1318 1.1 mrg CD18xx_INTRACK_MxINT); 1319 1.1 mrg DPRINTF(CDD_INTR, (" mx: ack1 %x\n", ack)); 1320 1.1 mrg cd18xx_mint(sc, &ns); 1321 1.1 mrg } 1322 1.1 mrg } 1323 1.1 mrg if (ns) 1324 1.20 ad softint_schedule(sc->sc_si); 1325 1.1 mrg } 1326 1.1 mrg 1327 1.1 mrg return (rv); 1328 1.1 mrg } 1329 1.1 mrg 1330 1.1 mrg /* 1331 1.1 mrg * software interrupt 1332 1.1 mrg */ 1333 1.1 mrg 1334 1.1 mrg void 1335 1.27 dsl cdtty_rxsoft(struct cd18xx_softc *sc, struct cdtty_port *p, struct tty *tp) 1336 1.1 mrg { 1337 1.1 mrg u_char *get, *end; 1338 1.1 mrg u_int cc, scc; 1339 1.1 mrg u_char rcsr; 1340 1.1 mrg int code; 1341 1.1 mrg int s; 1342 1.1 mrg 1343 1.1 mrg end = p->p_ebuf; 1344 1.1 mrg get = p->p_rbget; 1345 1.1 mrg scc = cc = cdtty_rbuf_size - p->p_rbavail; 1346 1.1 mrg 1347 1.1 mrg if (cc == cdtty_rbuf_size) { 1348 1.1 mrg p->p_floods++; 1349 1.1 mrg #if 0 1350 1.1 mrg if (p->p_errors++ == 0) 1351 1.1 mrg callout_reset(&p->p_diag_callout, 60 * hz, 1352 1.1 mrg cdttydiag, p); 1353 1.1 mrg #endif 1354 1.1 mrg } 1355 1.1 mrg 1356 1.1 mrg while (cc) { 1357 1.1 mrg code = get[0]; 1358 1.1 mrg rcsr = get[1]; 1359 1.1 mrg if (ISSET(rcsr, CD18xx_RCSR_OVERRUNERR | CD18xx_RCSR_BREAK | 1360 1.1 mrg CD18xx_RCSR_FRAMERR | CD18xx_RCSR_PARITYERR)) { 1361 1.1 mrg if (ISSET(rcsr, CD18xx_RCSR_OVERRUNERR)) { 1362 1.1 mrg p->p_overflows++; 1363 1.1 mrg #if 0 1364 1.1 mrg if (p->p_errors++ == 0) 1365 1.1 mrg callout_reset(&p->p_diag_callout, 1366 1.1 mrg 60 * hz, cdttydiag, p); 1367 1.1 mrg #endif 1368 1.1 mrg } 1369 1.1 mrg if (ISSET(rcsr, CD18xx_RCSR_BREAK|CD18xx_RCSR_FRAMERR)) 1370 1.1 mrg SET(code, TTY_FE); 1371 1.1 mrg if (ISSET(rcsr, CD18xx_RCSR_PARITYERR)) 1372 1.1 mrg SET(code, TTY_PE); 1373 1.1 mrg } 1374 1.1 mrg if ((*tp->t_linesw->l_rint)(code, tp) == -1) { 1375 1.1 mrg /* 1376 1.1 mrg * The line discipline's buffer is out of space. 1377 1.1 mrg */ 1378 1.1 mrg if (!ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1379 1.1 mrg /* 1380 1.1 mrg * We're either not using flow control, or the 1381 1.1 mrg * line discipline didn't tell us to block for 1382 1.1 mrg * some reason. Either way, we have no way to 1383 1.1 mrg * know when there's more space available, so 1384 1.1 mrg * just drop the rest of the data. 1385 1.1 mrg */ 1386 1.1 mrg get += cc << 1; 1387 1.1 mrg if (get >= end) 1388 1.1 mrg get -= cdtty_rbuf_size << 1; 1389 1.1 mrg cc = 0; 1390 1.1 mrg } else { 1391 1.1 mrg /* 1392 1.1 mrg * Don't schedule any more receive processing 1393 1.1 mrg * until the line discipline tells us there's 1394 1.1 mrg * space available (through cdttyhwiflow()). 1395 1.1 mrg * Leave the rest of the data in the input 1396 1.1 mrg * buffer. 1397 1.1 mrg */ 1398 1.1 mrg SET(p->p_rx_flags, RX_TTY_OVERFLOWED); 1399 1.1 mrg } 1400 1.1 mrg break; 1401 1.1 mrg } 1402 1.1 mrg get += 2; 1403 1.1 mrg if (get >= end) 1404 1.1 mrg get = p->p_rbuf; 1405 1.1 mrg cc--; 1406 1.1 mrg } 1407 1.1 mrg 1408 1.1 mrg if (cc != scc) { 1409 1.1 mrg p->p_rbget = get; 1410 1.1 mrg s = splserial(); 1411 1.10 perry 1412 1.1 mrg cc = p->p_rbavail += scc - cc; 1413 1.1 mrg /* Buffers should be ok again, release possible block. */ 1414 1.1 mrg if (cc >= p->p_r_lowat) { 1415 1.1 mrg if (ISSET(p->p_rx_flags, RX_IBUF_OVERFLOWED)) { 1416 1.1 mrg CLR(p->p_rx_flags, RX_IBUF_OVERFLOWED); 1417 1.1 mrg cd18xx_set_car(sc, CD18XX_CHANNEL(tp->t_dev)); 1418 1.1 mrg SET(p->p_srer, CD18xx_SRER_Rx | 1419 1.1 mrg CD18xx_SRER_RxSC | 1420 1.1 mrg CD18xx_SRER_CD); 1421 1.1 mrg cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1422 1.1 mrg } 1423 1.1 mrg if (ISSET(p->p_rx_flags, RX_IBUF_BLOCKED)) { 1424 1.1 mrg CLR(p->p_rx_flags, RX_IBUF_BLOCKED); 1425 1.1 mrg cdtty_hwiflow(sc, p); 1426 1.1 mrg } 1427 1.1 mrg } 1428 1.1 mrg splx(s); 1429 1.1 mrg } 1430 1.1 mrg } 1431 1.1 mrg 1432 1.1 mrg void 1433 1.27 dsl cdtty_txsoft(struct cd18xx_softc *sc, struct cdtty_port *p, struct tty *tp) 1434 1.1 mrg { 1435 1.1 mrg 1436 1.1 mrg CLR(tp->t_state, TS_BUSY); 1437 1.1 mrg if (ISSET(tp->t_state, TS_FLUSH)) 1438 1.1 mrg CLR(tp->t_state, TS_FLUSH); 1439 1.1 mrg else 1440 1.1 mrg ndflush(&tp->t_outq, (int)(p->p_tba - tp->t_outq.c_cf)); 1441 1.1 mrg (*tp->t_linesw->l_start)(tp); 1442 1.1 mrg } 1443 1.1 mrg 1444 1.1 mrg void 1445 1.27 dsl cdtty_stsoft(struct cd18xx_softc *sc, struct cdtty_port *p, struct tty *tp) 1446 1.1 mrg { 1447 1.1 mrg u_char msvr, delta; 1448 1.1 mrg int s; 1449 1.1 mrg 1450 1.1 mrg s = splserial(); 1451 1.1 mrg msvr = p->p_msvr; 1452 1.1 mrg delta = p->p_msvr_delta; 1453 1.1 mrg p->p_msvr_delta = 0; 1454 1.1 mrg splx(s); 1455 1.1 mrg 1456 1.1 mrg if (ISSET(delta, p->p_msvr_dcd)) { 1457 1.1 mrg /* 1458 1.1 mrg * Inform the tty layer that carrier detect changed. 1459 1.1 mrg */ 1460 1.1 mrg (void) (*tp->t_linesw->l_modem)(tp, ISSET(msvr, CD18xx_MSVR_CD)); 1461 1.1 mrg } 1462 1.1 mrg 1463 1.1 mrg if (ISSET(delta, p->p_msvr_cts)) { 1464 1.1 mrg /* Block or unblock output according to flow control. */ 1465 1.1 mrg if (ISSET(msvr, p->p_msvr_cts)) { 1466 1.1 mrg p->p_tx_stopped = 0; 1467 1.1 mrg (*tp->t_linesw->l_start)(tp); 1468 1.1 mrg } else { 1469 1.1 mrg p->p_tx_stopped = 1; 1470 1.1 mrg } 1471 1.1 mrg } 1472 1.1 mrg } 1473 1.1 mrg 1474 1.1 mrg void 1475 1.27 dsl cd18xx_softintr(void *v) 1476 1.1 mrg { 1477 1.1 mrg struct cd18xx_softc *sc = v; 1478 1.1 mrg struct cdtty_port *p; 1479 1.1 mrg struct tty *tp; 1480 1.1 mrg int i; 1481 1.1 mrg 1482 1.1 mrg for (i = 0; i < 8; i++) { 1483 1.1 mrg p = &sc->sc_ports[i]; 1484 1.1 mrg 1485 1.1 mrg tp = p->p_tty; 1486 1.1 mrg if (tp == NULL) 1487 1.1 mrg continue; 1488 1.1 mrg if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1489 1.1 mrg continue; 1490 1.1 mrg 1491 1.1 mrg if (p->p_rx_ready) { 1492 1.1 mrg p->p_rx_ready = 0; 1493 1.1 mrg cdtty_rxsoft(sc, p, tp); 1494 1.1 mrg } 1495 1.1 mrg 1496 1.1 mrg if (p->p_st_check) { 1497 1.1 mrg p->p_st_check = 0; 1498 1.1 mrg cdtty_stsoft(sc, p, tp); 1499 1.1 mrg } 1500 1.1 mrg 1501 1.1 mrg if (p->p_tx_done) { 1502 1.1 mrg p->p_tx_done = 0; 1503 1.1 mrg cdtty_txsoft(sc, p, tp); 1504 1.1 mrg } 1505 1.1 mrg } 1506 1.1 mrg } 1507