1 /* $OpenBSD: sab.c,v 1.1 2001/10/28 02:19:16 jason Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jason L. Wright 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * SAB82532 Dual UART driver 36 */ 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/conf.h> 43 #include <sys/file.h> 44 #include <sys/ioctl.h> 45 #include <sys/kernel.h> 46 #include <sys/proc.h> 47 #include <sys/tty.h> 48 #include <sys/time.h> 49 #include <sys/syslog.h> 50 51 #include <machine/autoconf.h> 52 #include <machine/openfirm.h> 53 #include <machine/bsd_openprom.h> 54 #include <machine/conf.h> 55 #include <machine/cpu.h> 56 #include <machine/eeprom.h> 57 #include <machine/psl.h> 58 59 #include <dev/cons.h> 60 #include <ddb/db_output.h> 61 62 #include <sparc64/dev/ebusreg.h> 63 #include <sparc64/dev/ebusvar.h> 64 #include <sparc64/dev/cons.h> 65 #include <sparc64/dev/sab82532reg.h> 66 67 #define SAB_CARD(x) ((minor(x) >> 6) & 3) 68 #define SAB_PORT(x) (minor(x) & 7) 69 #define SAB_DIALOUT(x) (minor(x) & 0x10) 70 #define SABTTY_RBUF_SIZE 1024 /* must be divisible by 2 */ 71 72 struct sab_softc { 73 struct device sc_dv; 74 struct intrhand * sc_ih; 75 bus_space_tag_t sc_bt; 76 bus_space_handle_t sc_bh; 77 struct sabtty_softc * sc_child[SAB_NCHAN]; 78 u_int sc_nchild; 79 void * sc_softintr; 80 }; 81 82 struct sabtty_attach_args { 83 u_int sbt_portno; 84 }; 85 86 struct sabtty_softc { 87 struct device sc_dv; 88 struct sab_softc * sc_parent; 89 bus_space_tag_t sc_bt; 90 bus_space_handle_t sc_bh; 91 struct tty * sc_tty; 92 u_int sc_portno; 93 u_int8_t sc_pvr_dtr, sc_pvr_dsr; 94 u_int8_t sc_imr0, sc_imr1; 95 int sc_openflags; 96 u_char * sc_txp; 97 int sc_txc; 98 int sc_flags; 99 #define SABTTYF_STOP 0x01 100 #define SABTTYF_DONE 0x02 101 #define SABTTYF_RINGOVERFLOW 0x04 102 #define SABTTYF_CDCHG 0x08 103 u_int8_t sc_rbuf[SABTTY_RBUF_SIZE]; 104 u_int8_t *sc_rend, *sc_rput, *sc_rget; 105 }; 106 107 #define SAB_READ(sc,r) \ 108 bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r)) 109 #define SAB_WRITE(sc,r,v) \ 110 bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v)) 111 112 int sab_match __P((struct device *, void *, void *)); 113 void sab_attach __P((struct device *, struct device *, void *)); 114 int sab_print __P((void *, const char *)); 115 int sab_intr __P((void *)); 116 void sab_softintr __P((void *)); 117 118 int sabtty_match __P((struct device *, void *, void *)); 119 void sabtty_attach __P((struct device *, struct device *, void *)); 120 void sabtty_start __P((struct tty *)); 121 int sabtty_param __P((struct tty *, struct termios *)); 122 int sabtty_intr __P((struct sabtty_softc *, int *)); 123 void sabtty_softintr __P((struct sabtty_softc *)); 124 int sabtty_mdmctrl __P((struct sabtty_softc *, int, int)); 125 void sabtty_cec_wait __P((struct sabtty_softc *)); 126 void sabtty_tec_wait __P((struct sabtty_softc *)); 127 void sabtty_reset __P((struct sabtty_softc *)); 128 void sabtty_flush __P((struct sabtty_softc *)); 129 int sabtty_speed __P((int)); 130 131 int sabttyopen __P((dev_t, int, int, struct proc *)); 132 int sabttyclose __P((dev_t, int, int, struct proc *)); 133 int sabttyread __P((dev_t, struct uio *, int)); 134 int sabttywrite __P((dev_t, struct uio *, int)); 135 int sabttyioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); 136 int sabttystop __P((struct tty *, int)); 137 struct tty *sabttytty __P((dev_t)); 138 139 struct cfattach sab_ca = { 140 sizeof(struct sab_softc), sab_match, sab_attach 141 }; 142 143 struct cfdriver sab_cd = { 144 NULL, "sab", DV_DULL 145 }; 146 147 struct cfattach sabtty_ca = { 148 sizeof(struct sabtty_softc), sabtty_match, sabtty_attach 149 }; 150 151 struct cfdriver sabtty_cd = { 152 NULL, "sabtty", DV_TTY 153 }; 154 155 struct sabtty_rate { 156 int baud; 157 int n, m; 158 }; 159 160 struct sabtty_rate sabtty_baudtable[] = { 161 { 50, 35, 10 }, 162 { 75, 47, 9 }, 163 { 110, 32, 9 }, 164 { 134, 53, 8 }, 165 { 150, 47, 8 }, 166 { 200, 35, 8 }, 167 { 300, 47, 7 }, 168 { 600, 47, 6 }, 169 { 1200, 47, 5 }, 170 { 1800, 31, 5 }, 171 { 2400, 47, 4 }, 172 { 4800, 47, 3 }, 173 { 9600, 47, 2 }, 174 { 19200, 47, 1 }, 175 { 38400, 23, 1 }, 176 { 57600, 15, 1 }, 177 { 115200, 7, 1 }, 178 { 230400, 3, 1 }, 179 { 460800, 1, 1 }, 180 { 76800, 11, 1 }, 181 { 153600, 5, 1 }, 182 { 307200, 3, 1 }, 183 { 614400, 3, 0 }, 184 { 921600, 0, 1 }, 185 }; 186 187 int 188 sab_match(parent, match, aux) 189 struct device *parent; 190 void *match, *aux; 191 { 192 struct ebus_attach_args *ea = aux; 193 194 if (strcmp(ea->ea_name, "se") == 0) 195 return (1); 196 return (0); 197 } 198 199 void 200 sab_attach(parent, self, aux) 201 struct device *parent; 202 struct device *self; 203 void *aux; 204 { 205 struct sab_softc *sc = (struct sab_softc *)self; 206 struct ebus_attach_args *ea = aux; 207 u_int8_t r; 208 u_int i; 209 210 sc->sc_bt = ea->ea_bustag; 211 212 /* Use prom mapping, if available. */ 213 if (ea->ea_nvaddrs) 214 sc->sc_bh = (bus_space_handle_t)ea->ea_vaddrs[0]; 215 else if (ebus_bus_map(sc->sc_bt, 0, 216 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 217 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_bh) != 0) { 218 printf(": can't map register space\n"); 219 return; 220 } 221 222 sc->sc_ih = bus_intr_establish(ea->ea_bustag, ea->ea_intrs[0], 223 IPL_TTY, 0, sab_intr, sc); 224 if (sc->sc_ih == NULL) { 225 printf(": can't map interrupt\n"); 226 return; 227 } 228 229 sc->sc_softintr = softintr_establish(IPL_TTY, sab_softintr, sc); 230 if (sc->sc_softintr == NULL) { 231 printf(": can't get soft intr\n"); 232 return; 233 } 234 235 printf(": rev "); 236 r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_VMASK; 237 switch (r) { 238 case SAB_VSTR_V_1: 239 printf("1"); 240 break; 241 case SAB_VSTR_V_2: 242 printf("2"); 243 break; 244 case SAB_VSTR_V_32: 245 printf("3.2"); 246 break; 247 default: 248 printf("unknown(0x%x)", r); 249 break; 250 } 251 printf("\n"); 252 253 /* Set all pins, except DTR pins to be inputs */ 254 SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B)); 255 /* Disable port interrupts */ 256 SAB_WRITE(sc, SAB_PIM, 0xff); 257 SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC); 258 SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL); 259 260 for (i = 0; i < SAB_NCHAN; i++) { 261 struct sabtty_attach_args sta; 262 263 sta.sbt_portno = i; 264 sc->sc_child[i] = (struct sabtty_softc *)config_found_sm(self, 265 &sta, sab_print, sabtty_match); 266 if (sc->sc_child[i] != NULL) 267 sc->sc_nchild++; 268 } 269 } 270 271 int 272 sab_print(args, name) 273 void *args; 274 const char *name; 275 { 276 struct sabtty_attach_args *sa = args; 277 278 if (name) 279 printf("sabtty at %s", name); 280 printf(" port %d", sa->sbt_portno); 281 return (UNCONF); 282 } 283 284 int 285 sab_intr(vsc) 286 void *vsc; 287 { 288 struct sab_softc *sc = vsc; 289 int r = 0, needsoft = 0; 290 u_int8_t gis; 291 292 gis = SAB_READ(sc, SAB_GIS); 293 294 /* channel A */ 295 if ((gis & (SAB_GIS_ISA1 | SAB_GIS_ISA0)) && sc->sc_child[0] && 296 sc->sc_child[0]->sc_tty) 297 r |= sabtty_intr(sc->sc_child[0], &needsoft); 298 299 /* channel B */ 300 if ((gis & (SAB_GIS_ISB1 | SAB_GIS_ISB0)) && sc->sc_child[1] && 301 sc->sc_child[1]->sc_tty) 302 r |= sabtty_intr(sc->sc_child[1], &needsoft); 303 304 if (needsoft) 305 softintr_schedule(sc->sc_softintr); 306 307 return (r); 308 } 309 310 void 311 sab_softintr(vsc) 312 void *vsc; 313 { 314 struct sab_softc *sc = vsc; 315 316 if (sc->sc_child[0] && sc->sc_child[0]->sc_tty) 317 sabtty_softintr(sc->sc_child[0]); 318 if (sc->sc_child[1] && sc->sc_child[1]->sc_tty) 319 sabtty_softintr(sc->sc_child[1]); 320 } 321 322 int 323 sabtty_match(parent, match, aux) 324 struct device *parent; 325 void *match, *aux; 326 { 327 struct sabtty_attach_args *sa = aux; 328 329 if (sa->sbt_portno < SAB_NCHAN) 330 return (1); 331 return (0); 332 } 333 334 void 335 sabtty_attach(parent, self, aux) 336 struct device *parent; 337 struct device *self; 338 void *aux; 339 { 340 struct sabtty_softc *sc = (struct sabtty_softc *)self; 341 struct sabtty_attach_args *sa = aux; 342 int r; 343 344 sc->sc_tty = ttymalloc(); 345 if (sc->sc_tty == NULL) { 346 printf(": failed to allocate tty\n"); 347 return; 348 } 349 tty_attach(sc->sc_tty); 350 sc->sc_tty->t_oproc = sabtty_start; 351 sc->sc_tty->t_param = sabtty_param; 352 353 sc->sc_parent = (struct sab_softc *)parent; 354 sc->sc_bt = sc->sc_parent->sc_bt; 355 sc->sc_portno = sa->sbt_portno; 356 sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE; 357 358 switch (sa->sbt_portno) { 359 case 0: /* port A */ 360 sc->sc_pvr_dtr = SAB_PVR_DTR_A; 361 sc->sc_pvr_dsr = SAB_PVR_DSR_A; 362 r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 363 SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh); 364 break; 365 case 1: /* port B */ 366 sc->sc_pvr_dtr = SAB_PVR_DTR_B; 367 sc->sc_pvr_dsr = SAB_PVR_DSR_B; 368 r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 369 SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh); 370 break; 371 default: 372 printf(": invalid channel: %u\n", sa->sbt_portno); 373 return; 374 } 375 if (r != 0) { 376 printf(": failed to allocate register subregion\n"); 377 return; 378 } 379 380 sabtty_reset(sc); 381 printf("\n"); 382 } 383 384 int 385 sabtty_intr(sc, needsoftp) 386 struct sabtty_softc *sc; 387 int *needsoftp; 388 { 389 u_int8_t isr0, isr1; 390 int i, len = 0, needsoft = 0, r = 0, clearfifo = 0; 391 392 isr0 = SAB_READ(sc, SAB_ISR0); 393 isr1 = SAB_READ(sc, SAB_ISR1); 394 395 if (isr0 || isr1) 396 r = 1; 397 398 if (isr0 & SAB_ISR0_RPF) { 399 len = 32; 400 clearfifo = 1; 401 } 402 if (isr0 & SAB_ISR0_TCD) { 403 len = (32 - 1) & SAB_READ(sc, SAB_RBCL); 404 clearfifo = 1; 405 } 406 if (isr0 & SAB_ISR0_TIME) { 407 sabtty_cec_wait(sc); 408 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); 409 } 410 if (isr0 & SAB_ISR0_RFO) { 411 sc->sc_flags |= SABTTYF_RINGOVERFLOW; 412 clearfifo = 1; 413 } 414 if (len != 0) { 415 u_int8_t *ptr; 416 417 ptr = sc->sc_rput; 418 for (i = 0; i < len; i++) { 419 *ptr++ = SAB_READ(sc, SAB_RFIFO); 420 if (ptr == sc->sc_rend) 421 ptr = sc->sc_rbuf; 422 if (ptr == sc->sc_rget) { 423 if (ptr == sc->sc_rbuf) 424 ptr = sc->sc_rend; 425 ptr--; 426 sc->sc_flags |= SABTTYF_RINGOVERFLOW; 427 } 428 } 429 sc->sc_rput = ptr; 430 needsoft = 1; 431 } 432 433 if (clearfifo) { 434 sabtty_cec_wait(sc); 435 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); 436 } 437 438 if (isr0 & SAB_ISR0_CDSC) { 439 sc->sc_flags |= SABTTYF_CDCHG; 440 needsoft = 1; 441 } 442 443 if (isr1 & SAB_ISR1_XPR) { 444 r = 1; 445 if ((sc->sc_flags & SABTTYF_STOP) == 0) { 446 len = 32; 447 if (sc->sc_txc < 32) 448 len = sc->sc_txc; 449 for (i = 0; i < len; i++) { 450 SAB_WRITE(sc, SAB_XFIFO + i, *sc->sc_txp); 451 sc->sc_txp++; 452 sc->sc_txc--; 453 } 454 if (i != 0) { 455 sabtty_cec_wait(sc); 456 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF); 457 } 458 } 459 460 if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) { 461 sc->sc_imr1 |= SAB_IMR1_XPR; 462 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 463 sc->sc_flags &= ~SABTTYF_STOP; 464 sc->sc_flags |= SABTTYF_DONE; 465 needsoft = 1; 466 } 467 } 468 469 if (needsoft) 470 *needsoftp = needsoft; 471 return (r); 472 } 473 474 void 475 sabtty_softintr(sc) 476 struct sabtty_softc *sc; 477 { 478 struct tty *tp = sc->sc_tty; 479 int s, flags; 480 u_int8_t r; 481 482 if (tp == NULL) 483 return; 484 485 if ((tp->t_state & TS_ISOPEN) == 0) 486 return; 487 488 while (sc->sc_rget != sc->sc_rput) { 489 int data; 490 u_int8_t stat; 491 492 data = sc->sc_rget[0]; 493 stat = sc->sc_rget[1]; 494 sc->sc_rget += 2; 495 if (stat & SAB_RSTAT_PE) 496 data |= TTY_PE; 497 if (stat & SAB_RSTAT_FE) 498 data |= TTY_FE; 499 if (sc->sc_rget == sc->sc_rend) 500 sc->sc_rget = sc->sc_rbuf; 501 502 (*linesw[tp->t_line].l_rint)(data, tp); 503 } 504 505 s = splhigh(); 506 flags = sc->sc_flags; 507 sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW); 508 splx(s); 509 510 if (flags & SABTTYF_CDCHG) { 511 s = spltty(); 512 r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD; 513 splx(s); 514 515 (*linesw[tp->t_line].l_modem)(tp, r); 516 } 517 518 if (flags & SABTTYF_RINGOVERFLOW) 519 log(LOG_WARNING, "%s: ring overflow\n", sc->sc_dv.dv_xname); 520 521 if (flags & SABTTYF_DONE) { 522 ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf); 523 tp->t_state &= ~TS_BUSY; 524 (*linesw[tp->t_line].l_start)(tp); 525 } 526 } 527 528 int 529 sabttyopen(dev, flags, mode, p) 530 dev_t dev; 531 int flags, mode; 532 struct proc *p; 533 { 534 struct sab_softc *bc; 535 struct sabtty_softc *sc; 536 struct tty *tp; 537 int card = SAB_CARD(dev), port = SAB_PORT(dev), s; 538 539 if (card >= sab_cd.cd_ndevs) 540 return (ENXIO); 541 bc = sab_cd.cd_devs[card]; 542 if (bc == NULL) 543 return (ENXIO); 544 545 if (port >= bc->sc_nchild) 546 return (ENXIO); 547 sc = bc->sc_child[port]; 548 if (sc == NULL) 549 return (ENXIO); 550 551 tp = sc->sc_tty; 552 tp->t_dev = dev; 553 554 if ((tp->t_state & TS_ISOPEN) == 0) { 555 tp->t_state |= TS_WOPEN; 556 557 ttychars(tp); 558 tp->t_iflag = TTYDEF_IFLAG; 559 tp->t_oflag = TTYDEF_OFLAG; 560 tp->t_cflag = TTYDEF_CFLAG; 561 if (sc->sc_openflags & TIOCFLAG_CLOCAL) 562 tp->t_cflag |= CLOCAL; 563 if (sc->sc_openflags & TIOCFLAG_CRTSCTS) 564 tp->t_cflag |= CRTSCTS; 565 if (sc->sc_openflags & TIOCFLAG_MDMBUF) 566 tp->t_cflag |= MDMBUF; 567 tp->t_lflag = TTYDEF_LFLAG; 568 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 569 570 sc->sc_rput = sc->sc_rget = sc->sc_rbuf; 571 572 s = spltty(); 573 574 sabtty_reset(sc); 575 sabtty_param(tp, &tp->t_termios); 576 ttsetwater(tp); 577 578 sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA; 579 SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 580 581 sc->sc_imr1 = SAB_IMR1_BRKT | SAB_IMR1_ALLS | SAB_IMR1_XDU | 582 SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR; 583 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 584 SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU); 585 sabtty_flush(sc); 586 587 if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) || 588 (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD)) 589 tp->t_state |= TS_CARR_ON; 590 else 591 tp->t_state &= ~TS_CARR_ON; 592 } else if ((tp->t_state & TS_XCLUDE) && 593 (!suser(p->p_ucred, &p->p_acflag))) { 594 return (EBUSY); 595 } else { 596 s = spltty(); 597 } 598 599 if ((flags & O_NONBLOCK) == 0) { 600 while ((tp->t_cflag & CLOCAL) == 0 && 601 (tp->t_state & TS_CARR_ON) == 0) { 602 int error; 603 604 tp->t_state |= TS_WOPEN; 605 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 606 "sabttycd", 0); 607 if (error != 0) { 608 splx(s); 609 tp->t_state &= ~TS_WOPEN; 610 return (error); 611 } 612 } 613 } 614 615 splx(s); 616 617 return ((*linesw[tp->t_line].l_open)(dev, tp)); 618 } 619 620 int 621 sabttyclose(dev, flags, mode, p) 622 dev_t dev; 623 int flags, mode; 624 struct proc *p; 625 { 626 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)]; 627 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)]; 628 struct tty *tp = sc->sc_tty; 629 int s; 630 631 (*linesw[tp->t_line].l_close)(tp, flags); 632 s = spltty(); 633 634 if ((tp->t_cflag & HUPCL) || ((tp->t_state & TS_ISOPEN) == 0)) { 635 sabtty_mdmctrl(sc, 0, DMSET); 636 sabtty_flush(sc); 637 sabtty_reset(sc); 638 } 639 splx(s); 640 ttyclose(tp); 641 return (0); 642 } 643 644 int 645 sabttyread(dev, uio, flags) 646 dev_t dev; 647 struct uio *uio; 648 int flags; 649 { 650 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)]; 651 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)]; 652 struct tty *tp = sc->sc_tty; 653 654 return ((*linesw[tp->t_line].l_read)(tp, uio, flags)); 655 } 656 657 int 658 sabttywrite(dev, uio, flags) 659 dev_t dev; 660 struct uio *uio; 661 int flags; 662 { 663 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)]; 664 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)]; 665 struct tty *tp = sc->sc_tty; 666 667 return ((*linesw[tp->t_line].l_write)(tp, uio, flags)); 668 } 669 670 int 671 sabttyioctl(dev, cmd, data, flags, p) 672 dev_t dev; 673 u_long cmd; 674 caddr_t data; 675 int flags; 676 struct proc *p; 677 { 678 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)]; 679 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)]; 680 struct tty *tp = sc->sc_tty; 681 int error; 682 683 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p); 684 if (error >= 0) 685 return (error); 686 687 error = ttioctl(tp, cmd, data, flags, p); 688 if (error >= 0) 689 return (error); 690 691 error = 0; 692 693 switch (cmd) { 694 case TIOCSBRK: 695 SAB_WRITE(sc, SAB_DAFO, 696 SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK); 697 break; 698 case TIOCCBRK: 699 SAB_WRITE(sc, SAB_DAFO, 700 SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK); 701 break; 702 case TIOCSDTR: 703 sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS); 704 break; 705 case TIOCCDTR: 706 sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC); 707 break; 708 case TIOCMBIS: 709 sabtty_mdmctrl(sc, *((int *)data), DMBIS); 710 break; 711 case TIOCMBIC: 712 sabtty_mdmctrl(sc, *((int *)data), DMBIC); 713 break; 714 case TIOCMGET: 715 *((int *)data) = sabtty_mdmctrl(sc, 0, DMGET); 716 break; 717 case TIOCMSET: 718 sabtty_mdmctrl(sc, *((int *)data), DMSET); 719 break; 720 case TIOCGFLAGS: 721 *((int *)data) = sc->sc_openflags; 722 break; 723 case TIOCSFLAGS: 724 if (suser(p->p_ucred, &p->p_acflag)) 725 error = EPERM; 726 else 727 sc->sc_openflags = *((int *)data) & 728 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 729 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 730 break; 731 default: 732 error = ENOTTY; 733 } 734 735 return (error); 736 } 737 738 struct tty * 739 sabttytty(dev) 740 dev_t dev; 741 { 742 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)]; 743 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)]; 744 745 return (sc->sc_tty); 746 } 747 748 int 749 sabttystop(tp, flags) 750 struct tty *tp; 751 int flags; 752 { 753 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)]; 754 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)]; 755 int s; 756 757 s = spltty(); 758 if (tp->t_state & TS_BUSY) { 759 if ((tp->t_state & TS_TTSTOP) == 0) 760 tp->t_state |= TS_FLUSH; 761 sc->sc_flags |= SABTTYF_STOP; 762 } 763 splx(s); 764 return (0); 765 } 766 767 int 768 sabtty_mdmctrl(sc, bits, how) 769 struct sabtty_softc *sc; 770 int bits, how; 771 { 772 u_int8_t r; 773 int s; 774 775 s = spltty(); 776 switch (how) { 777 case DMGET: 778 bits = 0; 779 if (SAB_READ(sc, SAB_STAR) & SAB_STAR_CTS) 780 bits |= TIOCM_CTS; 781 if ((SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD) == 0) 782 bits |= TIOCM_CD; 783 784 r = SAB_READ(sc, SAB_PVR); 785 if ((r & sc->sc_pvr_dtr) == 0) 786 bits |= TIOCM_DTR; 787 if ((r & sc->sc_pvr_dsr) == 0) 788 bits |= TIOCM_DSR; 789 790 r = SAB_READ(sc, SAB_MODE); 791 if ((r & (SAB_MODE_RTS|SAB_MODE_FRTS)) == SAB_MODE_RTS) 792 bits |= TIOCM_RTS; 793 break; 794 case DMSET: 795 r = SAB_READ(sc, SAB_MODE); 796 if (bits & TIOCM_RTS) { 797 r &= ~SAB_MODE_FRTS; 798 r |= SAB_MODE_RTS; 799 } else 800 r |= SAB_MODE_FRTS | SAB_MODE_RTS; 801 SAB_WRITE(sc, SAB_MODE, r); 802 803 r = SAB_READ(sc, SAB_PVR); 804 if (bits & TIOCM_DTR) 805 r &= ~sc->sc_pvr_dtr; 806 else 807 r |= sc->sc_pvr_dtr; 808 SAB_WRITE(sc, SAB_PVR, r); 809 break; 810 case DMBIS: 811 if (bits & TIOCM_RTS) { 812 r = SAB_READ(sc, SAB_MODE); 813 r &= ~SAB_MODE_FRTS; 814 r |= SAB_MODE_RTS; 815 SAB_WRITE(sc, SAB_MODE, r); 816 } 817 if (bits & TIOCM_DTR) { 818 r = SAB_READ(sc, SAB_PVR); 819 r &= ~sc->sc_pvr_dtr; 820 SAB_WRITE(sc, SAB_PVR, r); 821 } 822 break; 823 case DMBIC: 824 if (bits & TIOCM_RTS) { 825 r = SAB_READ(sc, SAB_MODE); 826 r |= SAB_MODE_FRTS | SAB_MODE_RTS; 827 SAB_WRITE(sc, SAB_MODE, r); 828 } 829 if (bits & TIOCM_DTR) { 830 r = SAB_READ(sc, SAB_PVR); 831 r |= sc->sc_pvr_dtr; 832 SAB_WRITE(sc, SAB_PVR, r); 833 } 834 break; 835 } 836 splx(s); 837 return (bits); 838 } 839 840 int 841 sabtty_param(tp, t) 842 struct tty *tp; 843 struct termios *t; 844 { 845 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)]; 846 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)]; 847 int s, ospeed; 848 u_int8_t dafo, r; 849 850 ospeed = sabtty_speed(t->c_ospeed); 851 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 852 return (EINVAL); 853 854 s = spltty(); 855 856 /* hang up line if ospeed is zero, otherwise raise dtr */ 857 sabtty_mdmctrl(sc, TIOCM_DTR, 858 (t->c_ospeed == 0) ? DMBIC : DMBIS); 859 860 dafo = SAB_READ(sc, SAB_DAFO); 861 862 if (t->c_cflag & CSTOPB) 863 dafo |= SAB_DAFO_STOP; 864 else 865 dafo &= ~SAB_DAFO_STOP; 866 867 dafo &= ~SAB_DAFO_CHL_CSIZE; 868 switch (t->c_cflag & CSIZE) { 869 case CS5: 870 dafo |= SAB_DAFO_CHL_CS5; 871 break; 872 case CS6: 873 dafo |= SAB_DAFO_CHL_CS6; 874 break; 875 case CS7: 876 dafo |= SAB_DAFO_CHL_CS7; 877 break; 878 default: 879 dafo |= SAB_DAFO_CHL_CS8; 880 break; 881 } 882 883 dafo &= ~SAB_DAFO_PARMASK; 884 if (t->c_cflag & PARENB) { 885 if (tp->t_cflag & PARODD) 886 dafo |= SAB_DAFO_PAR_ODD; 887 else 888 dafo |= SAB_DAFO_PAR_EVEN; 889 } else 890 dafo |= SAB_DAFO_PAR_NONE; 891 892 if (ospeed != 0) { 893 SAB_WRITE(sc, SAB_BGR, ospeed & 0xff); 894 r = SAB_READ(sc, SAB_CCR2); 895 r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8); 896 r |= (ospeed >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8); 897 SAB_WRITE(sc, SAB_CCR2, r); 898 } 899 900 r = SAB_READ(sc, SAB_MODE); 901 r |= SAB_MODE_RAC; 902 if (t->c_cflag & CRTSCTS) { 903 r &= ~(SAB_MODE_RTS | SAB_MODE_FCTS); 904 r |= SAB_MODE_FRTS; 905 sc->sc_imr1 &= ~SAB_IMR1_CSC; 906 } else { 907 r |= SAB_MODE_RTS | SAB_MODE_FCTS; 908 r &= ~SAB_MODE_FRTS; 909 sc->sc_imr1 |= SAB_IMR1_CSC; 910 } 911 SAB_WRITE(sc, SAB_MODE, r); 912 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 913 914 splx(s); 915 return (0); 916 } 917 918 void 919 sabtty_start(tp) 920 struct tty *tp; 921 { 922 struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)]; 923 struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)]; 924 int s; 925 926 s = spltty(); 927 if ((tp->t_state & (TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) == 0) { 928 if (tp->t_outq.c_cc <= tp->t_lowat) { 929 if (tp->t_state & TS_ASLEEP) { 930 tp->t_state &= ~TS_ASLEEP; 931 wakeup(&tp->t_outq); 932 } 933 selwakeup(&tp->t_wsel); 934 } 935 if (tp->t_outq.c_cc) { 936 sc->sc_txc = ndqb(&tp->t_outq, 0); 937 sc->sc_txp = tp->t_outq.c_cf; 938 tp->t_state |= TS_BUSY; 939 sc->sc_imr1 &= ~SAB_IMR1_XPR; 940 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 941 } 942 } 943 splx(s); 944 } 945 946 void 947 sabtty_cec_wait(sc) 948 struct sabtty_softc *sc; 949 { 950 int i = 50000; 951 952 for (;;) { 953 if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0) 954 return; 955 if (--i == 0) 956 break; 957 DELAY(1); 958 } 959 if (i == 0) 960 printf("%s: cec timeout\n", sc->sc_dv.dv_xname); 961 } 962 963 void 964 sabtty_tec_wait(sc) 965 struct sabtty_softc *sc; 966 { 967 int i = 200000; 968 969 for (;;) { 970 if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0) 971 return; 972 if (--i == 0) 973 break; 974 DELAY(1); 975 } 976 if (i == 0) 977 printf("%s: tec timeout\n", sc->sc_dv.dv_xname); 978 } 979 980 void 981 sabtty_reset(sc) 982 struct sabtty_softc *sc; 983 { 984 /* power down */ 985 SAB_WRITE(sc, SAB_CCR0, 0); 986 987 /* set basic configuration */ 988 SAB_WRITE(sc, SAB_CCR0, 989 SAB_CCR0_MCE | SAB_CCR0_SC_NRZ | SAB_CCR0_SM_ASYNC); 990 SAB_WRITE(sc, SAB_CCR1, SAB_CCR1_ODS | SAB_CCR1_BCR | SAB_CCR1_CM_7); 991 SAB_WRITE(sc, SAB_CCR2, SAB_CCR2_BDF | SAB_CCR2_SSEL | SAB_CCR2_TOE); 992 SAB_WRITE(sc, SAB_CCR3, 0); 993 SAB_WRITE(sc, SAB_CCR4, SAB_CCR4_MCK4 | SAB_CCR4_EBRG); 994 SAB_WRITE(sc, SAB_MODE, SAB_MODE_RTS | SAB_MODE_FCTS | SAB_MODE_RAC); 995 SAB_WRITE(sc, SAB_RFC, 996 SAB_RFC_DPS | SAB_RFC_RFDF | SAB_RFC_RFTH_32CHAR); 997 998 /* clear interrupts */ 999 sc->sc_imr0 = sc->sc_imr1 = 0xff; 1000 SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 1001 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1002 SAB_READ(sc, SAB_ISR0); 1003 SAB_READ(sc, SAB_ISR1); 1004 } 1005 1006 void 1007 sabtty_flush(sc) 1008 struct sabtty_softc *sc; 1009 { 1010 /* clear rx fifo */ 1011 sabtty_cec_wait(sc); 1012 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1013 1014 /* clear tx fifo */ 1015 sabtty_cec_wait(sc); 1016 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); 1017 } 1018 1019 int 1020 sabtty_speed(rate) 1021 int rate; 1022 { 1023 int i, len, r; 1024 1025 if (rate == 0) 1026 return (0); 1027 len = sizeof(sabtty_baudtable)/sizeof(sabtty_baudtable[0]); 1028 for (i = 0; i < len; i++) { 1029 if (rate == sabtty_baudtable[i].baud) { 1030 r = sabtty_baudtable[i].n | 1031 (sabtty_baudtable[i].m << 6); 1032 return (r); 1033 } 1034 } 1035 return (-1); 1036 } 1037