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