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