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