1 /* $NetBSD: spif.c,v 1.6 2006/05/15 11:17:55 yamt 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.6 2006/05/15 11:17:55 yamt 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 64 #include <machine/bus.h> 65 #include <machine/intr.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 = softintr_establish(IPL_TTY, 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 int s; 339 340 if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs) 341 return (ENXIO); 342 343 sc = stty_cd.cd_devs[card]; 344 csc = spif_cd.cd_devs[card]; 345 if (sc == NULL || csc == NULL) 346 return (ENXIO); 347 348 if (port >= sc->sc_nports) 349 return (ENXIO); 350 351 sp = &sc->sc_port[port]; 352 tp = sp->sp_tty; 353 tp->t_dev = dev; 354 355 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 356 ttychars(tp); 357 tp->t_iflag = TTYDEF_IFLAG; 358 tp->t_oflag = TTYDEF_OFLAG; 359 tp->t_cflag = TTYDEF_CFLAG; 360 if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) 361 SET(tp->t_cflag, CLOCAL); 362 if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) 363 SET(tp->t_cflag, CRTSCTS); 364 if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) 365 SET(tp->t_cflag, MDMBUF); 366 tp->t_lflag = TTYDEF_LFLAG; 367 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 368 369 sp->sp_rput = sp->sp_rget = sp->sp_rbuf; 370 371 s = spltty(); 372 373 STC_WRITE(csc, STC_CAR, sp->sp_channel); 374 stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 375 STC_WRITE(csc, STC_CAR, sp->sp_channel); 376 377 stty_param(tp, &tp->t_termios); 378 379 ttsetwater(tp); 380 381 STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); 382 383 if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) 384 SET(tp->t_state, TS_CARR_ON); 385 else 386 CLR(tp->t_state, TS_CARR_ON); 387 } 388 else if (ISSET(tp->t_state, TS_XCLUDE) && 389 kauth_authorize_generic(l->l_proc->p_cred, KAUTH_GENERIC_ISSUSER, &l->l_proc->p_acflag) != 0) { 390 return (EBUSY); 391 } else { 392 s = spltty(); 393 } 394 395 if (!ISSET(flags, O_NONBLOCK)) { 396 while (!ISSET(tp->t_cflag, CLOCAL) && 397 !ISSET(tp->t_state, TS_CARR_ON)) { 398 int error; 399 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 400 "sttycd", 0); 401 if (error != 0) { 402 splx(s); 403 return (error); 404 } 405 } 406 } 407 408 splx(s); 409 410 return ((*tp->t_linesw->l_open)(dev, tp)); 411 } 412 413 int 414 stty_close(dev, flags, mode, l) 415 dev_t dev; 416 int flags; 417 int mode; 418 struct lwp *l; 419 { 420 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 421 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 422 struct spif_softc *csc = sp->sp_sc; 423 struct tty *tp = sp->sp_tty; 424 int port = SPIF_PORT(dev); 425 int s; 426 427 (*tp->t_linesw->l_close)(tp, flags); 428 s = spltty(); 429 430 if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { 431 stty_modem_control(sp, 0, DMSET); 432 STC_WRITE(csc, STC_CAR, port); 433 STC_WRITE(csc, STC_CCR, 434 CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 435 } 436 437 splx(s); 438 ttyclose(tp); 439 return (0); 440 } 441 442 int 443 stty_ioctl(dev, cmd, data, flags, l) 444 dev_t dev; 445 u_long cmd; 446 caddr_t data; 447 int flags; 448 struct lwp *l; 449 { 450 struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)]; 451 struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; 452 struct spif_softc *sc = sp->sp_sc; 453 struct tty *tp = sp->sp_tty; 454 int error; 455 456 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); 457 if (error >= 0) 458 return (error); 459 460 error = ttioctl(tp, cmd, data, flags, l); 461 if (error >= 0) 462 return (error); 463 464 error = 0; 465 466 switch (cmd) { 467 case TIOCSBRK: 468 SET(sp->sp_flags, STTYF_SET_BREAK); 469 STC_WRITE(sc, STC_CAR, sp->sp_channel); 470 STC_WRITE(sc, STC_SRER, 471 STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 472 break; 473 case TIOCCBRK: 474 SET(sp->sp_flags, STTYF_CLR_BREAK); 475 STC_WRITE(sc, STC_CAR, sp->sp_channel); 476 STC_WRITE(sc, STC_SRER, 477 STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 478 break; 479 case TIOCSDTR: 480 stty_modem_control(sp, TIOCM_DTR, DMBIS); 481 break; 482 case TIOCCDTR: 483 stty_modem_control(sp, TIOCM_DTR, DMBIC); 484 break; 485 case TIOCMBIS: 486 stty_modem_control(sp, *((int *)data), DMBIS); 487 break; 488 case TIOCMBIC: 489 stty_modem_control(sp, *((int *)data), DMBIC); 490 break; 491 case TIOCMGET: 492 *((int *)data) = stty_modem_control(sp, 0, DMGET); 493 break; 494 case TIOCMSET: 495 stty_modem_control(sp, *((int *)data), DMSET); 496 break; 497 case TIOCGFLAGS: 498 *((int *)data) = sp->sp_openflags; 499 break; 500 case TIOCSFLAGS: 501 if (kauth_authorize_generic(l->l_proc->p_cred, KAUTH_GENERIC_ISSUSER, &l->l_proc->p_acflag) ) 502 error = EPERM; 503 else 504 sp->sp_openflags = *((int *)data) & 505 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 506 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 507 break; 508 default: 509 error = ENOTTY; 510 } 511 512 return (error); 513 } 514 515 int 516 stty_modem_control(sp, bits, how) 517 struct stty_port *sp; 518 int bits, how; 519 { 520 struct spif_softc *csc = sp->sp_sc; 521 struct tty *tp = sp->sp_tty; 522 int s, msvr; 523 524 s = spltty(); 525 STC_WRITE(csc, STC_CAR, sp->sp_channel); 526 527 switch (how) { 528 case DMGET: 529 bits = TIOCM_LE; 530 if (DTR_READ(csc, sp->sp_channel)) 531 bits |= TIOCM_DTR; 532 msvr = STC_READ(csc, STC_MSVR); 533 if (ISSET(msvr, CD180_MSVR_DSR)) 534 bits |= TIOCM_DSR; 535 if (ISSET(msvr, CD180_MSVR_CD)) 536 bits |= TIOCM_CD; 537 if (ISSET(msvr, CD180_MSVR_CTS)) 538 bits |= TIOCM_CTS; 539 if (ISSET(msvr, CD180_MSVR_RTS)) 540 bits |= TIOCM_RTS; 541 break; 542 case DMSET: 543 DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0); 544 if (ISSET(bits, TIOCM_RTS)) 545 STC_WRITE(csc, STC_MSVR, 546 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 547 else 548 STC_WRITE(csc, STC_MSVR, 549 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 550 break; 551 case DMBIS: 552 if (ISSET(bits, TIOCM_DTR)) 553 DTR_WRITE(csc, sp->sp_channel, 1); 554 if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) 555 STC_WRITE(csc, STC_MSVR, 556 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 557 break; 558 case DMBIC: 559 if (ISSET(bits, TIOCM_DTR)) 560 DTR_WRITE(csc, sp->sp_channel, 0); 561 if (ISSET(bits, TIOCM_RTS)) 562 STC_WRITE(csc, STC_MSVR, 563 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 564 break; 565 } 566 567 splx(s); 568 return (bits); 569 } 570 571 int 572 stty_param(tp, t) 573 struct tty *tp; 574 struct termios *t; 575 { 576 struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 577 struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; 578 struct spif_softc *sc = sp->sp_sc; 579 u_int8_t rbprl, rbprh, tbprl, tbprh; 580 int s, opt; 581 582 if (t->c_ospeed && 583 stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) 584 return (EINVAL); 585 586 if (t->c_ispeed && 587 stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) 588 return (EINVAL); 589 590 s = spltty(); 591 592 /* hang up line if ospeed is zero, otherwise raise DTR */ 593 stty_modem_control(sp, TIOCM_DTR, 594 (t->c_ospeed == 0 ? DMBIC : DMBIS)); 595 596 STC_WRITE(sc, STC_CAR, sp->sp_channel); 597 598 opt = 0; 599 if (ISSET(t->c_cflag, PARENB)) { 600 opt |= CD180_COR1_PARMODE_NORMAL; 601 opt |= (ISSET(t->c_cflag, PARODD) ? 602 CD180_COR1_ODDPAR : 603 CD180_COR1_EVENPAR); 604 } 605 else 606 opt |= CD180_COR1_PARMODE_NO; 607 608 if (!ISSET(t->c_iflag, INPCK)) 609 opt |= CD180_COR1_IGNPAR; 610 611 if (ISSET(t->c_cflag, CSTOPB)) 612 opt |= CD180_COR1_STOP2; 613 614 switch (t->c_cflag & CSIZE) { 615 case CS5: 616 opt |= CD180_COR1_CS5; 617 break; 618 case CS6: 619 opt |= CD180_COR1_CS6; 620 break; 621 case CS7: 622 opt |= CD180_COR1_CS7; 623 break; 624 default: 625 opt |= CD180_COR1_CS8; 626 break; 627 } 628 STC_WRITE(sc, STC_COR1, opt); 629 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1); 630 631 opt = CD180_COR2_ETC; 632 if (ISSET(t->c_cflag, CRTSCTS)) 633 opt |= CD180_COR2_CTSAE; 634 STC_WRITE(sc, STC_COR2, opt); 635 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2); 636 637 STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD); 638 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3); 639 640 STC_WRITE(sc, STC_SCHR1, 0x11); 641 STC_WRITE(sc, STC_SCHR2, 0x13); 642 STC_WRITE(sc, STC_SCHR3, 0x11); 643 STC_WRITE(sc, STC_SCHR4, 0x13); 644 STC_WRITE(sc, STC_RTPR, 0x12); 645 646 STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD); 647 STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD); 648 STC_WRITE(sc, STC_MCR, 0); 649 650 if (t->c_ospeed) { 651 STC_WRITE(sc, STC_TBPRH, tbprh); 652 STC_WRITE(sc, STC_TBPRL, tbprl); 653 } 654 655 if (t->c_ispeed) { 656 STC_WRITE(sc, STC_RBPRH, rbprh); 657 STC_WRITE(sc, STC_RBPRL, rbprl); 658 } 659 660 stty_write_ccr(sc, CD180_CCR_CMD_CHAN | 661 CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); 662 663 sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD; 664 665 splx(s); 666 return (0); 667 } 668 669 int 670 stty_read(dev, uio, flags) 671 dev_t dev; 672 struct uio *uio; 673 int flags; 674 { 675 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 676 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 677 struct tty *tp = sp->sp_tty; 678 679 return ((*tp->t_linesw->l_read)(tp, uio, flags)); 680 } 681 682 int 683 stty_write(dev, uio, flags) 684 dev_t dev; 685 struct uio *uio; 686 int flags; 687 { 688 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 689 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 690 struct tty *tp = sp->sp_tty; 691 692 return ((*tp->t_linesw->l_write)(tp, uio, flags)); 693 } 694 695 int 696 stty_poll(dev, events, l) 697 dev_t dev; 698 int events; 699 struct lwp *l; 700 { 701 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 702 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 703 struct tty *tp = sp->sp_tty; 704 705 return ((*tp->t_linesw->l_poll)(tp, events, l)); 706 } 707 708 struct tty * 709 stty_tty(dev) 710 dev_t dev; 711 { 712 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 713 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 714 715 return (sp->sp_tty); 716 } 717 718 void 719 stty_stop(tp, flags) 720 struct tty *tp; 721 int flags; 722 { 723 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 724 struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; 725 int s; 726 727 s = spltty(); 728 if (ISSET(tp->t_state, TS_BUSY)) { 729 if (!ISSET(tp->t_state, TS_TTSTOP)) 730 SET(tp->t_state, TS_FLUSH); 731 SET(sp->sp_flags, STTYF_STOP); 732 } 733 splx(s); 734 } 735 736 void 737 stty_start(tp) 738 struct tty *tp; 739 { 740 struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 741 struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; 742 struct spif_softc *sc = sp->sp_sc; 743 int s; 744 745 s = spltty(); 746 747 if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { 748 if (tp->t_outq.c_cc <= tp->t_lowat) { 749 if (ISSET(tp->t_state, TS_ASLEEP)) { 750 CLR(tp->t_state, TS_ASLEEP); 751 wakeup(&tp->t_outq); 752 } 753 selwakeup(&tp->t_wsel); 754 } 755 if (tp->t_outq.c_cc) { 756 sp->sp_txc = ndqb(&tp->t_outq, 0); 757 sp->sp_txp = tp->t_outq.c_cf; 758 SET(tp->t_state, TS_BUSY); 759 STC_WRITE(sc, STC_CAR, sp->sp_channel); 760 STC_WRITE(sc, STC_SRER, 761 STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 762 } 763 } 764 765 splx(s); 766 } 767 768 int 769 spif_stcintr_rxexception(sc, needsoftp) 770 struct spif_softc *sc; 771 int *needsoftp; 772 { 773 struct stty_port *sp; 774 u_int8_t channel, *ptr; 775 776 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 777 sp = &sc->sc_ttys->sc_port[channel]; 778 ptr = sp->sp_rput; 779 *ptr++ = STC_READ(sc, STC_RCSR); 780 *ptr++ = STC_READ(sc, STC_RDR); 781 if (ptr == sp->sp_rend) 782 ptr = sp->sp_rbuf; 783 if (ptr == sp->sp_rget) { 784 if (ptr == sp->sp_rbuf) 785 ptr = sp->sp_rend; 786 ptr -= 2; 787 SET(sp->sp_flags, STTYF_RING_OVERFLOW); 788 } 789 STC_WRITE(sc, STC_EOSRR, 0); 790 *needsoftp = 1; 791 sp->sp_rput = ptr; 792 return (1); 793 } 794 795 int 796 spif_stcintr_rx(sc, needsoftp) 797 struct spif_softc *sc; 798 int *needsoftp; 799 { 800 struct stty_port *sp; 801 u_int8_t channel, *ptr, cnt, rcsr; 802 int i; 803 804 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 805 sp = &sc->sc_ttys->sc_port[channel]; 806 ptr = sp->sp_rput; 807 cnt = STC_READ(sc, STC_RDCR); 808 for (i = 0; i < cnt; i++) { 809 *ptr++ = 0; 810 rcsr = STC_READ(sc, STC_RCSR); 811 *ptr++ = STC_READ(sc, STC_RDR); 812 if (ptr == sp->sp_rend) 813 ptr = sp->sp_rbuf; 814 if (ptr == sp->sp_rget) { 815 if (ptr == sp->sp_rbuf) 816 ptr = sp->sp_rend; 817 ptr -= 2; 818 SET(sp->sp_flags, STTYF_RING_OVERFLOW); 819 break; 820 } 821 } 822 STC_WRITE(sc, STC_EOSRR, 0); 823 if (cnt) { 824 *needsoftp = 1; 825 sp->sp_rput = ptr; 826 } 827 return (1); 828 } 829 830 int 831 spif_stcintr_tx(sc, needsoftp) 832 struct spif_softc *sc; 833 int *needsoftp; 834 { 835 struct stty_port *sp; 836 u_int8_t channel, ch; 837 int cnt = 0; 838 839 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 840 sp = &sc->sc_ttys->sc_port[channel]; 841 if (!ISSET(sp->sp_flags, STTYF_STOP)) { 842 if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { 843 STC_WRITE(sc, STC_TDR, 0); 844 STC_WRITE(sc, STC_TDR, 0x81); 845 CLR(sp->sp_flags, STTYF_SET_BREAK); 846 cnt += 2; 847 } 848 if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { 849 STC_WRITE(sc, STC_TDR, 0); 850 STC_WRITE(sc, STC_TDR, 0x83); 851 CLR(sp->sp_flags, STTYF_CLR_BREAK); 852 cnt += 2; 853 } 854 855 while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { 856 ch = *sp->sp_txp; 857 sp->sp_txc--; 858 sp->sp_txp++; 859 860 if (ch == 0) { 861 STC_WRITE(sc, STC_TDR, ch); 862 cnt++; 863 } 864 STC_WRITE(sc, STC_TDR, ch); 865 cnt++; 866 } 867 } 868 869 if (sp->sp_txc == 0 || 870 ISSET(sp->sp_flags, STTYF_STOP)) { 871 STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) & 872 (~CD180_SRER_TXD)); 873 CLR(sp->sp_flags, STTYF_STOP); 874 SET(sp->sp_flags, STTYF_DONE); 875 *needsoftp = 1; 876 } 877 878 STC_WRITE(sc, STC_EOSRR, 0); 879 880 return (1); 881 } 882 883 int 884 spif_stcintr_mx(sc, needsoftp) 885 struct spif_softc *sc; 886 int *needsoftp; 887 { 888 struct stty_port *sp; 889 u_int8_t channel, mcr; 890 891 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 892 sp = &sc->sc_ttys->sc_port[channel]; 893 mcr = STC_READ(sc, STC_MCR); 894 if (mcr & CD180_MCR_CD) { 895 SET(sp->sp_flags, STTYF_CDCHG); 896 *needsoftp = 1; 897 } 898 STC_WRITE(sc, STC_MCR, 0); 899 STC_WRITE(sc, STC_EOSRR, 0); 900 return (1); 901 } 902 903 int 904 spif_stcintr(vsc) 905 void *vsc; 906 { 907 struct spif_softc *sc = (struct spif_softc *)vsc; 908 int needsoft = 0, r = 0, i; 909 u_int8_t ar; 910 911 for (i = 0; i < 8; i++) { 912 ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK; 913 if (ar == CD180_GSVR_RXGOOD) 914 r |= spif_stcintr_rx(sc, &needsoft); 915 else if (ar == CD180_GSVR_RXEXCEPTION) 916 r |= spif_stcintr_rxexception(sc, &needsoft); 917 } 918 919 for (i = 0; i < 8; i++) { 920 ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK; 921 if (ar == CD180_GSVR_TXDATA) 922 r |= spif_stcintr_tx(sc, &needsoft); 923 } 924 925 for (i = 0; i < 8; i++) { 926 ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK; 927 if (ar == CD180_GSVR_STATCHG) 928 r |= spif_stcintr_mx(sc, &needsoft); 929 } 930 931 if (needsoft) 932 softintr_schedule(sc->sc_softih); 933 return (r); 934 } 935 936 void 937 spif_softintr(vsc) 938 void *vsc; 939 { 940 struct spif_softc *sc = (struct spif_softc *)vsc; 941 struct stty_softc *stc = sc->sc_ttys; 942 int r = 0, i, data, s, flags; 943 u_int8_t stat, msvr; 944 struct stty_port *sp; 945 struct tty *tp; 946 947 if (stc != NULL) { 948 for (i = 0; i < stc->sc_nports; i++) { 949 sp = &stc->sc_port[i]; 950 tp = sp->sp_tty; 951 952 if (!ISSET(tp->t_state, TS_ISOPEN)) 953 continue; 954 955 while (sp->sp_rget != sp->sp_rput) { 956 stat = sp->sp_rget[0]; 957 data = sp->sp_rget[1]; 958 sp->sp_rget += 2; 959 if (sp->sp_rget == sp->sp_rend) 960 sp->sp_rget = sp->sp_rbuf; 961 962 if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) 963 data |= TTY_FE; 964 965 if (stat & CD180_RCSR_PE) 966 data |= TTY_PE; 967 968 (*tp->t_linesw->l_rint)(data, tp); 969 r = 1; 970 } 971 972 s = splhigh(); 973 flags = sp->sp_flags; 974 CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | 975 STTYF_RING_OVERFLOW); 976 splx(s); 977 978 if (ISSET(flags, STTYF_CDCHG)) { 979 s = spltty(); 980 STC_WRITE(sc, STC_CAR, i); 981 msvr = STC_READ(sc, STC_MSVR); 982 splx(s); 983 984 sp->sp_carrier = msvr & CD180_MSVR_CD; 985 (*tp->t_linesw->l_modem)(tp, 986 sp->sp_carrier); 987 r = 1; 988 } 989 990 if (ISSET(flags, STTYF_RING_OVERFLOW)) { 991 log(LOG_WARNING, "%s-%x: ring overflow\n", 992 stc->sc_dev.dv_xname, i); 993 r = 1; 994 } 995 996 if (ISSET(flags, STTYF_DONE)) { 997 ndflush(&tp->t_outq, 998 sp->sp_txp - tp->t_outq.c_cf); 999 CLR(tp->t_state, TS_BUSY); 1000 (*tp->t_linesw->l_start)(tp); 1001 r = 1; 1002 } 1003 } 1004 } 1005 } 1006 1007 void 1008 stty_write_ccr(sc, val) 1009 struct spif_softc *sc; 1010 u_int8_t val; 1011 { 1012 int tries = 100000; 1013 1014 while (STC_READ(sc, STC_CCR) && tries--) 1015 /*EMPTY*/; 1016 if (tries == 0) 1017 printf("%s: ccr timeout\n", sc->sc_dev.dv_xname); 1018 STC_WRITE(sc, STC_CCR, val); 1019 } 1020 1021 int 1022 stty_compute_baud(speed, clock, bprlp, bprhp) 1023 speed_t speed; 1024 int clock; 1025 u_int8_t *bprlp, *bprhp; 1026 { 1027 u_int32_t rate; 1028 1029 rate = (2 * clock) / (16 * speed); 1030 if (rate & 1) 1031 rate = (rate >> 1) + 1; 1032 else 1033 rate = rate >> 1; 1034 1035 if (rate > 0xffff || rate == 0) 1036 return (1); 1037 1038 *bprlp = rate & 0xff; 1039 *bprhp = (rate >> 8) & 0xff; 1040 return (0); 1041 } 1042 1043 int 1044 sbpp_match(parent, vcf, aux) 1045 struct device *parent; 1046 struct cfdata *vcf; 1047 void *aux; 1048 { 1049 struct spif_softc *sc = (struct spif_softc *)parent; 1050 1051 return (aux == sbpp_match && sc->sc_bpps == NULL); 1052 } 1053 1054 void 1055 sbpp_attach(parent, dev, aux) 1056 struct device *parent, *dev; 1057 void *aux; 1058 { 1059 struct spif_softc *sc = (struct spif_softc *)parent; 1060 struct sbpp_softc *psc = (struct sbpp_softc *)dev; 1061 int port; 1062 1063 sc->sc_bpps = psc; 1064 1065 for (port = 0; port < sc->sc_npar; port++) { 1066 } 1067 1068 psc->sc_nports = port; 1069 printf(": %d port%s\n", port, port == 1 ? "" : "s"); 1070 } 1071 1072 int 1073 sbpp_open(dev, flags, mode, l) 1074 dev_t dev; 1075 int flags; 1076 int mode; 1077 struct lwp *l; 1078 { 1079 return (ENXIO); 1080 } 1081 1082 int 1083 sbpp_close(dev, flags, mode, l) 1084 dev_t dev; 1085 int flags; 1086 int mode; 1087 struct lwp *l; 1088 { 1089 return (ENXIO); 1090 } 1091 1092 int 1093 spif_ppcintr(v) 1094 void *v; 1095 { 1096 return (0); 1097 } 1098 1099 int 1100 sbpp_read(dev, uio, flags) 1101 dev_t dev; 1102 struct uio *uio; 1103 int flags; 1104 { 1105 return (sbpp_rw(dev, uio)); 1106 } 1107 1108 int 1109 sbpp_write(dev, uio, flags) 1110 dev_t dev; 1111 struct uio *uio; 1112 int flags; 1113 { 1114 return (sbpp_rw(dev, uio)); 1115 } 1116 1117 int 1118 sbpp_rw(dev, uio) 1119 dev_t dev; 1120 struct uio *uio; 1121 { 1122 return (ENXIO); 1123 } 1124 1125 int 1126 sbpp_poll(dev, events, l) 1127 dev_t dev; 1128 int events; 1129 struct lwp *l; 1130 { 1131 return (seltrue(dev, events, l)); 1132 } 1133 1134 int 1135 sbpp_ioctl(dev, cmd, data, flags, l) 1136 dev_t dev; 1137 u_long cmd; 1138 caddr_t data; 1139 int flags; 1140 struct lwp *l; 1141 { 1142 int error; 1143 1144 error = ENOTTY; 1145 1146 return (error); 1147 } 1148 1149 #endif /* NSPIF */ 1150