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