1 /* $NetBSD: spif.c,v 1.4 2005/12/11 12:23:44 christos 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.4 2005/12/11 12:23:44 christos 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 63 #include <machine/bus.h> 64 #include <machine/intr.h> 65 #include <machine/autoconf.h> 66 #include <machine/promlib.h> 67 68 #include <dev/sbus/sbusvar.h> 69 70 #include <dev/sbus/spifvar.h> 71 #include <dev/sbus/spifreg.h> 72 73 74 /* Autoconfig stuff */ 75 76 CFATTACH_DECL(spif, sizeof(struct spif_softc), 77 spif_match, spif_attach, NULL, NULL); 78 79 CFATTACH_DECL(stty, sizeof(struct stty_softc), 80 stty_match, stty_attach, NULL, NULL); 81 82 CFATTACH_DECL(sbpp, sizeof(struct sbpp_softc), 83 sbpp_match, sbpp_attach, NULL, NULL); 84 85 extern struct cfdriver spif_cd; 86 extern struct cfdriver stty_cd; 87 extern struct cfdriver sbpp_cd; 88 89 dev_type_open(stty_open); 90 dev_type_close(stty_close); 91 dev_type_read(stty_read); 92 dev_type_write(stty_write); 93 dev_type_ioctl(stty_ioctl); 94 dev_type_stop(stty_stop); 95 dev_type_tty(stty_tty); 96 dev_type_poll(stty_poll); 97 98 const struct cdevsw stty_cdevsw = { 99 stty_open, stty_close, stty_read, stty_write, stty_ioctl, 100 stty_stop, stty_tty, stty_poll, nommap, ttykqfilter, D_TTY 101 }; 102 103 dev_type_open(sbpp_open); 104 dev_type_close(sbpp_close); 105 dev_type_read(sbpp_read); 106 dev_type_write(sbpp_write); 107 dev_type_ioctl(sbpp_ioctl); 108 dev_type_poll(sbpp_poll); 109 110 const struct cdevsw sbpp_cdevsw = { 111 sbpp_open, sbpp_close, sbpp_read, sbpp_write, sbpp_ioctl, 112 nostop, notty, sbpp_poll, nommap, nokqfilter, 113 }; 114 115 116 /* normal STC access */ 117 #define STC_WRITE(sc,r,v) \ 118 bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v)) 119 #define STC_READ(sc,r) \ 120 bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r)) 121 122 /* IACK STC access */ 123 #define ISTC_WRITE(sc,r,v) \ 124 bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v)) 125 #define ISTC_READ(sc,r) \ 126 bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r)) 127 128 /* PPC access */ 129 #define PPC_WRITE(sc,r,v) \ 130 bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v)) 131 #define PPC_READ(sc,r) \ 132 bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r)) 133 134 #define DTR_WRITE(sc,port,v) \ 135 do { \ 136 sc->sc_ttys->sc_port[(port)].sp_dtr = v; \ 137 bus_space_write_1((sc)->sc_bustag, \ 138 sc->sc_dtrh, port, (v == 0) ? 1 : 0); \ 139 } while (0) 140 141 #define DTR_READ(sc,port) ((sc)->sc_ttys->sc_port[(port)].sp_dtr) 142 143 144 int 145 spif_match(parent, vcf, aux) 146 struct device *parent; 147 struct cfdata *vcf; 148 void *aux; 149 { 150 struct sbus_attach_args *sa = aux; 151 152 if (strcmp(vcf->cf_name, sa->sa_name) && 153 strcmp("SUNW,spif", sa->sa_name)) 154 return (0); 155 return (1); 156 } 157 158 void 159 spif_attach(parent, self, aux) 160 struct device *parent, *self; 161 void *aux; 162 { 163 struct spif_softc *sc = (struct spif_softc *)self; 164 struct sbus_attach_args *sa = aux; 165 166 if (sa->sa_nintr != 2) { 167 printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); 168 return; 169 } 170 171 if (sa->sa_nreg != 1) { 172 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); 173 return; 174 } 175 176 sc->sc_bustag = sa->sa_bustag; 177 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 178 sa->sa_offset, sa->sa_size, 179 0, &sc->sc_regh) != 0) { 180 printf(": can't map registers\n"); 181 return; 182 } 183 184 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 185 DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { 186 printf(": can't map dtr regs\n"); 187 goto fail_unmapregs; 188 } 189 190 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 191 STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { 192 printf(": can't map dtr regs\n"); 193 goto fail_unmapregs; 194 } 195 196 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 197 ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { 198 printf(": can't map dtr regs\n"); 199 goto fail_unmapregs; 200 } 201 202 if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, 203 PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { 204 printf(": can't map dtr regs\n"); 205 goto fail_unmapregs; 206 } 207 208 sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, 209 sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); 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].oi_pri, IPL_SERIAL, spif_stcintr, sc); 217 if (sc->sc_stcih == NULL) { 218 printf(": failed to establish stc interrupt\n"); 219 goto fail_unmapregs; 220 } 221 222 sc->sc_softih = softintr_establish(IPL_TTY, spif_softintr, sc); 223 if (sc->sc_softih == NULL) { 224 printf(": can't get soft intr\n"); 225 goto fail_unmapregs; 226 } 227 228 sc->sc_node = sa->sa_node; 229 230 sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); 231 232 sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); 233 switch (sc->sc_osc) { 234 case SPIF_OSC10: 235 sc->sc_osc = 10000000; 236 break; 237 case SPIF_OSC9: 238 default: 239 sc->sc_osc = 9830400; 240 break; 241 } 242 243 sc->sc_nser = 8; 244 sc->sc_npar = 1; 245 246 sc->sc_rev2 = STC_READ(sc, STC_GFRCR); 247 STC_WRITE(sc, STC_GSVR, 0); 248 249 stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); 250 while (STC_READ(sc, STC_GSVR) != 0xff); 251 while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); 252 253 STC_WRITE(sc, STC_PPRH, CD180_PPRH); 254 STC_WRITE(sc, STC_PPRL, CD180_PPRL); 255 STC_WRITE(sc, STC_MSMR, SPIF_MSMR); 256 STC_WRITE(sc, STC_TSMR, SPIF_TSMR); 257 STC_WRITE(sc, STC_RSMR, SPIF_RSMR); 258 STC_WRITE(sc, STC_GSVR, 0); 259 STC_WRITE(sc, STC_GSCR1, 0); 260 STC_WRITE(sc, STC_GSCR2, 0); 261 STC_WRITE(sc, STC_GSCR3, 0); 262 263 printf(": rev %x chiprev %x osc %sMHz\n", 264 sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); 265 266 (void)config_found(self, stty_match, NULL); 267 (void)config_found(self, sbpp_match, NULL); 268 269 return; 270 271 fail_unmapregs: 272 bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); 273 } 274 275 int 276 stty_match(parent, vcf, aux) 277 struct device *parent; 278 struct cfdata *vcf; 279 void *aux; 280 { 281 struct spif_softc *sc = (struct spif_softc *)parent; 282 283 return (aux == stty_match && sc->sc_ttys == NULL); 284 } 285 286 void 287 stty_attach(parent, dev, aux) 288 struct device *parent, *dev; 289 void *aux; 290 { 291 struct spif_softc *sc = (struct spif_softc *)parent; 292 struct stty_softc *ssc = (struct stty_softc *)dev; 293 int port; 294 295 sc->sc_ttys = ssc; 296 297 for (port = 0; port < sc->sc_nser; port++) { 298 struct stty_port *sp = &ssc->sc_port[port]; 299 struct tty *tp; 300 301 DTR_WRITE(sc, port, 0); 302 303 tp = ttymalloc(); 304 305 tp->t_oproc = stty_start; 306 tp->t_param = stty_param; 307 308 sp->sp_tty = tp; 309 sp->sp_sc = sc; 310 sp->sp_channel = port; 311 312 sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); 313 if(sp->sp_rbuf == NULL) 314 break; 315 316 sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE; 317 } 318 319 ssc->sc_nports = port; 320 321 printf(": %d tty%s\n", port, port == 1 ? "" : "s"); 322 } 323 324 int 325 stty_open(dev, flags, mode, l) 326 dev_t dev; 327 int flags; 328 int mode; 329 struct lwp *l; 330 { 331 struct spif_softc *csc; 332 struct stty_softc *sc; 333 struct stty_port *sp; 334 struct tty *tp; 335 int card = SPIF_CARD(dev); 336 int port = SPIF_PORT(dev); 337 int s; 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 (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 355 ttychars(tp); 356 tp->t_iflag = TTYDEF_IFLAG; 357 tp->t_oflag = TTYDEF_OFLAG; 358 tp->t_cflag = TTYDEF_CFLAG; 359 if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL)) 360 SET(tp->t_cflag, CLOCAL); 361 if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS)) 362 SET(tp->t_cflag, CRTSCTS); 363 if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF)) 364 SET(tp->t_cflag, MDMBUF); 365 tp->t_lflag = TTYDEF_LFLAG; 366 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 367 368 sp->sp_rput = sp->sp_rget = sp->sp_rbuf; 369 370 s = spltty(); 371 372 STC_WRITE(csc, STC_CAR, sp->sp_channel); 373 stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 374 STC_WRITE(csc, STC_CAR, sp->sp_channel); 375 376 stty_param(tp, &tp->t_termios); 377 378 ttsetwater(tp); 379 380 STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD); 381 382 if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier) 383 SET(tp->t_state, TS_CARR_ON); 384 else 385 CLR(tp->t_state, TS_CARR_ON); 386 } 387 else if (ISSET(tp->t_state, TS_XCLUDE) && 388 suser(l->l_proc->p_ucred, &l->l_proc->p_acflag) != 0) { 389 return (EBUSY); 390 } else { 391 s = spltty(); 392 } 393 394 if (!ISSET(flags, O_NONBLOCK)) { 395 while (!ISSET(tp->t_cflag, CLOCAL) && 396 !ISSET(tp->t_state, TS_CARR_ON)) { 397 int error; 398 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 399 "sttycd", 0); 400 if (error != 0) { 401 splx(s); 402 return (error); 403 } 404 } 405 } 406 407 splx(s); 408 409 return ((*tp->t_linesw->l_open)(dev, tp)); 410 } 411 412 int 413 stty_close(dev, flags, mode, l) 414 dev_t dev; 415 int flags; 416 int mode; 417 struct lwp *l; 418 { 419 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 420 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 421 struct spif_softc *csc = sp->sp_sc; 422 struct tty *tp = sp->sp_tty; 423 int port = SPIF_PORT(dev); 424 int s; 425 426 (*tp->t_linesw->l_close)(tp, flags); 427 s = spltty(); 428 429 if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) { 430 stty_modem_control(sp, 0, DMSET); 431 STC_WRITE(csc, STC_CAR, port); 432 STC_WRITE(csc, STC_CCR, 433 CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN); 434 } 435 436 splx(s); 437 ttyclose(tp); 438 return (0); 439 } 440 441 int 442 stty_ioctl(dev, cmd, data, flags, l) 443 dev_t dev; 444 u_long cmd; 445 caddr_t data; 446 int flags; 447 struct lwp *l; 448 { 449 struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)]; 450 struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)]; 451 struct spif_softc *sc = sp->sp_sc; 452 struct tty *tp = sp->sp_tty; 453 int error; 454 455 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); 456 if (error >= 0) 457 return (error); 458 459 error = ttioctl(tp, cmd, data, flags, l); 460 if (error >= 0) 461 return (error); 462 463 error = 0; 464 465 switch (cmd) { 466 case TIOCSBRK: 467 SET(sp->sp_flags, STTYF_SET_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 TIOCCBRK: 473 SET(sp->sp_flags, STTYF_CLR_BREAK); 474 STC_WRITE(sc, STC_CAR, sp->sp_channel); 475 STC_WRITE(sc, STC_SRER, 476 STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 477 break; 478 case TIOCSDTR: 479 stty_modem_control(sp, TIOCM_DTR, DMBIS); 480 break; 481 case TIOCCDTR: 482 stty_modem_control(sp, TIOCM_DTR, DMBIC); 483 break; 484 case TIOCMBIS: 485 stty_modem_control(sp, *((int *)data), DMBIS); 486 break; 487 case TIOCMBIC: 488 stty_modem_control(sp, *((int *)data), DMBIC); 489 break; 490 case TIOCMGET: 491 *((int *)data) = stty_modem_control(sp, 0, DMGET); 492 break; 493 case TIOCMSET: 494 stty_modem_control(sp, *((int *)data), DMSET); 495 break; 496 case TIOCGFLAGS: 497 *((int *)data) = sp->sp_openflags; 498 break; 499 case TIOCSFLAGS: 500 if( suser(l->l_proc->p_ucred, &l->l_proc->p_acflag) ) 501 error = EPERM; 502 else 503 sp->sp_openflags = *((int *)data) & 504 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 505 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 506 break; 507 default: 508 error = ENOTTY; 509 } 510 511 return (error); 512 } 513 514 int 515 stty_modem_control(sp, bits, how) 516 struct stty_port *sp; 517 int bits, how; 518 { 519 struct spif_softc *csc = sp->sp_sc; 520 struct tty *tp = sp->sp_tty; 521 int s, msvr; 522 523 s = spltty(); 524 STC_WRITE(csc, STC_CAR, sp->sp_channel); 525 526 switch (how) { 527 case DMGET: 528 bits = TIOCM_LE; 529 if (DTR_READ(csc, sp->sp_channel)) 530 bits |= TIOCM_DTR; 531 msvr = STC_READ(csc, STC_MSVR); 532 if (ISSET(msvr, CD180_MSVR_DSR)) 533 bits |= TIOCM_DSR; 534 if (ISSET(msvr, CD180_MSVR_CD)) 535 bits |= TIOCM_CD; 536 if (ISSET(msvr, CD180_MSVR_CTS)) 537 bits |= TIOCM_CTS; 538 if (ISSET(msvr, CD180_MSVR_RTS)) 539 bits |= TIOCM_RTS; 540 break; 541 case DMSET: 542 DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0); 543 if (ISSET(bits, TIOCM_RTS)) 544 STC_WRITE(csc, STC_MSVR, 545 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 546 else 547 STC_WRITE(csc, STC_MSVR, 548 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 549 break; 550 case DMBIS: 551 if (ISSET(bits, TIOCM_DTR)) 552 DTR_WRITE(csc, sp->sp_channel, 1); 553 if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS)) 554 STC_WRITE(csc, STC_MSVR, 555 STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS)); 556 break; 557 case DMBIC: 558 if (ISSET(bits, TIOCM_DTR)) 559 DTR_WRITE(csc, sp->sp_channel, 0); 560 if (ISSET(bits, TIOCM_RTS)) 561 STC_WRITE(csc, STC_MSVR, 562 STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS); 563 break; 564 } 565 566 splx(s); 567 return (bits); 568 } 569 570 int 571 stty_param(tp, t) 572 struct tty *tp; 573 struct termios *t; 574 { 575 struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 576 struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)]; 577 struct spif_softc *sc = sp->sp_sc; 578 u_int8_t rbprl, rbprh, tbprl, tbprh; 579 int s, opt; 580 581 if (t->c_ospeed && 582 stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh)) 583 return (EINVAL); 584 585 if (t->c_ispeed && 586 stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh)) 587 return (EINVAL); 588 589 s = spltty(); 590 591 /* hang up line if ospeed is zero, otherwise raise DTR */ 592 stty_modem_control(sp, TIOCM_DTR, 593 (t->c_ospeed == 0 ? DMBIC : DMBIS)); 594 595 STC_WRITE(sc, STC_CAR, sp->sp_channel); 596 597 opt = 0; 598 if (ISSET(t->c_cflag, PARENB)) { 599 opt |= CD180_COR1_PARMODE_NORMAL; 600 opt |= (ISSET(t->c_cflag, PARODD) ? 601 CD180_COR1_ODDPAR : 602 CD180_COR1_EVENPAR); 603 } 604 else 605 opt |= CD180_COR1_PARMODE_NO; 606 607 if (!ISSET(t->c_iflag, INPCK)) 608 opt |= CD180_COR1_IGNPAR; 609 610 if (ISSET(t->c_cflag, CSTOPB)) 611 opt |= CD180_COR1_STOP2; 612 613 switch (t->c_cflag & CSIZE) { 614 case CS5: 615 opt |= CD180_COR1_CS5; 616 break; 617 case CS6: 618 opt |= CD180_COR1_CS6; 619 break; 620 case CS7: 621 opt |= CD180_COR1_CS7; 622 break; 623 default: 624 opt |= CD180_COR1_CS8; 625 break; 626 } 627 STC_WRITE(sc, STC_COR1, opt); 628 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1); 629 630 opt = CD180_COR2_ETC; 631 if (ISSET(t->c_cflag, CRTSCTS)) 632 opt |= CD180_COR2_CTSAE; 633 STC_WRITE(sc, STC_COR2, opt); 634 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2); 635 636 STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD); 637 stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3); 638 639 STC_WRITE(sc, STC_SCHR1, 0x11); 640 STC_WRITE(sc, STC_SCHR2, 0x13); 641 STC_WRITE(sc, STC_SCHR3, 0x11); 642 STC_WRITE(sc, STC_SCHR4, 0x13); 643 STC_WRITE(sc, STC_RTPR, 0x12); 644 645 STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD); 646 STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD); 647 STC_WRITE(sc, STC_MCR, 0); 648 649 if (t->c_ospeed) { 650 STC_WRITE(sc, STC_TBPRH, tbprh); 651 STC_WRITE(sc, STC_TBPRL, tbprl); 652 } 653 654 if (t->c_ispeed) { 655 STC_WRITE(sc, STC_RBPRH, rbprh); 656 STC_WRITE(sc, STC_RBPRL, rbprl); 657 } 658 659 stty_write_ccr(sc, CD180_CCR_CMD_CHAN | 660 CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN); 661 662 sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD; 663 664 splx(s); 665 return (0); 666 } 667 668 int 669 stty_read(dev, uio, flags) 670 dev_t dev; 671 struct uio *uio; 672 int flags; 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 struct tty *tp = sp->sp_tty; 677 678 return ((*tp->t_linesw->l_read)(tp, uio, flags)); 679 } 680 681 int 682 stty_write(dev, uio, flags) 683 dev_t dev; 684 struct uio *uio; 685 int flags; 686 { 687 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 688 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 689 struct tty *tp = sp->sp_tty; 690 691 return ((*tp->t_linesw->l_write)(tp, uio, flags)); 692 } 693 694 int 695 stty_poll(dev, events, l) 696 dev_t dev; 697 int events; 698 struct lwp *l; 699 { 700 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 701 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 702 struct tty *tp = sp->sp_tty; 703 704 return ((*tp->t_linesw->l_poll)(tp, events, l)); 705 } 706 707 struct tty * 708 stty_tty(dev) 709 dev_t dev; 710 { 711 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)]; 712 struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)]; 713 714 return (sp->sp_tty); 715 } 716 717 void 718 stty_stop(tp, flags) 719 struct tty *tp; 720 int flags; 721 { 722 struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 723 struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)]; 724 int s; 725 726 s = spltty(); 727 if (ISSET(tp->t_state, TS_BUSY)) { 728 if (!ISSET(tp->t_state, TS_TTSTOP)) 729 SET(tp->t_state, TS_FLUSH); 730 SET(sp->sp_flags, STTYF_STOP); 731 } 732 splx(s); 733 } 734 735 void 736 stty_start(tp) 737 struct tty *tp; 738 { 739 struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)]; 740 struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)]; 741 struct spif_softc *sc = sp->sp_sc; 742 int s; 743 744 s = spltty(); 745 746 if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) { 747 if (tp->t_outq.c_cc <= tp->t_lowat) { 748 if (ISSET(tp->t_state, TS_ASLEEP)) { 749 CLR(tp->t_state, TS_ASLEEP); 750 wakeup(&tp->t_outq); 751 } 752 selwakeup(&tp->t_wsel); 753 } 754 if (tp->t_outq.c_cc) { 755 sp->sp_txc = ndqb(&tp->t_outq, 0); 756 sp->sp_txp = tp->t_outq.c_cf; 757 SET(tp->t_state, TS_BUSY); 758 STC_WRITE(sc, STC_CAR, sp->sp_channel); 759 STC_WRITE(sc, STC_SRER, 760 STC_READ(sc, STC_SRER) | CD180_SRER_TXD); 761 } 762 } 763 764 splx(s); 765 } 766 767 int 768 spif_stcintr_rxexception(sc, needsoftp) 769 struct spif_softc *sc; 770 int *needsoftp; 771 { 772 struct stty_port *sp; 773 u_int8_t channel, *ptr; 774 775 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 776 sp = &sc->sc_ttys->sc_port[channel]; 777 ptr = sp->sp_rput; 778 *ptr++ = STC_READ(sc, STC_RCSR); 779 *ptr++ = STC_READ(sc, STC_RDR); 780 if (ptr == sp->sp_rend) 781 ptr = sp->sp_rbuf; 782 if (ptr == sp->sp_rget) { 783 if (ptr == sp->sp_rbuf) 784 ptr = sp->sp_rend; 785 ptr -= 2; 786 SET(sp->sp_flags, STTYF_RING_OVERFLOW); 787 } 788 STC_WRITE(sc, STC_EOSRR, 0); 789 *needsoftp = 1; 790 sp->sp_rput = ptr; 791 return (1); 792 } 793 794 int 795 spif_stcintr_rx(sc, needsoftp) 796 struct spif_softc *sc; 797 int *needsoftp; 798 { 799 struct stty_port *sp; 800 u_int8_t channel, *ptr, cnt, rcsr; 801 int i; 802 803 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 804 sp = &sc->sc_ttys->sc_port[channel]; 805 ptr = sp->sp_rput; 806 cnt = STC_READ(sc, STC_RDCR); 807 for (i = 0; i < cnt; i++) { 808 *ptr++ = 0; 809 rcsr = STC_READ(sc, STC_RCSR); 810 *ptr++ = STC_READ(sc, STC_RDR); 811 if (ptr == sp->sp_rend) 812 ptr = sp->sp_rbuf; 813 if (ptr == sp->sp_rget) { 814 if (ptr == sp->sp_rbuf) 815 ptr = sp->sp_rend; 816 ptr -= 2; 817 SET(sp->sp_flags, STTYF_RING_OVERFLOW); 818 break; 819 } 820 } 821 STC_WRITE(sc, STC_EOSRR, 0); 822 if (cnt) { 823 *needsoftp = 1; 824 sp->sp_rput = ptr; 825 } 826 return (1); 827 } 828 829 int 830 spif_stcintr_tx(sc, needsoftp) 831 struct spif_softc *sc; 832 int *needsoftp; 833 { 834 struct stty_port *sp; 835 u_int8_t channel, ch; 836 int cnt = 0; 837 838 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 839 sp = &sc->sc_ttys->sc_port[channel]; 840 if (!ISSET(sp->sp_flags, STTYF_STOP)) { 841 if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) { 842 STC_WRITE(sc, STC_TDR, 0); 843 STC_WRITE(sc, STC_TDR, 0x81); 844 CLR(sp->sp_flags, STTYF_SET_BREAK); 845 cnt += 2; 846 } 847 if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) { 848 STC_WRITE(sc, STC_TDR, 0); 849 STC_WRITE(sc, STC_TDR, 0x83); 850 CLR(sp->sp_flags, STTYF_CLR_BREAK); 851 cnt += 2; 852 } 853 854 while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) { 855 ch = *sp->sp_txp; 856 sp->sp_txc--; 857 sp->sp_txp++; 858 859 if (ch == 0) { 860 STC_WRITE(sc, STC_TDR, ch); 861 cnt++; 862 } 863 STC_WRITE(sc, STC_TDR, ch); 864 cnt++; 865 } 866 } 867 868 if (sp->sp_txc == 0 || 869 ISSET(sp->sp_flags, STTYF_STOP)) { 870 STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) & 871 (~CD180_SRER_TXD)); 872 CLR(sp->sp_flags, STTYF_STOP); 873 SET(sp->sp_flags, STTYF_DONE); 874 *needsoftp = 1; 875 } 876 877 STC_WRITE(sc, STC_EOSRR, 0); 878 879 return (1); 880 } 881 882 int 883 spif_stcintr_mx(sc, needsoftp) 884 struct spif_softc *sc; 885 int *needsoftp; 886 { 887 struct stty_port *sp; 888 u_int8_t channel, mcr; 889 890 channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1)); 891 sp = &sc->sc_ttys->sc_port[channel]; 892 mcr = STC_READ(sc, STC_MCR); 893 if (mcr & CD180_MCR_CD) { 894 SET(sp->sp_flags, STTYF_CDCHG); 895 *needsoftp = 1; 896 } 897 STC_WRITE(sc, STC_MCR, 0); 898 STC_WRITE(sc, STC_EOSRR, 0); 899 return (1); 900 } 901 902 int 903 spif_stcintr(vsc) 904 void *vsc; 905 { 906 struct spif_softc *sc = (struct spif_softc *)vsc; 907 int needsoft = 0, r = 0, i; 908 u_int8_t ar; 909 910 for (i = 0; i < 8; i++) { 911 ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK; 912 if (ar == CD180_GSVR_RXGOOD) 913 r |= spif_stcintr_rx(sc, &needsoft); 914 else if (ar == CD180_GSVR_RXEXCEPTION) 915 r |= spif_stcintr_rxexception(sc, &needsoft); 916 } 917 918 for (i = 0; i < 8; i++) { 919 ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK; 920 if (ar == CD180_GSVR_TXDATA) 921 r |= spif_stcintr_tx(sc, &needsoft); 922 } 923 924 for (i = 0; i < 8; i++) { 925 ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK; 926 if (ar == CD180_GSVR_STATCHG) 927 r |= spif_stcintr_mx(sc, &needsoft); 928 } 929 930 if (needsoft) 931 softintr_schedule(sc->sc_softih); 932 return (r); 933 } 934 935 void 936 spif_softintr(vsc) 937 void *vsc; 938 { 939 struct spif_softc *sc = (struct spif_softc *)vsc; 940 struct stty_softc *stc = sc->sc_ttys; 941 int r = 0, i, data, s, flags; 942 u_int8_t stat, msvr; 943 struct stty_port *sp; 944 struct tty *tp; 945 946 if (stc != NULL) { 947 for (i = 0; i < stc->sc_nports; i++) { 948 sp = &stc->sc_port[i]; 949 tp = sp->sp_tty; 950 951 if (!ISSET(tp->t_state, TS_ISOPEN)) 952 continue; 953 954 while (sp->sp_rget != sp->sp_rput) { 955 stat = sp->sp_rget[0]; 956 data = sp->sp_rget[1]; 957 sp->sp_rget += 2; 958 if (sp->sp_rget == sp->sp_rend) 959 sp->sp_rget = sp->sp_rbuf; 960 961 if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) 962 data |= TTY_FE; 963 964 if (stat & CD180_RCSR_PE) 965 data |= TTY_PE; 966 967 (*tp->t_linesw->l_rint)(data, tp); 968 r = 1; 969 } 970 971 s = splhigh(); 972 flags = sp->sp_flags; 973 CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | 974 STTYF_RING_OVERFLOW); 975 splx(s); 976 977 if (ISSET(flags, STTYF_CDCHG)) { 978 s = spltty(); 979 STC_WRITE(sc, STC_CAR, i); 980 msvr = STC_READ(sc, STC_MSVR); 981 splx(s); 982 983 sp->sp_carrier = msvr & CD180_MSVR_CD; 984 (*tp->t_linesw->l_modem)(tp, 985 sp->sp_carrier); 986 r = 1; 987 } 988 989 if (ISSET(flags, STTYF_RING_OVERFLOW)) { 990 log(LOG_WARNING, "%s-%x: ring overflow\n", 991 stc->sc_dev.dv_xname, i); 992 r = 1; 993 } 994 995 if (ISSET(flags, STTYF_DONE)) { 996 ndflush(&tp->t_outq, 997 sp->sp_txp - tp->t_outq.c_cf); 998 CLR(tp->t_state, TS_BUSY); 999 (*tp->t_linesw->l_start)(tp); 1000 r = 1; 1001 } 1002 } 1003 } 1004 } 1005 1006 void 1007 stty_write_ccr(sc, val) 1008 struct spif_softc *sc; 1009 u_int8_t val; 1010 { 1011 int tries = 100000; 1012 1013 while (STC_READ(sc, STC_CCR) && tries--) 1014 /*EMPTY*/; 1015 if (tries == 0) 1016 printf("%s: ccr timeout\n", sc->sc_dev.dv_xname); 1017 STC_WRITE(sc, STC_CCR, val); 1018 } 1019 1020 int 1021 stty_compute_baud(speed, clock, bprlp, bprhp) 1022 speed_t speed; 1023 int clock; 1024 u_int8_t *bprlp, *bprhp; 1025 { 1026 u_int32_t rate; 1027 1028 rate = (2 * clock) / (16 * speed); 1029 if (rate & 1) 1030 rate = (rate >> 1) + 1; 1031 else 1032 rate = rate >> 1; 1033 1034 if (rate > 0xffff || rate == 0) 1035 return (1); 1036 1037 *bprlp = rate & 0xff; 1038 *bprhp = (rate >> 8) & 0xff; 1039 return (0); 1040 } 1041 1042 int 1043 sbpp_match(parent, vcf, aux) 1044 struct device *parent; 1045 struct cfdata *vcf; 1046 void *aux; 1047 { 1048 struct spif_softc *sc = (struct spif_softc *)parent; 1049 1050 return (aux == sbpp_match && sc->sc_bpps == NULL); 1051 } 1052 1053 void 1054 sbpp_attach(parent, dev, aux) 1055 struct device *parent, *dev; 1056 void *aux; 1057 { 1058 struct spif_softc *sc = (struct spif_softc *)parent; 1059 struct sbpp_softc *psc = (struct sbpp_softc *)dev; 1060 int port; 1061 1062 sc->sc_bpps = psc; 1063 1064 for (port = 0; port < sc->sc_npar; port++) { 1065 } 1066 1067 psc->sc_nports = port; 1068 printf(": %d port%s\n", port, port == 1 ? "" : "s"); 1069 } 1070 1071 int 1072 sbpp_open(dev, flags, mode, l) 1073 dev_t dev; 1074 int flags; 1075 int mode; 1076 struct lwp *l; 1077 { 1078 return (ENXIO); 1079 } 1080 1081 int 1082 sbpp_close(dev, flags, mode, l) 1083 dev_t dev; 1084 int flags; 1085 int mode; 1086 struct lwp *l; 1087 { 1088 return (ENXIO); 1089 } 1090 1091 int 1092 spif_ppcintr(v) 1093 void *v; 1094 { 1095 return (0); 1096 } 1097 1098 int 1099 sbpp_read(dev, uio, flags) 1100 dev_t dev; 1101 struct uio *uio; 1102 int flags; 1103 { 1104 return (sbpp_rw(dev, uio)); 1105 } 1106 1107 int 1108 sbpp_write(dev, uio, flags) 1109 dev_t dev; 1110 struct uio *uio; 1111 int flags; 1112 { 1113 return (sbpp_rw(dev, uio)); 1114 } 1115 1116 int 1117 sbpp_rw(dev, uio) 1118 dev_t dev; 1119 struct uio *uio; 1120 { 1121 return (ENXIO); 1122 } 1123 1124 int 1125 sbpp_poll(dev, events, l) 1126 dev_t dev; 1127 int events; 1128 struct lwp *l; 1129 { 1130 return (seltrue(dev, events, l)); 1131 } 1132 1133 int 1134 sbpp_ioctl(dev, cmd, data, flags, l) 1135 dev_t dev; 1136 u_long cmd; 1137 caddr_t data; 1138 int flags; 1139 struct lwp *l; 1140 { 1141 int error; 1142 1143 error = ENOTTY; 1144 1145 return (error); 1146 } 1147 1148 #endif /* NSPIF */ 1149