1 1.35 riastrad /* $NetBSD: spif.c,v 1.35 2022/10/26 23:46:50 riastradh Exp $ */ 2 1.1 mrg /* $OpenBSD: spif.c,v 1.12 2003/10/03 16:44:51 miod Exp $ */ 3 1.1 mrg 4 1.1 mrg /* 5 1.1 mrg * Copyright (c) 1999-2002 Jason L. Wright (jason (at) thought.net) 6 1.1 mrg * All rights reserved. 7 1.1 mrg * 8 1.1 mrg * Redistribution and use in source and binary forms, with or without 9 1.1 mrg * modification, are permitted provided that the following conditions 10 1.1 mrg * are met: 11 1.1 mrg * 1. Redistributions of source code must retain the above copyright 12 1.1 mrg * notice, this list of conditions and the following disclaimer. 13 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 mrg * notice, this list of conditions and the following disclaimer in the 15 1.1 mrg * documentation and/or other materials provided with the distribution. 16 1.1 mrg * 17 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 1.1 mrg * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 1.1 mrg * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 1.1 mrg * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 1.1 mrg * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 1.1 mrg * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 1.1 mrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 1.1 mrg * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 1.1 mrg * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 mrg * POSSIBILITY OF SUCH DAMAGE. 28 1.1 mrg * 29 1.1 mrg * Effort sponsored in part by the Defense Advanced Research Projects 30 1.1 mrg * Agency (DARPA) and Air Force Research Laboratory, Air Force 31 1.1 mrg * Materiel Command, USAF, under agreement number F30602-01-2-0537. 32 1.1 mrg * 33 1.1 mrg */ 34 1.1 mrg 35 1.1 mrg /* 36 1.1 mrg * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board 37 1.1 mrg * based heavily on Iain Hibbert's driver for the MAGMA cards 38 1.1 mrg */ 39 1.1 mrg 40 1.1 mrg /* Ported to NetBSD 2.0 by Hauke Fath */ 41 1.1 mrg 42 1.1 mrg 43 1.1 mrg #include <sys/cdefs.h> 44 1.35 riastrad __KERNEL_RCSID(0, "$NetBSD: spif.c,v 1.35 2022/10/26 23:46:50 riastradh Exp $"); 45 1.1 mrg 46 1.1 mrg #include "spif.h" 47 1.1 mrg #if NSPIF > 0 48 1.1 mrg 49 1.1 mrg #include <sys/param.h> 50 1.1 mrg #include <sys/systm.h> 51 1.1 mrg #include <sys/proc.h> 52 1.1 mrg #include <sys/device.h> 53 1.1 mrg #include <sys/file.h> 54 1.1 mrg #include <sys/ioctl.h> 55 1.1 mrg #include <sys/malloc.h> 56 1.1 mrg #include <sys/tty.h> 57 1.1 mrg #include <sys/time.h> 58 1.1 mrg #include <sys/kernel.h> 59 1.1 mrg #include <sys/syslog.h> 60 1.1 mrg #include <sys/conf.h> 61 1.1 mrg #include <sys/errno.h> 62 1.6 yamt #include <sys/kauth.h> 63 1.11 ad #include <sys/intr.h> 64 1.1 mrg 65 1.12 ad #include <sys/bus.h> 66 1.1 mrg #include <machine/autoconf.h> 67 1.1 mrg #include <machine/promlib.h> 68 1.1 mrg 69 1.1 mrg #include <dev/sbus/sbusvar.h> 70 1.1 mrg 71 1.1 mrg #include <dev/sbus/spifvar.h> 72 1.1 mrg #include <dev/sbus/spifreg.h> 73 1.1 mrg 74 1.24 tsutsui #include "ioconf.h" 75 1.1 mrg 76 1.1 mrg /* Autoconfig stuff */ 77 1.1 mrg 78 1.28 mrg CFATTACH_DECL_NEW(spif, sizeof(struct spif_softc), 79 1.1 mrg spif_match, spif_attach, NULL, NULL); 80 1.1 mrg 81 1.28 mrg CFATTACH_DECL_NEW(stty, sizeof(struct stty_softc), 82 1.1 mrg stty_match, stty_attach, NULL, NULL); 83 1.1 mrg 84 1.28 mrg CFATTACH_DECL_NEW(sbpp, sizeof(struct sbpp_softc), 85 1.1 mrg sbpp_match, sbpp_attach, NULL, NULL); 86 1.1 mrg 87 1.1 mrg dev_type_open(stty_open); 88 1.1 mrg dev_type_close(stty_close); 89 1.1 mrg dev_type_read(stty_read); 90 1.1 mrg dev_type_write(stty_write); 91 1.1 mrg dev_type_ioctl(stty_ioctl); 92 1.1 mrg dev_type_stop(stty_stop); 93 1.1 mrg dev_type_tty(stty_tty); 94 1.1 mrg dev_type_poll(stty_poll); 95 1.1 mrg 96 1.1 mrg const struct cdevsw stty_cdevsw = { 97 1.30 dholland .d_open = stty_open, 98 1.30 dholland .d_close = stty_close, 99 1.30 dholland .d_read = stty_read, 100 1.30 dholland .d_write = stty_write, 101 1.30 dholland .d_ioctl = stty_ioctl, 102 1.30 dholland .d_stop = stty_stop, 103 1.30 dholland .d_tty = stty_tty, 104 1.30 dholland .d_poll = stty_poll, 105 1.30 dholland .d_mmap = nommap, 106 1.30 dholland .d_kqfilter = ttykqfilter, 107 1.31 dholland .d_discard = nodiscard, 108 1.30 dholland .d_flag = D_TTY 109 1.1 mrg }; 110 1.1 mrg 111 1.1 mrg dev_type_open(sbpp_open); 112 1.1 mrg dev_type_close(sbpp_close); 113 1.1 mrg dev_type_read(sbpp_read); 114 1.1 mrg dev_type_write(sbpp_write); 115 1.1 mrg dev_type_ioctl(sbpp_ioctl); 116 1.1 mrg dev_type_poll(sbpp_poll); 117 1.1 mrg 118 1.1 mrg const struct cdevsw sbpp_cdevsw = { 119 1.30 dholland .d_open = sbpp_open, 120 1.30 dholland .d_close = sbpp_close, 121 1.30 dholland .d_read = sbpp_read, 122 1.30 dholland .d_write = sbpp_write, 123 1.30 dholland .d_ioctl = sbpp_ioctl, 124 1.30 dholland .d_stop = nostop, 125 1.30 dholland .d_tty = notty, 126 1.30 dholland .d_poll = sbpp_poll, 127 1.30 dholland .d_mmap = nommap, 128 1.30 dholland .d_kqfilter = nokqfilter, 129 1.31 dholland .d_discard = nodiscard, 130 1.30 dholland .d_flag = D_OTHER 131 1.1 mrg }; 132 1.1 mrg 133 1.1 mrg 134 1.1 mrg /* normal STC access */ 135 1.1 mrg #define STC_WRITE(sc,r,v) \ 136 1.1 mrg bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v)) 137 1.1 mrg #define STC_READ(sc,r) \ 138 1.1 mrg bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r)) 139 1.1 mrg 140 1.1 mrg /* IACK STC access */ 141 1.1 mrg #define ISTC_WRITE(sc,r,v) \ 142 1.1 mrg bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v)) 143 1.1 mrg #define ISTC_READ(sc,r) \ 144 1.1 mrg bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r)) 145 1.1 mrg 146 1.1 mrg /* PPC access */ 147 1.1 mrg #define PPC_WRITE(sc,r,v) \ 148 1.1 mrg bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v)) 149 1.1 mrg #define PPC_READ(sc,r) \ 150 1.1 mrg bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r)) 151 1.1 mrg 152 1.1 mrg #define DTR_WRITE(sc,port,v) \ 153 1.1 mrg do { \ 154 1.1 mrg sc->sc_ttys->sc_port[(port)].sp_dtr = v; \ 155 1.1 mrg bus_space_write_1((sc)->sc_bustag, \ 156 1.1 mrg sc->sc_dtrh, port, (v == 0) ? 1 : 0); \ 157 1.1 mrg } while (0) 158 1.1 mrg 159 1.1 mrg #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr) 160 1.1 mrg 161 1.1 mrg 162 1.1 mrg int 163 1.23 cegger spif_match(device_t parent, cfdata_t vcf, void *aux) 164 1.1 mrg { 165 1.1 mrg struct sbus_attach_args *sa = aux; 166 1.1 mrg 167 1.1 mrg if (strcmp(vcf->cf_name, sa->sa_name) && 168 1.1 mrg strcmp("SUNW,spif", sa->sa_name)) 169 1.1 mrg return (0); 170 1.1 mrg return (1); 171 1.1 mrg } 172 1.1 mrg 173 1.2 perry void 174 1.23 cegger spif_attach(device_t parent, device_t self, void *aux) 175 1.1 mrg { 176 1.18 drochner struct spif_softc *sc = device_private(self); 177 1.1 mrg struct sbus_attach_args *sa = aux; 178 1.1 mrg 179 1.28 mrg sc->sc_dev = self; 180 1.28 mrg 181 1.1 mrg if (sa->sa_nintr != 2) { 182 1.1 mrg printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); 183 1.1 mrg return; 184 1.1 mrg } 185 1.1 mrg 186 1.1 mrg if (sa->sa_nreg != 1) { 187 1.1 mrg printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); 188 1.1 mrg return; 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg sc->sc_bustag = sa->sa_bustag; 192 1.1 mrg if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 193 1.1 mrg sa->sa_offset, sa->sa_size, 194 1.1 mrg 0, &sc->sc_regh) != 0) { 195 1.1 mrg printf(": can't map registers\n"); 196 1.1 mrg return; 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 200 1.1 mrg DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { 201 1.1 mrg printf(": can't map dtr regs\n"); 202 1.1 mrg goto fail_unmapregs; 203 1.1 mrg } 204 1.1 mrg 205 1.1 mrg if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 206 1.1 mrg STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { 207 1.1 mrg printf(": can't map dtr regs\n"); 208 1.1 mrg goto fail_unmapregs; 209 1.1 mrg } 210 1.1 mrg 211 1.1 mrg if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 212 1.1 mrg ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { 213 1.1 mrg printf(": can't map dtr regs\n"); 214 1.1 mrg goto fail_unmapregs; 215 1.1 mrg } 216 1.1 mrg 217 1.1 mrg if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 218 1.1 mrg PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { 219 1.1 mrg printf(": can't map dtr regs\n"); 220 1.1 mrg goto fail_unmapregs; 221 1.1 mrg } 222 1.1 mrg 223 1.1 mrg sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, 224 1.1 mrg sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); 225 1.1 mrg if (sc->sc_ppcih == NULL) { 226 1.1 mrg printf(": failed to establish ppc interrupt\n"); 227 1.1 mrg goto fail_unmapregs; 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg sc->sc_stcih = bus_intr_establish(sa->sa_bustag, 231 1.1 mrg sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc); 232 1.1 mrg if (sc->sc_stcih == NULL) { 233 1.1 mrg printf(": failed to establish stc interrupt\n"); 234 1.1 mrg goto fail_unmapregs; 235 1.1 mrg } 236 1.1 mrg 237 1.11 ad sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc); 238 1.1 mrg if (sc->sc_softih == NULL) { 239 1.1 mrg printf(": can't get soft intr\n"); 240 1.1 mrg goto fail_unmapregs; 241 1.1 mrg } 242 1.1 mrg 243 1.1 mrg sc->sc_node = sa->sa_node; 244 1.1 mrg 245 1.1 mrg sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); 246 1.1 mrg 247 1.1 mrg sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); 248 1.1 mrg switch (sc->sc_osc) { 249 1.1 mrg case SPIF_OSC10: 250 1.1 mrg sc->sc_osc = 10000000; 251 1.1 mrg break; 252 1.1 mrg case SPIF_OSC9: 253 1.1 mrg default: 254 1.1 mrg sc->sc_osc = 9830400; 255 1.1 mrg break; 256 1.1 mrg } 257 1.1 mrg 258 1.1 mrg sc->sc_nser = 8; 259 1.1 mrg sc->sc_npar = 1; 260 1.1 mrg 261 1.1 mrg sc->sc_rev2 = STC_READ(sc, STC_GFRCR); 262 1.1 mrg STC_WRITE(sc, STC_GSVR, 0); 263 1.1 mrg 264 1.1 mrg stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); 265 1.1 mrg while (STC_READ(sc, STC_GSVR) != 0xff); 266 1.1 mrg while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); 267 1.1 mrg 268 1.1 mrg STC_WRITE(sc, STC_PPRH, CD180_PPRH); 269 1.1 mrg STC_WRITE(sc, STC_PPRL, CD180_PPRL); 270 1.1 mrg STC_WRITE(sc, STC_MSMR, SPIF_MSMR); 271 1.1 mrg STC_WRITE(sc, STC_TSMR, SPIF_TSMR); 272 1.1 mrg STC_WRITE(sc, STC_RSMR, SPIF_RSMR); 273 1.1 mrg STC_WRITE(sc, STC_GSVR, 0); 274 1.1 mrg STC_WRITE(sc, STC_GSCR1, 0); 275 1.1 mrg STC_WRITE(sc, STC_GSCR2, 0); 276 1.1 mrg STC_WRITE(sc, STC_GSCR3, 0); 277 1.1 mrg 278 1.1 mrg printf(": rev %x chiprev %x osc %sMHz\n", 279 1.1 mrg sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); 280 1.1 mrg 281 1.34 thorpej (void)config_found(self, stty_match, NULL, CFARGS_NONE); 282 1.34 thorpej (void)config_found(self, sbpp_match, NULL, CFARGS_NONE); 283 1.1 mrg 284 1.1 mrg return; 285 1.1 mrg 286 1.1 mrg fail_unmapregs: 287 1.1 mrg bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); 288 1.1 mrg } 289 1.1 mrg 290 1.1 mrg int 291 1.23 cegger stty_match(device_t parent, cfdata_t vcf, void *aux) 292 1.1 mrg { 293 1.18 drochner struct spif_softc *sc = device_private(parent); 294 1.1 mrg 295 1.1 mrg return (aux == stty_match && sc->sc_ttys == NULL); 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg void 299 1.23 cegger stty_attach(device_t parent, device_t dev, void *aux) 300 1.1 mrg { 301 1.18 drochner struct spif_softc *sc = device_private(parent); 302 1.18 drochner struct stty_softc *ssc = device_private(dev); 303 1.1 mrg int port; 304 1.1 mrg 305 1.28 mrg sc->sc_dev = dev; 306 1.1 mrg sc->sc_ttys = ssc; 307 1.1 mrg 308 1.1 mrg for (port = 0; port < sc->sc_nser; port++) { 309 1.1 mrg struct stty_port *sp = &ssc->sc_port[port]; 310 1.1 mrg struct tty *tp; 311 1.1 mrg 312 1.1 mrg DTR_WRITE(sc, port, 0); 313 1.1 mrg 314 1.26 rmind tp = tty_alloc(); 315 1.1 mrg 316 1.1 mrg tp->t_oproc = stty_start; 317 1.1 mrg tp->t_param = stty_param; 318 1.1 mrg 319 1.1 mrg sp->sp_tty = tp; 320 1.1 mrg sp->sp_sc = sc; 321 1.1 mrg sp->sp_channel = port; 322 1.1 mrg 323 1.32 chs sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_WAITOK); 324 1.1 mrg sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE; 325 1.1 mrg } 326 1.1 mrg 327 1.1 mrg ssc->sc_nports = port; 328 1.1 mrg 329 1.1 mrg printf(": %d tty%s\n", port, port == 1 ? "" : "s"); 330 1.1 mrg } 331 1.1 mrg 332 1.1 mrg int 333 1.17 cegger stty_open(dev_t dev, int flags, int mode, struct lwp *l) 334 1.1 mrg { 335 1.1 mrg struct spif_softc *csc; 336 1.1 mrg struct stty_softc *sc; 337 1.1 mrg struct stty_port *sp; 338 1.1 mrg struct tty *tp; 339 1.1 mrg int card = SPIF_CARD(dev); 340 1.1 mrg int port = SPIF_PORT(dev); 341 1.1 mrg 342 1.17 cegger sc = device_lookup_private(&stty_cd, card); 343 1.17 cegger csc = device_lookup_private(&spif_cd, card); 344 1.1 mrg if (sc == NULL || csc == NULL) 345 1.1 mrg return (ENXIO); 346 1.1 mrg 347 1.1 mrg if (port >= sc->sc_nports) 348 1.1 mrg return (ENXIO); 349 1.1 mrg 350 1.1 mrg sp = &sc->sc_port[port]; 351 1.1 mrg tp = sp->sp_tty; 352 1.1 mrg tp->t_dev = dev; 353 1.1 mrg 354 1.8 elad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 355 1.8 elad return (EBUSY); 356 1.8 elad 357 1.35 riastrad ttylock(tp); 358 1.1 mrg if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 359 1.1 mrg ttychars(tp); 360 1.1 mrg tp->t_iflag = TTYDEF_IFLAG; 361 1.1 mrg tp->t_oflag = TTYDEF_OFLAG; 362 1.1 mrg tp->t_cflag = TTYDEF_CFLAG; 363 1.1 mrg if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) 364 1.1 mrg SET(tp->t_cflag, CLOCAL); 365 1.1 mrg if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) 366 1.1 mrg SET(tp->t_cflag, CRTSCTS); 367 1.1 mrg if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) 368 1.1 mrg SET(tp->t_cflag, MDMBUF); 369 1.1 mrg tp->t_lflag = TTYDEF_LFLAG; 370 1.1 mrg tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 371 1.1 mrg 372 1.1 mrg sp->sp_rput = sp->sp_rget = sp->sp_rbuf; 373 1.1 mrg 374 1.1 mrg STC_WRITE(csc, STC_CAR, sp->sp_channel); 375 1.1 mrg stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 376 1.1 mrg STC_WRITE(csc, STC_CAR, sp->sp_channel); 377 1.1 mrg 378 1.1 mrg stty_param(tp, &tp->t_termios); 379 1.1 mrg 380 1.1 mrg ttsetwater(tp); 381 1.1 mrg 382 1.1 mrg STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); 383 1.1 mrg 384 1.1 mrg if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) 385 1.1 mrg SET(tp->t_state, TS_CARR_ON); 386 1.1 mrg else 387 1.1 mrg CLR(tp->t_state, TS_CARR_ON); 388 1.1 mrg } 389 1.1 mrg 390 1.1 mrg if (!ISSET(flags, O_NONBLOCK)) { 391 1.1 mrg while (!ISSET(tp->t_cflag, CLOCAL) && 392 1.1 mrg !ISSET(tp->t_state, TS_CARR_ON)) { 393 1.1 mrg int error; 394 1.16 ad error = ttysleep(tp, &tp->t_rawcv, true, 0); 395 1.1 mrg if (error != 0) { 396 1.35 riastrad ttyunlock(tp); 397 1.1 mrg return (error); 398 1.1 mrg } 399 1.1 mrg } 400 1.1 mrg } 401 1.35 riastrad ttyunlock(tp); 402 1.1 mrg 403 1.1 mrg return ((*tp->t_linesw->l_open)(dev, tp)); 404 1.1 mrg } 405 1.1 mrg 406 1.1 mrg int 407 1.17 cegger stty_close(dev_t dev, int flags, int mode, struct lwp *l) 408 1.1 mrg { 409 1.17 cegger struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); 410 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 411 1.1 mrg struct spif_softc *csc = sp->sp_sc; 412 1.1 mrg struct tty *tp = sp->sp_tty; 413 1.1 mrg int port = SPIF_PORT(dev); 414 1.1 mrg int s; 415 1.1 mrg 416 1.1 mrg (*tp->t_linesw->l_close)(tp, flags); 417 1.1 mrg s = spltty(); 418 1.1 mrg 419 1.1 mrg if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { 420 1.1 mrg stty_modem_control(sp, 0, DMSET); 421 1.1 mrg STC_WRITE(csc, STC_CAR, port); 422 1.1 mrg STC_WRITE(csc, STC_CCR, 423 1.1 mrg CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 424 1.1 mrg } 425 1.1 mrg 426 1.1 mrg splx(s); 427 1.1 mrg ttyclose(tp); 428 1.1 mrg return (0); 429 1.1 mrg } 430 1.1 mrg 431 1.1 mrg int 432 1.17 cegger stty_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 433 1.1 mrg { 434 1.18 drochner struct stty_softc *stc = device_lookup_private(&stty_cd, 435 1.18 drochner SPIF_CARD(dev)); 436 1.1 mrg struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; 437 1.1 mrg struct spif_softc *sc = sp->sp_sc; 438 1.1 mrg struct tty *tp = sp->sp_tty; 439 1.1 mrg int error; 440 1.1 mrg 441 1.4 christos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); 442 1.1 mrg if (error >= 0) 443 1.1 mrg return (error); 444 1.1 mrg 445 1.4 christos error = ttioctl(tp, cmd, data, flags, l); 446 1.1 mrg if (error >= 0) 447 1.1 mrg return (error); 448 1.1 mrg 449 1.1 mrg error = 0; 450 1.1 mrg 451 1.1 mrg switch (cmd) { 452 1.1 mrg case TIOCSBRK: 453 1.1 mrg SET(sp->sp_flags, STTYF_SET_BREAK); 454 1.1 mrg STC_WRITE(sc, STC_CAR, sp->sp_channel); 455 1.1 mrg STC_WRITE(sc, STC_SRER, 456 1.1 mrg STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 457 1.1 mrg break; 458 1.1 mrg case TIOCCBRK: 459 1.1 mrg SET(sp->sp_flags, STTYF_CLR_BREAK); 460 1.1 mrg STC_WRITE(sc, STC_CAR, sp->sp_channel); 461 1.1 mrg STC_WRITE(sc, STC_SRER, 462 1.1 mrg STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 463 1.1 mrg break; 464 1.1 mrg case TIOCSDTR: 465 1.1 mrg stty_modem_control(sp, TIOCM_DTR, DMBIS); 466 1.1 mrg break; 467 1.1 mrg case TIOCCDTR: 468 1.1 mrg stty_modem_control(sp, TIOCM_DTR, DMBIC); 469 1.1 mrg break; 470 1.1 mrg case TIOCMBIS: 471 1.1 mrg stty_modem_control(sp, *((int *)data), DMBIS); 472 1.1 mrg break; 473 1.1 mrg case TIOCMBIC: 474 1.1 mrg stty_modem_control(sp, *((int *)data), DMBIC); 475 1.1 mrg break; 476 1.1 mrg case TIOCMGET: 477 1.1 mrg *((int *)data) = stty_modem_control(sp, 0, DMGET); 478 1.1 mrg break; 479 1.1 mrg case TIOCMSET: 480 1.1 mrg stty_modem_control(sp, *((int *)data), DMSET); 481 1.1 mrg break; 482 1.1 mrg case TIOCGFLAGS: 483 1.1 mrg *((int *)data) = sp->sp_openflags; 484 1.1 mrg break; 485 1.1 mrg case TIOCSFLAGS: 486 1.9 elad if (kauth_authorize_device_tty(l->l_cred, 487 1.9 elad KAUTH_DEVICE_TTY_PRIVSET, tp)) 488 1.1 mrg error = EPERM; 489 1.1 mrg else 490 1.1 mrg sp->sp_openflags = *((int *)data) & 491 1.1 mrg (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 492 1.1 mrg TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 493 1.1 mrg break; 494 1.1 mrg default: 495 1.1 mrg error = ENOTTY; 496 1.1 mrg } 497 1.1 mrg 498 1.1 mrg return (error); 499 1.1 mrg } 500 1.1 mrg 501 1.1 mrg int 502 1.21 dsl stty_modem_control(struct stty_port *sp, int bits, int how) 503 1.1 mrg { 504 1.1 mrg struct spif_softc *csc = sp->sp_sc; 505 1.1 mrg struct tty *tp = sp->sp_tty; 506 1.1 mrg int s, msvr; 507 1.1 mrg 508 1.1 mrg s = spltty(); 509 1.1 mrg STC_WRITE(csc, STC_CAR, sp->sp_channel); 510 1.1 mrg 511 1.1 mrg switch (how) { 512 1.1 mrg case DMGET: 513 1.1 mrg bits = TIOCM_LE; 514 1.1 mrg if (DTR_READ(csc, sp->sp_channel)) 515 1.1 mrg bits |= TIOCM_DTR; 516 1.1 mrg msvr = STC_READ(csc, STC_MSVR); 517 1.1 mrg if (ISSET(msvr, CD180_MSVR_DSR)) 518 1.1 mrg bits |= TIOCM_DSR; 519 1.1 mrg if (ISSET(msvr, CD180_MSVR_CD)) 520 1.1 mrg bits |= TIOCM_CD; 521 1.1 mrg if (ISSET(msvr, CD180_MSVR_CTS)) 522 1.1 mrg bits |= TIOCM_CTS; 523 1.1 mrg if (ISSET(msvr, CD180_MSVR_RTS)) 524 1.1 mrg bits |= TIOCM_RTS; 525 1.1 mrg break; 526 1.1 mrg case DMSET: 527 1.1 mrg DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0); 528 1.1 mrg if (ISSET(bits, TIOCM_RTS)) 529 1.1 mrg STC_WRITE(csc, STC_MSVR, 530 1.1 mrg STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 531 1.1 mrg else 532 1.1 mrg STC_WRITE(csc, STC_MSVR, 533 1.1 mrg STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 534 1.1 mrg break; 535 1.1 mrg case DMBIS: 536 1.1 mrg if (ISSET(bits, TIOCM_DTR)) 537 1.1 mrg DTR_WRITE(csc, sp->sp_channel, 1); 538 1.1 mrg if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) 539 1.1 mrg STC_WRITE(csc, STC_MSVR, 540 1.1 mrg STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 541 1.1 mrg break; 542 1.1 mrg case DMBIC: 543 1.1 mrg if (ISSET(bits, TIOCM_DTR)) 544 1.1 mrg DTR_WRITE(csc, sp->sp_channel, 0); 545 1.1 mrg if (ISSET(bits, TIOCM_RTS)) 546 1.1 mrg STC_WRITE(csc, STC_MSVR, 547 1.1 mrg STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 548 1.1 mrg break; 549 1.1 mrg } 550 1.1 mrg 551 1.1 mrg splx(s); 552 1.1 mrg return (bits); 553 1.1 mrg } 554 1.1 mrg 555 1.1 mrg int 556 1.17 cegger stty_param(struct tty *tp, struct termios *t) 557 1.1 mrg { 558 1.18 drochner struct stty_softc *st = device_lookup_private(&stty_cd, 559 1.18 drochner SPIF_CARD(tp->t_dev)); 560 1.1 mrg struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; 561 1.1 mrg struct spif_softc *sc = sp->sp_sc; 562 1.27 mrg uint8_t rbprl = 0, rbprh = 0, tbprl = 0, tbprh = 0; 563 1.1 mrg int s, opt; 564 1.1 mrg 565 1.1 mrg if (t->c_ospeed && 566 1.1 mrg stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) 567 1.1 mrg return (EINVAL); 568 1.1 mrg 569 1.1 mrg if (t->c_ispeed && 570 1.1 mrg stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) 571 1.1 mrg return (EINVAL); 572 1.1 mrg 573 1.1 mrg s = spltty(); 574 1.1 mrg 575 1.1 mrg /* hang up line if ospeed is zero, otherwise raise DTR */ 576 1.1 mrg stty_modem_control(sp, TIOCM_DTR, 577 1.1 mrg (t->c_ospeed == 0 ? DMBIC : DMBIS)); 578 1.1 mrg 579 1.1 mrg STC_WRITE(sc, STC_CAR, sp->sp_channel); 580 1.1 mrg 581 1.1 mrg opt = 0; 582 1.1 mrg if (ISSET(t->c_cflag, PARENB)) { 583 1.1 mrg opt |= CD180_COR1_PARMODE_NORMAL; 584 1.1 mrg opt |= (ISSET(t->c_cflag, PARODD) ? 585 1.1 mrg CD180_COR1_ODDPAR : 586 1.1 mrg CD180_COR1_EVENPAR); 587 1.1 mrg } 588 1.1 mrg else 589 1.1 mrg opt |= CD180_COR1_PARMODE_NO; 590 1.1 mrg 591 1.1 mrg if (!ISSET(t->c_iflag, INPCK)) 592 1.1 mrg opt |= CD180_COR1_IGNPAR; 593 1.1 mrg 594 1.1 mrg if (ISSET(t->c_cflag, CSTOPB)) 595 1.1 mrg opt |= CD180_COR1_STOP2; 596 1.1 mrg 597 1.1 mrg switch (t->c_cflag & CSIZE) { 598 1.1 mrg case CS5: 599 1.1 mrg opt |= CD180_COR1_CS5; 600 1.1 mrg break; 601 1.1 mrg case CS6: 602 1.1 mrg opt |= CD180_COR1_CS6; 603 1.1 mrg break; 604 1.1 mrg case CS7: 605 1.1 mrg opt |= CD180_COR1_CS7; 606 1.1 mrg break; 607 1.1 mrg default: 608 1.1 mrg opt |= CD180_COR1_CS8; 609 1.1 mrg break; 610 1.1 mrg } 611 1.1 mrg STC_WRITE(sc, STC_COR1, opt); 612 1.1 mrg stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1); 613 1.1 mrg 614 1.1 mrg opt = CD180_COR2_ETC; 615 1.1 mrg if (ISSET(t->c_cflag, CRTSCTS)) 616 1.1 mrg opt |= CD180_COR2_CTSAE; 617 1.1 mrg STC_WRITE(sc, STC_COR2, opt); 618 1.1 mrg stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2); 619 1.1 mrg 620 1.1 mrg STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD); 621 1.1 mrg stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3); 622 1.1 mrg 623 1.1 mrg STC_WRITE(sc, STC_SCHR1, 0x11); 624 1.1 mrg STC_WRITE(sc, STC_SCHR2, 0x13); 625 1.1 mrg STC_WRITE(sc, STC_SCHR3, 0x11); 626 1.1 mrg STC_WRITE(sc, STC_SCHR4, 0x13); 627 1.1 mrg STC_WRITE(sc, STC_RTPR, 0x12); 628 1.1 mrg 629 1.1 mrg STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD); 630 1.1 mrg STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD); 631 1.1 mrg STC_WRITE(sc, STC_MCR, 0); 632 1.1 mrg 633 1.1 mrg if (t->c_ospeed) { 634 1.1 mrg STC_WRITE(sc, STC_TBPRH, tbprh); 635 1.1 mrg STC_WRITE(sc, STC_TBPRL, tbprl); 636 1.1 mrg } 637 1.1 mrg 638 1.1 mrg if (t->c_ispeed) { 639 1.1 mrg STC_WRITE(sc, STC_RBPRH, rbprh); 640 1.1 mrg STC_WRITE(sc, STC_RBPRL, rbprl); 641 1.1 mrg } 642 1.1 mrg 643 1.1 mrg stty_write_ccr(sc, CD180_CCR_CMD_CHAN | 644 1.1 mrg CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); 645 1.1 mrg 646 1.1 mrg sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD; 647 1.1 mrg 648 1.1 mrg splx(s); 649 1.1 mrg return (0); 650 1.1 mrg } 651 1.1 mrg 652 1.1 mrg int 653 1.17 cegger stty_read(dev_t dev, struct uio *uio, int flags) 654 1.1 mrg { 655 1.17 cegger struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); 656 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 657 1.1 mrg struct tty *tp = sp->sp_tty; 658 1.1 mrg 659 1.1 mrg return ((*tp->t_linesw->l_read)(tp, uio, flags)); 660 1.1 mrg } 661 1.1 mrg 662 1.1 mrg int 663 1.17 cegger stty_write(dev_t dev, struct uio *uio, int flags) 664 1.1 mrg { 665 1.17 cegger struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); 666 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 667 1.1 mrg struct tty *tp = sp->sp_tty; 668 1.1 mrg 669 1.1 mrg return ((*tp->t_linesw->l_write)(tp, uio, flags)); 670 1.1 mrg } 671 1.1 mrg 672 1.1 mrg int 673 1.17 cegger stty_poll(dev_t dev, int events, struct lwp *l) 674 1.1 mrg { 675 1.17 cegger struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); 676 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 677 1.1 mrg struct tty *tp = sp->sp_tty; 678 1.2 perry 679 1.4 christos return ((*tp->t_linesw->l_poll)(tp, events, l)); 680 1.1 mrg } 681 1.1 mrg 682 1.1 mrg struct tty * 683 1.17 cegger stty_tty(dev_t dev) 684 1.1 mrg { 685 1.17 cegger struct stty_softc *sc = device_lookup_private(&stty_cd, SPIF_CARD(dev)); 686 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 687 1.1 mrg 688 1.1 mrg return (sp->sp_tty); 689 1.1 mrg } 690 1.1 mrg 691 1.1 mrg void 692 1.17 cegger stty_stop(struct tty *tp, int flags) 693 1.1 mrg { 694 1.18 drochner struct stty_softc *sc = device_lookup_private(&stty_cd, 695 1.18 drochner SPIF_CARD(tp->t_dev)); 696 1.1 mrg struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; 697 1.1 mrg int s; 698 1.1 mrg 699 1.1 mrg s = spltty(); 700 1.1 mrg if (ISSET(tp->t_state, TS_BUSY)) { 701 1.1 mrg if (!ISSET(tp->t_state, TS_TTSTOP)) 702 1.1 mrg SET(tp->t_state, TS_FLUSH); 703 1.1 mrg SET(sp->sp_flags, STTYF_STOP); 704 1.1 mrg } 705 1.1 mrg splx(s); 706 1.1 mrg } 707 1.1 mrg 708 1.1 mrg void 709 1.17 cegger stty_start(struct tty *tp) 710 1.1 mrg { 711 1.18 drochner struct stty_softc *stc = device_lookup_private(&stty_cd, 712 1.18 drochner SPIF_CARD(tp->t_dev)); 713 1.1 mrg struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; 714 1.1 mrg struct spif_softc *sc = sp->sp_sc; 715 1.1 mrg int s; 716 1.1 mrg 717 1.1 mrg s = spltty(); 718 1.1 mrg 719 1.1 mrg if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { 720 1.14 ad if (ttypull(tp)) { 721 1.1 mrg sp->sp_txc = ndqb(&tp->t_outq, 0); 722 1.1 mrg sp->sp_txp = tp->t_outq.c_cf; 723 1.1 mrg SET(tp->t_state, TS_BUSY); 724 1.1 mrg STC_WRITE(sc, STC_CAR, sp->sp_channel); 725 1.1 mrg STC_WRITE(sc, STC_SRER, 726 1.1 mrg STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 727 1.1 mrg } 728 1.1 mrg } 729 1.1 mrg 730 1.1 mrg splx(s); 731 1.1 mrg } 732 1.1 mrg 733 1.1 mrg int 734 1.20 dsl spif_stcintr_rxexception(struct spif_softc *sc, int *needsoftp) 735 1.1 mrg { 736 1.1 mrg struct stty_port *sp; 737 1.25 tsutsui uint8_t channel, *ptr; 738 1.1 mrg 739 1.1 mrg channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 740 1.1 mrg sp = &sc->sc_ttys->sc_port[channel]; 741 1.1 mrg ptr = sp->sp_rput; 742 1.1 mrg *ptr++ = STC_READ(sc, STC_RCSR); 743 1.1 mrg *ptr++ = STC_READ(sc, STC_RDR); 744 1.1 mrg if (ptr == sp->sp_rend) 745 1.1 mrg ptr = sp->sp_rbuf; 746 1.1 mrg if (ptr == sp->sp_rget) { 747 1.1 mrg if (ptr == sp->sp_rbuf) 748 1.1 mrg ptr = sp->sp_rend; 749 1.1 mrg ptr -= 2; 750 1.1 mrg SET(sp->sp_flags, STTYF_RING_OVERFLOW); 751 1.1 mrg } 752 1.1 mrg STC_WRITE(sc, STC_EOSRR, 0); 753 1.1 mrg *needsoftp = 1; 754 1.1 mrg sp->sp_rput = ptr; 755 1.1 mrg return (1); 756 1.1 mrg } 757 1.1 mrg 758 1.1 mrg int 759 1.20 dsl spif_stcintr_rx(struct spif_softc *sc, int *needsoftp) 760 1.1 mrg { 761 1.1 mrg struct stty_port *sp; 762 1.29 martin uint8_t channel, *ptr, cnt; 763 1.1 mrg int i; 764 1.1 mrg 765 1.1 mrg channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 766 1.1 mrg sp = &sc->sc_ttys->sc_port[channel]; 767 1.1 mrg ptr = sp->sp_rput; 768 1.1 mrg cnt = STC_READ(sc, STC_RDCR); 769 1.1 mrg for (i = 0; i < cnt; i++) { 770 1.1 mrg *ptr++ = 0; 771 1.29 martin (void)STC_READ(sc, STC_RCSR); 772 1.1 mrg *ptr++ = STC_READ(sc, STC_RDR); 773 1.1 mrg if (ptr == sp->sp_rend) 774 1.1 mrg ptr = sp->sp_rbuf; 775 1.1 mrg if (ptr == sp->sp_rget) { 776 1.1 mrg if (ptr == sp->sp_rbuf) 777 1.1 mrg ptr = sp->sp_rend; 778 1.1 mrg ptr -= 2; 779 1.1 mrg SET(sp->sp_flags, STTYF_RING_OVERFLOW); 780 1.1 mrg break; 781 1.1 mrg } 782 1.1 mrg } 783 1.1 mrg STC_WRITE(sc, STC_EOSRR, 0); 784 1.1 mrg if (cnt) { 785 1.1 mrg *needsoftp = 1; 786 1.1 mrg sp->sp_rput = ptr; 787 1.1 mrg } 788 1.1 mrg return (1); 789 1.1 mrg } 790 1.1 mrg 791 1.1 mrg int 792 1.20 dsl spif_stcintr_tx(struct spif_softc *sc, int *needsoftp) 793 1.1 mrg { 794 1.1 mrg struct stty_port *sp; 795 1.25 tsutsui uint8_t channel, ch; 796 1.1 mrg int cnt = 0; 797 1.1 mrg 798 1.1 mrg channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 799 1.1 mrg sp = &sc->sc_ttys->sc_port[channel]; 800 1.1 mrg if (!ISSET(sp->sp_flags, STTYF_STOP)) { 801 1.1 mrg if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { 802 1.1 mrg STC_WRITE(sc, STC_TDR, 0); 803 1.1 mrg STC_WRITE(sc, STC_TDR, 0x81); 804 1.1 mrg CLR(sp->sp_flags, STTYF_SET_BREAK); 805 1.1 mrg cnt += 2; 806 1.1 mrg } 807 1.1 mrg if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { 808 1.1 mrg STC_WRITE(sc, STC_TDR, 0); 809 1.1 mrg STC_WRITE(sc, STC_TDR, 0x83); 810 1.1 mrg CLR(sp->sp_flags, STTYF_CLR_BREAK); 811 1.1 mrg cnt += 2; 812 1.1 mrg } 813 1.1 mrg 814 1.1 mrg while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { 815 1.1 mrg ch = *sp->sp_txp; 816 1.1 mrg sp->sp_txc--; 817 1.1 mrg sp->sp_txp++; 818 1.1 mrg 819 1.1 mrg if (ch == 0) { 820 1.1 mrg STC_WRITE(sc, STC_TDR, ch); 821 1.1 mrg cnt++; 822 1.1 mrg } 823 1.1 mrg STC_WRITE(sc, STC_TDR, ch); 824 1.1 mrg cnt++; 825 1.1 mrg } 826 1.1 mrg } 827 1.1 mrg 828 1.1 mrg if (sp->sp_txc == 0 || 829 1.1 mrg ISSET(sp->sp_flags, STTYF_STOP)) { 830 1.1 mrg STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) & 831 1.1 mrg (~CD180_SRER_TXD)); 832 1.1 mrg CLR(sp->sp_flags, STTYF_STOP); 833 1.1 mrg SET(sp->sp_flags, STTYF_DONE); 834 1.1 mrg *needsoftp = 1; 835 1.1 mrg } 836 1.1 mrg 837 1.1 mrg STC_WRITE(sc, STC_EOSRR, 0); 838 1.1 mrg 839 1.1 mrg return (1); 840 1.1 mrg } 841 1.1 mrg 842 1.1 mrg int 843 1.20 dsl spif_stcintr_mx(struct spif_softc *sc, int *needsoftp) 844 1.1 mrg { 845 1.1 mrg struct stty_port *sp; 846 1.25 tsutsui uint8_t channel, mcr; 847 1.1 mrg 848 1.1 mrg channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 849 1.1 mrg sp = &sc->sc_ttys->sc_port[channel]; 850 1.1 mrg mcr = STC_READ(sc, STC_MCR); 851 1.1 mrg if (mcr & CD180_MCR_CD) { 852 1.1 mrg SET(sp->sp_flags, STTYF_CDCHG); 853 1.1 mrg *needsoftp = 1; 854 1.1 mrg } 855 1.1 mrg STC_WRITE(sc, STC_MCR, 0); 856 1.1 mrg STC_WRITE(sc, STC_EOSRR, 0); 857 1.1 mrg return (1); 858 1.1 mrg } 859 1.1 mrg 860 1.1 mrg int 861 1.20 dsl spif_stcintr(void *vsc) 862 1.1 mrg { 863 1.1 mrg struct spif_softc *sc = (struct spif_softc *)vsc; 864 1.1 mrg int needsoft = 0, r = 0, i; 865 1.25 tsutsui uint8_t ar; 866 1.1 mrg 867 1.1 mrg for (i = 0; i < 8; i++) { 868 1.1 mrg ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK; 869 1.1 mrg if (ar == CD180_GSVR_RXGOOD) 870 1.1 mrg r |= spif_stcintr_rx(sc, &needsoft); 871 1.1 mrg else if (ar == CD180_GSVR_RXEXCEPTION) 872 1.1 mrg r |= spif_stcintr_rxexception(sc, &needsoft); 873 1.1 mrg } 874 1.1 mrg 875 1.1 mrg for (i = 0; i < 8; i++) { 876 1.1 mrg ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK; 877 1.1 mrg if (ar == CD180_GSVR_TXDATA) 878 1.1 mrg r |= spif_stcintr_tx(sc, &needsoft); 879 1.1 mrg } 880 1.1 mrg 881 1.1 mrg for (i = 0; i < 8; i++) { 882 1.1 mrg ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK; 883 1.1 mrg if (ar == CD180_GSVR_STATCHG) 884 1.1 mrg r |= spif_stcintr_mx(sc, &needsoft); 885 1.1 mrg } 886 1.1 mrg 887 1.1 mrg if (needsoft) 888 1.11 ad softint_schedule(sc->sc_softih); 889 1.1 mrg return (r); 890 1.1 mrg } 891 1.1 mrg 892 1.1 mrg void 893 1.20 dsl spif_softintr(void *vsc) 894 1.1 mrg { 895 1.1 mrg struct spif_softc *sc = (struct spif_softc *)vsc; 896 1.1 mrg struct stty_softc *stc = sc->sc_ttys; 897 1.29 martin int i, data, s, flags; 898 1.25 tsutsui uint8_t stat, msvr; 899 1.1 mrg struct stty_port *sp; 900 1.1 mrg struct tty *tp; 901 1.1 mrg 902 1.1 mrg if (stc != NULL) { 903 1.1 mrg for (i = 0; i < stc->sc_nports; i++) { 904 1.1 mrg sp = &stc->sc_port[i]; 905 1.1 mrg tp = sp->sp_tty; 906 1.1 mrg 907 1.1 mrg if (!ISSET(tp->t_state, TS_ISOPEN)) 908 1.1 mrg continue; 909 1.1 mrg 910 1.1 mrg while (sp->sp_rget != sp->sp_rput) { 911 1.1 mrg stat = sp->sp_rget[0]; 912 1.1 mrg data = sp->sp_rget[1]; 913 1.1 mrg sp->sp_rget += 2; 914 1.1 mrg if (sp->sp_rget == sp->sp_rend) 915 1.1 mrg sp->sp_rget = sp->sp_rbuf; 916 1.1 mrg 917 1.1 mrg if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) 918 1.1 mrg data |= TTY_FE; 919 1.1 mrg 920 1.1 mrg if (stat & CD180_RCSR_PE) 921 1.1 mrg data |= TTY_PE; 922 1.1 mrg 923 1.1 mrg (*tp->t_linesw->l_rint)(data, tp); 924 1.1 mrg } 925 1.1 mrg 926 1.1 mrg s = splhigh(); 927 1.1 mrg flags = sp->sp_flags; 928 1.1 mrg CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | 929 1.1 mrg STTYF_RING_OVERFLOW); 930 1.1 mrg splx(s); 931 1.1 mrg 932 1.1 mrg if (ISSET(flags, STTYF_CDCHG)) { 933 1.1 mrg s = spltty(); 934 1.1 mrg STC_WRITE(sc, STC_CAR, i); 935 1.1 mrg msvr = STC_READ(sc, STC_MSVR); 936 1.1 mrg splx(s); 937 1.1 mrg 938 1.1 mrg sp->sp_carrier = msvr & CD180_MSVR_CD; 939 1.1 mrg (*tp->t_linesw->l_modem)(tp, 940 1.1 mrg sp->sp_carrier); 941 1.1 mrg } 942 1.1 mrg 943 1.1 mrg if (ISSET(flags, STTYF_RING_OVERFLOW)) { 944 1.1 mrg log(LOG_WARNING, "%s-%x: ring overflow\n", 945 1.28 mrg device_xname(stc->sc_dev), i); 946 1.1 mrg } 947 1.1 mrg 948 1.1 mrg if (ISSET(flags, STTYF_DONE)) { 949 1.1 mrg ndflush(&tp->t_outq, 950 1.1 mrg sp->sp_txp - tp->t_outq.c_cf); 951 1.1 mrg CLR(tp->t_state, TS_BUSY); 952 1.1 mrg (*tp->t_linesw->l_start)(tp); 953 1.1 mrg } 954 1.1 mrg } 955 1.1 mrg } 956 1.1 mrg } 957 1.1 mrg 958 1.1 mrg void 959 1.25 tsutsui stty_write_ccr(struct spif_softc *sc, uint8_t val) 960 1.1 mrg { 961 1.1 mrg int tries = 100000; 962 1.1 mrg 963 1.1 mrg while (STC_READ(sc, STC_CCR) && tries--) 964 1.1 mrg /*EMPTY*/; 965 1.1 mrg if (tries == 0) 966 1.28 mrg aprint_error_dev(sc->sc_dev, "ccr timeout\n"); 967 1.1 mrg STC_WRITE(sc, STC_CCR, val); 968 1.1 mrg } 969 1.1 mrg 970 1.1 mrg int 971 1.25 tsutsui stty_compute_baud(speed_t speed, int clock, uint8_t *bprlp, uint8_t *bprhp) 972 1.1 mrg { 973 1.25 tsutsui uint32_t rate; 974 1.1 mrg 975 1.1 mrg rate = (2 * clock) / (16 * speed); 976 1.1 mrg if (rate & 1) 977 1.1 mrg rate = (rate >> 1) + 1; 978 1.1 mrg else 979 1.1 mrg rate = rate >> 1; 980 1.1 mrg 981 1.1 mrg if (rate > 0xffff || rate == 0) 982 1.1 mrg return (1); 983 1.1 mrg 984 1.1 mrg *bprlp = rate & 0xff; 985 1.1 mrg *bprhp = (rate >> 8) & 0xff; 986 1.1 mrg return (0); 987 1.1 mrg } 988 1.1 mrg 989 1.1 mrg int 990 1.23 cegger sbpp_match(device_t parent, cfdata_t vcf, void *aux) 991 1.1 mrg { 992 1.18 drochner struct spif_softc *sc = device_private(parent); 993 1.1 mrg 994 1.1 mrg return (aux == sbpp_match && sc->sc_bpps == NULL); 995 1.1 mrg } 996 1.1 mrg 997 1.1 mrg void 998 1.23 cegger sbpp_attach(device_t parent, device_t dev, void *aux) 999 1.1 mrg { 1000 1.18 drochner struct spif_softc *sc = device_private(parent); 1001 1.18 drochner struct sbpp_softc *psc = device_private(dev); 1002 1.1 mrg int port; 1003 1.1 mrg 1004 1.1 mrg sc->sc_bpps = psc; 1005 1.1 mrg 1006 1.1 mrg for (port = 0; port < sc->sc_npar; port++) { 1007 1.1 mrg } 1008 1.1 mrg 1009 1.1 mrg psc->sc_nports = port; 1010 1.1 mrg printf(": %d port%s\n", port, port == 1 ? "" : "s"); 1011 1.1 mrg } 1012 1.1 mrg 1013 1.1 mrg int 1014 1.20 dsl sbpp_open(dev_t dev, int flags, int mode, struct lwp *l) 1015 1.1 mrg { 1016 1.1 mrg return (ENXIO); 1017 1.1 mrg } 1018 1.1 mrg 1019 1.1 mrg int 1020 1.20 dsl sbpp_close(dev_t dev, int flags, int mode, struct lwp *l) 1021 1.1 mrg { 1022 1.1 mrg return (ENXIO); 1023 1.1 mrg } 1024 1.1 mrg 1025 1.1 mrg int 1026 1.20 dsl spif_ppcintr(void *v) 1027 1.1 mrg { 1028 1.1 mrg return (0); 1029 1.1 mrg } 1030 1.1 mrg 1031 1.1 mrg int 1032 1.20 dsl sbpp_read(dev_t dev, struct uio *uio, int flags) 1033 1.1 mrg { 1034 1.1 mrg return (sbpp_rw(dev, uio)); 1035 1.1 mrg } 1036 1.1 mrg 1037 1.1 mrg int 1038 1.20 dsl sbpp_write(dev_t dev, struct uio *uio, int flags) 1039 1.1 mrg { 1040 1.1 mrg return (sbpp_rw(dev, uio)); 1041 1.1 mrg } 1042 1.1 mrg 1043 1.1 mrg int 1044 1.20 dsl sbpp_rw(dev_t dev, struct uio *uio) 1045 1.1 mrg { 1046 1.1 mrg return (ENXIO); 1047 1.1 mrg } 1048 1.1 mrg 1049 1.1 mrg int 1050 1.20 dsl sbpp_poll(dev_t dev, int events, struct lwp *l) 1051 1.1 mrg { 1052 1.4 christos return (seltrue(dev, events, l)); 1053 1.1 mrg } 1054 1.1 mrg 1055 1.1 mrg int 1056 1.20 dsl sbpp_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 1057 1.1 mrg { 1058 1.1 mrg int error; 1059 1.1 mrg 1060 1.1 mrg error = ENOTTY; 1061 1.1 mrg 1062 1.1 mrg return (error); 1063 1.1 mrg } 1064 1.1 mrg 1065 1.1 mrg #endif /* NSPIF */ 1066