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