1 /* $NetBSD: sab.c,v 1.25 2006/02/13 21:47:12 cdi Exp $ */ 2 /* $OpenBSD: sab.c,v 1.7 2002/04/08 17:49:42 jason Exp $ */ 3 4 /* 5 * Copyright (c) 2001 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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Jason L. Wright 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 * Effort sponsored in part by the Defense Advanced Research Projects 35 * Agency (DARPA) and Air Force Research Laboratory, Air Force 36 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 37 * 38 */ 39 40 /* 41 * SAB82532 Dual UART driver 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: sab.c,v 1.25 2006/02/13 21:47:12 cdi Exp $"); 46 47 #include <sys/types.h> 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/device.h> 51 #include <sys/conf.h> 52 #include <sys/file.h> 53 #include <sys/ioctl.h> 54 #include <sys/kernel.h> 55 #include <sys/proc.h> 56 #include <sys/tty.h> 57 #include <sys/syslog.h> 58 59 #include <machine/autoconf.h> 60 #include <machine/openfirm.h> 61 62 #include <dev/cons.h> 63 64 #include <dev/ebus/ebusreg.h> 65 #include <dev/ebus/ebusvar.h> 66 #include <sparc64/dev/sab82532reg.h> 67 68 #include "locators.h" 69 70 #define SABUNIT(x) (minor(x) & 0x7ffff) 71 #define SABDIALOUT(x) (minor(x) & 0x80000) 72 73 #define SABTTY_RBUF_SIZE 1024 /* must be divisible by 2 */ 74 75 struct sab_softc { 76 struct device sc_dv; 77 struct intrhand * sc_ih; 78 bus_space_tag_t sc_bt; 79 bus_space_handle_t sc_bh; 80 struct sabtty_softc * sc_child[SAB_NCHAN]; 81 u_int sc_nchild; 82 void * sc_softintr; 83 int sc_node; 84 }; 85 86 struct sabtty_attach_args { 87 u_int sbt_portno; 88 }; 89 90 struct sabtty_softc { 91 struct device sc_dv; 92 struct sab_softc * sc_parent; 93 bus_space_tag_t sc_bt; 94 bus_space_handle_t sc_bh; 95 struct tty * sc_tty; 96 u_int sc_portno; 97 uint8_t sc_pvr_dtr, sc_pvr_dsr; 98 uint8_t sc_imr0, sc_imr1; 99 int sc_openflags; 100 u_char * sc_txp; 101 int sc_txc; 102 int sc_flags; 103 #define SABTTYF_STOP 0x01 104 #define SABTTYF_DONE 0x02 105 #define SABTTYF_RINGOVERFLOW 0x04 106 #define SABTTYF_CDCHG 0x08 107 #define SABTTYF_CONS_IN 0x10 108 #define SABTTYF_CONS_OUT 0x20 109 #define SABTTYF_TXDRAIN 0x40 110 #define SABTTYF_DONTDDB 0x80 111 uint8_t sc_rbuf[SABTTY_RBUF_SIZE]; 112 uint8_t *sc_rend, *sc_rput, *sc_rget; 113 uint8_t sc_polling, sc_pollrfc; 114 }; 115 116 struct sabtty_softc *sabtty_cons_input; 117 struct sabtty_softc *sabtty_cons_output; 118 119 #define SAB_READ(sc,r) \ 120 bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r)) 121 #define SAB_WRITE(sc,r,v) \ 122 bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v)) 123 #define SAB_WRITE_BLOCK(sc,r,p,c) \ 124 bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c)) 125 126 int sab_match(struct device *, struct cfdata *, void *); 127 void sab_attach(struct device *, struct device *, void *); 128 int sab_print(void *, const char *); 129 int sab_intr(void *); 130 131 void sab_softintr(void *); 132 void sab_cnputc(dev_t, int); 133 int sab_cngetc(dev_t); 134 void sab_cnpollc(dev_t, int); 135 136 int sabtty_match(struct device *, struct cfdata *, void *); 137 void sabtty_attach(struct device *, struct device *, void *); 138 void sabtty_start(struct tty *); 139 int sabtty_param(struct tty *, struct termios *); 140 int sabtty_intr(struct sabtty_softc *, int *); 141 void sabtty_softintr(struct sabtty_softc *); 142 int sabtty_mdmctrl(struct sabtty_softc *, int, int); 143 void sabtty_cec_wait(struct sabtty_softc *); 144 void sabtty_tec_wait(struct sabtty_softc *); 145 void sabtty_reset(struct sabtty_softc *); 146 void sabtty_flush(struct sabtty_softc *); 147 int sabtty_speed(int); 148 void sabtty_console_flags(struct sabtty_softc *); 149 void sabtty_cnpollc(struct sabtty_softc *, int); 150 void sabtty_shutdown(void *); 151 int sabttyparam(struct sabtty_softc *, struct tty *, struct termios *); 152 153 void sabtty_cnputc(struct sabtty_softc *, int); 154 int sabtty_cngetc(struct sabtty_softc *); 155 156 CFATTACH_DECL(sab, sizeof(struct sab_softc), 157 sab_match, sab_attach, NULL, NULL); 158 159 extern struct cfdriver sab_cd; 160 161 CFATTACH_DECL(sabtty, sizeof(struct sabtty_softc), 162 sabtty_match, sabtty_attach, NULL, NULL); 163 164 extern struct cfdriver sabtty_cd; 165 166 dev_type_open(sabopen); 167 dev_type_close(sabclose); 168 dev_type_read(sabread); 169 dev_type_write(sabwrite); 170 dev_type_ioctl(sabioctl); 171 dev_type_stop(sabstop); 172 dev_type_tty(sabtty); 173 dev_type_poll(sabpoll); 174 175 static struct cnm_state sabtty_cnm_state; 176 177 const struct cdevsw sabtty_cdevsw = { 178 sabopen, sabclose, sabread, sabwrite, sabioctl, 179 sabstop, sabtty, sabpoll, nommap, ttykqfilter, D_TTY 180 }; 181 182 struct sabtty_rate { 183 int baud; 184 int n, m; 185 }; 186 187 struct sabtty_rate sabtty_baudtable[] = { 188 { 50, 35, 10 }, 189 { 75, 47, 9 }, 190 { 110, 32, 9 }, 191 { 134, 53, 8 }, 192 { 150, 47, 8 }, 193 { 200, 35, 8 }, 194 { 300, 47, 7 }, 195 { 600, 47, 6 }, 196 { 1200, 47, 5 }, 197 { 1800, 31, 5 }, 198 { 2400, 47, 4 }, 199 { 4800, 47, 3 }, 200 { 9600, 47, 2 }, 201 { 19200, 47, 1 }, 202 { 38400, 23, 1 }, 203 { 57600, 15, 1 }, 204 { 115200, 7, 1 }, 205 { 230400, 3, 1 }, 206 { 460800, 1, 1 }, 207 { 76800, 11, 1 }, 208 { 153600, 5, 1 }, 209 { 307200, 3, 1 }, 210 { 614400, 3, 0 }, 211 { 921600, 0, 1 }, 212 }; 213 214 int 215 sab_match(struct device *parent, struct cfdata *match, void *aux) 216 { 217 struct ebus_attach_args *ea = aux; 218 char *compat; 219 220 if (strcmp(ea->ea_name, "se") == 0) 221 return (1); 222 223 compat = prom_getpropstring(ea->ea_node, "compatible"); 224 if (compat != NULL && !strcmp(compat, "sab82532")) 225 return (1); 226 227 return (0); 228 } 229 230 void 231 sab_attach(struct device *parent, struct device *self, void *aux) 232 { 233 struct sab_softc *sc = (struct sab_softc *)self; 234 struct ebus_attach_args *ea = aux; 235 uint8_t r; 236 u_int i; 237 int locs[SABCF_NLOCS]; 238 239 sc->sc_bt = ea->ea_bustag; 240 sc->sc_node = ea->ea_node; 241 242 /* Use prom mapping, if available. */ 243 if (ea->ea_nvaddr) 244 sparc_promaddr_to_handle(sc->sc_bt, ea->ea_vaddr[0], &sc->sc_bh); 245 else if (bus_space_map(sc->sc_bt, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 246 ea->ea_reg[0].size, 0, &sc->sc_bh) != 0) { 247 printf(": can't map register space\n"); 248 return; 249 } 250 251 sc->sc_ih = bus_intr_establish(ea->ea_bustag, ea->ea_intr[0], 252 IPL_TTY, sab_intr, sc); 253 if (sc->sc_ih == NULL) { 254 printf(": can't map interrupt\n"); 255 return; 256 } 257 258 sc->sc_softintr = softintr_establish(IPL_TTY, sab_softintr, sc); 259 if (sc->sc_softintr == NULL) { 260 printf(": can't get soft intr\n"); 261 return; 262 } 263 264 aprint_normal(": rev "); 265 r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_VMASK; 266 switch (r) { 267 case SAB_VSTR_V_1: 268 aprint_normal("1"); 269 break; 270 case SAB_VSTR_V_2: 271 aprint_normal("2"); 272 break; 273 case SAB_VSTR_V_32: 274 aprint_normal("3.2"); 275 break; 276 default: 277 aprint_normal("unknown(0x%x)", r); 278 break; 279 } 280 aprint_normal("\n"); 281 282 /* Let current output drain */ 283 DELAY(100000); 284 285 /* Set all pins, except DTR pins to be inputs */ 286 SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B)); 287 /* Disable port interrupts */ 288 SAB_WRITE(sc, SAB_PIM, 0xff); 289 SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC); 290 SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL); 291 292 for (i = 0; i < SAB_NCHAN; i++) { 293 struct sabtty_attach_args stax; 294 295 stax.sbt_portno = i; 296 297 locs[SABCF_CHANNEL] = i; 298 299 sc->sc_child[i] = 300 (struct sabtty_softc *)config_found_sm_loc(self, 301 "sab", locs, &stax, sab_print, config_stdsubmatch); 302 if (sc->sc_child[i] != NULL) 303 sc->sc_nchild++; 304 } 305 } 306 307 int 308 sab_print(void *args, const char *name) 309 { 310 struct sabtty_attach_args *sa = args; 311 312 if (name) 313 aprint_normal("sabtty at %s", name); 314 aprint_normal(" port %u", sa->sbt_portno); 315 return (UNCONF); 316 } 317 318 int 319 sab_intr(void *vsc) 320 { 321 struct sab_softc *sc = vsc; 322 int r = 0, needsoft = 0; 323 uint8_t gis; 324 325 gis = SAB_READ(sc, SAB_GIS); 326 327 /* channel A */ 328 if ((gis & (SAB_GIS_ISA1 | SAB_GIS_ISA0)) && sc->sc_child[0] && 329 sc->sc_child[0]->sc_tty) 330 r |= sabtty_intr(sc->sc_child[0], &needsoft); 331 332 /* channel B */ 333 if ((gis & (SAB_GIS_ISB1 | SAB_GIS_ISB0)) && sc->sc_child[1] && 334 sc->sc_child[1]->sc_tty) 335 r |= sabtty_intr(sc->sc_child[1], &needsoft); 336 337 if (needsoft) 338 softintr_schedule(sc->sc_softintr); 339 340 return (r); 341 } 342 343 void 344 sab_softintr(void *vsc) 345 { 346 struct sab_softc *sc = vsc; 347 348 if (sc->sc_child[0] && sc->sc_child[0]->sc_tty) 349 sabtty_softintr(sc->sc_child[0]); 350 if (sc->sc_child[1] && sc->sc_child[1]->sc_tty) 351 sabtty_softintr(sc->sc_child[1]); 352 } 353 354 int 355 sabtty_match(struct device *parent, struct cfdata *match, void *aux) 356 { 357 358 return (1); 359 } 360 361 void 362 sabtty_attach(struct device *parent, struct device *self, void *aux) 363 { 364 struct sabtty_softc *sc = (struct sabtty_softc *)self; 365 struct sabtty_attach_args *sa = aux; 366 int r; 367 int maj; 368 369 sc->sc_tty = ttymalloc(); 370 if (sc->sc_tty == NULL) { 371 aprint_normal(": failed to allocate tty\n"); 372 return; 373 } 374 tty_attach(sc->sc_tty); 375 sc->sc_tty->t_oproc = sabtty_start; 376 sc->sc_tty->t_param = sabtty_param; 377 378 sc->sc_parent = (struct sab_softc *)parent; 379 sc->sc_bt = sc->sc_parent->sc_bt; 380 sc->sc_portno = sa->sbt_portno; 381 sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE; 382 383 switch (sa->sbt_portno) { 384 case 0: /* port A */ 385 sc->sc_pvr_dtr = SAB_PVR_DTR_A; 386 sc->sc_pvr_dsr = SAB_PVR_DSR_A; 387 r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 388 SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh); 389 break; 390 case 1: /* port B */ 391 sc->sc_pvr_dtr = SAB_PVR_DTR_B; 392 sc->sc_pvr_dsr = SAB_PVR_DSR_B; 393 r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, 394 SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh); 395 break; 396 default: 397 aprint_normal(": invalid channel: %u\n", sa->sbt_portno); 398 return; 399 } 400 if (r != 0) { 401 aprint_normal(": failed to allocate register subregion\n"); 402 return; 403 } 404 405 sabtty_console_flags(sc); 406 407 if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 408 struct termios t; 409 const char *acc; 410 411 /* Let residual prom output drain */ 412 DELAY(100000); 413 414 switch (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 415 case SABTTYF_CONS_IN: 416 acc = "input"; 417 break; 418 case SABTTYF_CONS_OUT: 419 acc = "output"; 420 break; 421 case SABTTYF_CONS_IN|SABTTYF_CONS_OUT: 422 default: 423 acc = "i/o"; 424 break; 425 } 426 427 t.c_ispeed= 0; 428 t.c_ospeed = 9600; 429 t.c_cflag = CREAD | CS8 | HUPCL; 430 sc->sc_tty->t_ospeed = 0; 431 sabttyparam(sc, sc->sc_tty, &t); 432 433 if (sc->sc_flags & SABTTYF_CONS_IN) { 434 sabtty_cons_input = sc; 435 cn_tab->cn_pollc = sab_cnpollc; 436 cn_tab->cn_getc = sab_cngetc; 437 maj = cdevsw_lookup_major(&sabtty_cdevsw); 438 cn_tab->cn_dev = makedev(maj, self->dv_unit); 439 shutdownhook_establish(sabtty_shutdown, sc); 440 cn_init_magic(&sabtty_cnm_state); 441 cn_set_magic("\047\001"); /* default magic is BREAK */ 442 } 443 444 if (sc->sc_flags & SABTTYF_CONS_OUT) { 445 sabtty_tec_wait(sc); 446 sabtty_cons_output = sc; 447 cn_tab->cn_putc = sab_cnputc; 448 maj = cdevsw_lookup_major(&sabtty_cdevsw); 449 cn_tab->cn_dev = makedev(maj, self->dv_unit); 450 } 451 aprint_normal(": console %s", acc); 452 } else { 453 /* Not a console... */ 454 sabtty_reset(sc); 455 } 456 457 aprint_normal("\n"); 458 } 459 460 int 461 sabtty_intr(struct sabtty_softc *sc, int *needsoftp) 462 { 463 uint8_t isr0, isr1; 464 int i, len = 0, needsoft = 0, r = 0, clearfifo = 0; 465 466 isr0 = SAB_READ(sc, SAB_ISR0); 467 isr1 = SAB_READ(sc, SAB_ISR1); 468 469 if (isr0 || isr1) 470 r = 1; 471 472 if (isr0 & SAB_ISR0_RPF) { 473 len = 32; 474 clearfifo = 1; 475 } 476 if (isr0 & SAB_ISR0_TCD) { 477 len = (32 - 1) & SAB_READ(sc, SAB_RBCL); 478 clearfifo = 1; 479 } 480 if (isr0 & SAB_ISR0_TIME) { 481 sabtty_cec_wait(sc); 482 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); 483 } 484 if (isr0 & SAB_ISR0_RFO) { 485 sc->sc_flags |= SABTTYF_RINGOVERFLOW; 486 clearfifo = 1; 487 } 488 if (len != 0) { 489 uint8_t *ptr, b; 490 491 ptr = sc->sc_rput; 492 for (i = 0; i < len; i++) { 493 b = SAB_READ(sc, SAB_RFIFO); 494 if (i % 2 == 0) /* skip status byte */ 495 cn_check_magic(sc->sc_tty->t_dev, 496 b, sabtty_cnm_state); 497 *ptr++ = b; 498 if (ptr == sc->sc_rend) 499 ptr = sc->sc_rbuf; 500 if (ptr == sc->sc_rget) { 501 if (ptr == sc->sc_rbuf) 502 ptr = sc->sc_rend; 503 ptr--; 504 sc->sc_flags |= SABTTYF_RINGOVERFLOW; 505 } 506 } 507 sc->sc_rput = ptr; 508 needsoft = 1; 509 } 510 511 if (clearfifo) { 512 sabtty_cec_wait(sc); 513 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); 514 } 515 516 if (isr0 & SAB_ISR0_CDSC) { 517 sc->sc_flags |= SABTTYF_CDCHG; 518 needsoft = 1; 519 } 520 521 if (isr1 & SAB_ISR1_BRKT) 522 cn_check_magic(sc->sc_tty->t_dev, 523 CNC_BREAK, sabtty_cnm_state); 524 525 if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) { 526 if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) && 527 (sc->sc_flags & SABTTYF_STOP) == 0) { 528 if (sc->sc_txc < 32) 529 len = sc->sc_txc; 530 else 531 len = 32; 532 533 if (len > 0) { 534 SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len); 535 sc->sc_txp += len; 536 sc->sc_txc -= len; 537 538 sabtty_cec_wait(sc); 539 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF); 540 541 /* 542 * Prevent the false end of xmit from 543 * confusing things below. 544 */ 545 isr1 &= ~SAB_ISR1_ALLS; 546 } 547 } 548 549 if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) { 550 if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) { 551 sc->sc_imr1 |= SAB_IMR1_XPR; 552 sc->sc_imr1 &= ~SAB_IMR1_ALLS; 553 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 554 } 555 } 556 } 557 558 if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) || 559 (sc->sc_flags & SABTTYF_STOP))) { 560 if (sc->sc_flags & SABTTYF_TXDRAIN) 561 wakeup(sc); 562 sc->sc_flags &= ~SABTTYF_STOP; 563 sc->sc_flags |= SABTTYF_DONE; 564 sc->sc_imr1 |= SAB_IMR1_ALLS; 565 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 566 needsoft = 1; 567 } 568 569 if (needsoft) 570 *needsoftp = needsoft; 571 return (r); 572 } 573 574 void 575 sabtty_softintr(struct sabtty_softc *sc) 576 { 577 struct tty *tp = sc->sc_tty; 578 int s, flags; 579 uint8_t r; 580 581 if (tp == NULL) 582 return; 583 584 if ((tp->t_state & TS_ISOPEN) == 0) 585 return; 586 587 while (sc->sc_rget != sc->sc_rput) { 588 int data; 589 uint8_t stat; 590 591 data = sc->sc_rget[0]; 592 stat = sc->sc_rget[1]; 593 sc->sc_rget += 2; 594 if (stat & SAB_RSTAT_PE) 595 data |= TTY_PE; 596 if (stat & SAB_RSTAT_FE) 597 data |= TTY_FE; 598 if (sc->sc_rget == sc->sc_rend) 599 sc->sc_rget = sc->sc_rbuf; 600 601 (*tp->t_linesw->l_rint)(data, tp); 602 } 603 604 s = splhigh(); 605 flags = sc->sc_flags; 606 sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW); 607 splx(s); 608 609 if (flags & SABTTYF_CDCHG) { 610 s = spltty(); 611 r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD; 612 splx(s); 613 614 (*tp->t_linesw->l_modem)(tp, r); 615 } 616 617 if (flags & SABTTYF_RINGOVERFLOW) 618 log(LOG_WARNING, "%s: ring overflow\n", sc->sc_dv.dv_xname); 619 620 if (flags & SABTTYF_DONE) { 621 ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf); 622 tp->t_state &= ~TS_BUSY; 623 (*tp->t_linesw->l_start)(tp); 624 } 625 } 626 627 int 628 sabopen(dev_t dev, int flags, int mode, struct lwp *l) 629 { 630 struct sabtty_softc *sc; 631 struct tty *tp; 632 struct proc *p; 633 int s, s1; 634 635 sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 636 if (sc == NULL) 637 return (ENXIO); 638 639 tp = sc->sc_tty; 640 tp->t_dev = dev; 641 p = l->l_proc; 642 643 if ((tp->t_state & TS_ISOPEN) == 0) { 644 ttychars(tp); 645 tp->t_iflag = TTYDEF_IFLAG; 646 tp->t_oflag = TTYDEF_OFLAG; 647 tp->t_cflag = TTYDEF_CFLAG; 648 if (sc->sc_openflags & TIOCFLAG_CLOCAL) 649 tp->t_cflag |= CLOCAL; 650 if (sc->sc_openflags & TIOCFLAG_CRTSCTS) 651 tp->t_cflag |= CRTSCTS; 652 if (sc->sc_openflags & TIOCFLAG_MDMBUF) 653 tp->t_cflag |= MDMBUF; 654 tp->t_lflag = TTYDEF_LFLAG; 655 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 656 657 sc->sc_rput = sc->sc_rget = sc->sc_rbuf; 658 659 s = spltty(); 660 661 ttsetwater(tp); 662 663 s1 = splhigh(); 664 sabtty_reset(sc); 665 sabtty_param(tp, &tp->t_termios); 666 sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA; 667 SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 668 sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU | 669 SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR; 670 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 671 SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU); 672 sabtty_cec_wait(sc); 673 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); 674 sabtty_cec_wait(sc); 675 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 676 sabtty_cec_wait(sc); 677 splx(s1); 678 679 sabtty_flush(sc); 680 681 if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) || 682 (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD)) 683 tp->t_state |= TS_CARR_ON; 684 else 685 tp->t_state &= ~TS_CARR_ON; 686 } else if ((tp->t_state & TS_XCLUDE) && 687 (!suser(p->p_ucred, &p->p_acflag))) { 688 return (EBUSY); 689 } else { 690 s = spltty(); 691 } 692 693 if ((flags & O_NONBLOCK) == 0) { 694 while ((tp->t_cflag & CLOCAL) == 0 && 695 (tp->t_state & TS_CARR_ON) == 0) { 696 int error; 697 698 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 699 "sabttycd", 0); 700 if (error != 0) { 701 splx(s); 702 return (error); 703 } 704 } 705 } 706 707 splx(s); 708 709 s = (*tp->t_linesw->l_open)(dev, tp); 710 if (s != 0) { 711 if (tp->t_state & TS_ISOPEN) 712 return (s); 713 714 if (tp->t_cflag & HUPCL) { 715 sabtty_mdmctrl(sc, 0, DMSET); 716 (void)tsleep(sc, TTIPRI, ttclos, hz); 717 } 718 719 if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) { 720 /* Flush and power down if we're not the console */ 721 sabtty_flush(sc); 722 sabtty_reset(sc); 723 } 724 } 725 return (s); 726 } 727 728 int 729 sabclose(dev_t dev, int flags, int mode, struct lwp *l) 730 { 731 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 732 struct sab_softc *bc = sc->sc_parent; 733 struct tty *tp = sc->sc_tty; 734 int s; 735 736 (*tp->t_linesw->l_close)(tp, flags); 737 738 s = spltty(); 739 740 if ((tp->t_state & TS_ISOPEN) == 0) { 741 /* Wait for output drain */ 742 sc->sc_imr1 &= ~SAB_IMR1_ALLS; 743 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 744 sc->sc_flags |= SABTTYF_TXDRAIN; 745 (void)tsleep(sc, TTIPRI, ttclos, 5 * hz); 746 sc->sc_imr1 |= SAB_IMR1_ALLS; 747 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 748 sc->sc_flags &= ~SABTTYF_TXDRAIN; 749 750 if (tp->t_cflag & HUPCL) { 751 sabtty_mdmctrl(sc, 0, DMSET); 752 (void)tsleep(bc, TTIPRI, ttclos, hz); 753 } 754 755 if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) { 756 /* Flush and power down if we're not the console */ 757 sabtty_flush(sc); 758 sabtty_reset(sc); 759 } 760 } 761 762 ttyclose(tp); 763 splx(s); 764 765 return (0); 766 } 767 768 int 769 sabread(dev_t dev, struct uio *uio, int flags) 770 { 771 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 772 struct tty *tp = sc->sc_tty; 773 774 return ((*tp->t_linesw->l_read)(tp, uio, flags)); 775 } 776 777 int 778 sabwrite(dev_t dev, struct uio *uio, int flags) 779 { 780 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 781 struct tty *tp = sc->sc_tty; 782 783 return ((*tp->t_linesw->l_write)(tp, uio, flags)); 784 } 785 786 int 787 sabioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l) 788 { 789 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 790 struct tty *tp = sc->sc_tty; 791 struct proc *p = l->l_proc; 792 int error; 793 794 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l); 795 if (error >= 0) 796 return (error); 797 798 error = ttioctl(tp, cmd, data, flags, l); 799 if (error >= 0) 800 return (error); 801 802 error = 0; 803 804 switch (cmd) { 805 case TIOCSBRK: 806 SAB_WRITE(sc, SAB_DAFO, 807 SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK); 808 break; 809 case TIOCCBRK: 810 SAB_WRITE(sc, SAB_DAFO, 811 SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK); 812 break; 813 case TIOCSDTR: 814 sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS); 815 break; 816 case TIOCCDTR: 817 sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC); 818 break; 819 case TIOCMBIS: 820 sabtty_mdmctrl(sc, *((int *)data), DMBIS); 821 break; 822 case TIOCMBIC: 823 sabtty_mdmctrl(sc, *((int *)data), DMBIC); 824 break; 825 case TIOCMGET: 826 *((int *)data) = sabtty_mdmctrl(sc, 0, DMGET); 827 break; 828 case TIOCMSET: 829 sabtty_mdmctrl(sc, *((int *)data), DMSET); 830 break; 831 case TIOCGFLAGS: 832 *((int *)data) = sc->sc_openflags; 833 break; 834 case TIOCSFLAGS: 835 if (suser(p->p_ucred, &p->p_acflag)) 836 error = EPERM; 837 else 838 sc->sc_openflags = *((int *)data) & 839 (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | 840 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF); 841 break; 842 default: 843 error = ENOTTY; 844 } 845 846 return (error); 847 } 848 849 struct tty * 850 sabtty(dev_t dev) 851 { 852 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 853 854 return (sc->sc_tty); 855 } 856 857 void 858 sabstop(struct tty *tp, int flag) 859 { 860 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev)); 861 int s; 862 863 s = spltty(); 864 if (tp->t_state & TS_BUSY) { 865 if ((tp->t_state & TS_TTSTOP) == 0) 866 tp->t_state |= TS_FLUSH; 867 sc->sc_flags |= SABTTYF_STOP; 868 sc->sc_imr1 &= ~SAB_IMR1_ALLS; 869 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 870 } 871 splx(s); 872 } 873 874 int 875 sabpoll(dev_t dev, int events, struct lwp *l) 876 { 877 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev)); 878 struct tty *tp = sc->sc_tty; 879 880 return ((*tp->t_linesw->l_poll)(tp, events, l)); 881 } 882 883 int 884 sabtty_mdmctrl(struct sabtty_softc *sc, int bits, int how) 885 { 886 uint8_t r; 887 int s; 888 889 s = spltty(); 890 switch (how) { 891 case DMGET: 892 bits = 0; 893 if (SAB_READ(sc, SAB_STAR) & SAB_STAR_CTS) 894 bits |= TIOCM_CTS; 895 if ((SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD) == 0) 896 bits |= TIOCM_CD; 897 898 r = SAB_READ(sc, SAB_PVR); 899 if ((r & sc->sc_pvr_dtr) == 0) 900 bits |= TIOCM_DTR; 901 if ((r & sc->sc_pvr_dsr) == 0) 902 bits |= TIOCM_DSR; 903 904 r = SAB_READ(sc, SAB_MODE); 905 if ((r & (SAB_MODE_RTS|SAB_MODE_FRTS)) == SAB_MODE_RTS) 906 bits |= TIOCM_RTS; 907 break; 908 case DMSET: 909 r = SAB_READ(sc, SAB_MODE); 910 if (bits & TIOCM_RTS) { 911 r &= ~SAB_MODE_FRTS; 912 r |= SAB_MODE_RTS; 913 } else 914 r |= SAB_MODE_FRTS | SAB_MODE_RTS; 915 SAB_WRITE(sc, SAB_MODE, r); 916 917 r = SAB_READ(sc, SAB_PVR); 918 if (bits & TIOCM_DTR) 919 r &= ~sc->sc_pvr_dtr; 920 else 921 r |= sc->sc_pvr_dtr; 922 SAB_WRITE(sc, SAB_PVR, r); 923 break; 924 case DMBIS: 925 if (bits & TIOCM_RTS) { 926 r = SAB_READ(sc, SAB_MODE); 927 r &= ~SAB_MODE_FRTS; 928 r |= SAB_MODE_RTS; 929 SAB_WRITE(sc, SAB_MODE, r); 930 } 931 if (bits & TIOCM_DTR) { 932 r = SAB_READ(sc, SAB_PVR); 933 r &= ~sc->sc_pvr_dtr; 934 SAB_WRITE(sc, SAB_PVR, r); 935 } 936 break; 937 case DMBIC: 938 if (bits & TIOCM_RTS) { 939 r = SAB_READ(sc, SAB_MODE); 940 r |= SAB_MODE_FRTS | SAB_MODE_RTS; 941 SAB_WRITE(sc, SAB_MODE, r); 942 } 943 if (bits & TIOCM_DTR) { 944 r = SAB_READ(sc, SAB_PVR); 945 r |= sc->sc_pvr_dtr; 946 SAB_WRITE(sc, SAB_PVR, r); 947 } 948 break; 949 } 950 splx(s); 951 return (bits); 952 } 953 954 int 955 sabttyparam(struct sabtty_softc *sc, struct tty *tp, struct termios *t) 956 { 957 int s, ospeed; 958 tcflag_t cflag; 959 uint8_t dafo, r; 960 961 ospeed = sabtty_speed(t->c_ospeed); 962 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 963 return (EINVAL); 964 965 s = spltty(); 966 967 /* hang up line if ospeed is zero, otherwise raise dtr */ 968 sabtty_mdmctrl(sc, TIOCM_DTR, 969 (t->c_ospeed == 0) ? DMBIC : DMBIS); 970 971 dafo = SAB_READ(sc, SAB_DAFO); 972 973 cflag = t->c_cflag; 974 975 if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { 976 cflag |= CLOCAL; 977 cflag &= ~HUPCL; 978 } 979 980 if (cflag & CSTOPB) 981 dafo |= SAB_DAFO_STOP; 982 else 983 dafo &= ~SAB_DAFO_STOP; 984 985 dafo &= ~SAB_DAFO_CHL_CSIZE; 986 switch (cflag & CSIZE) { 987 case CS5: 988 dafo |= SAB_DAFO_CHL_CS5; 989 break; 990 case CS6: 991 dafo |= SAB_DAFO_CHL_CS6; 992 break; 993 case CS7: 994 dafo |= SAB_DAFO_CHL_CS7; 995 break; 996 default: 997 dafo |= SAB_DAFO_CHL_CS8; 998 break; 999 } 1000 1001 dafo &= ~SAB_DAFO_PARMASK; 1002 if (cflag & PARENB) { 1003 if (cflag & PARODD) 1004 dafo |= SAB_DAFO_PAR_ODD; 1005 else 1006 dafo |= SAB_DAFO_PAR_EVEN; 1007 } else 1008 dafo |= SAB_DAFO_PAR_NONE; 1009 1010 if (ospeed != 0) { 1011 SAB_WRITE(sc, SAB_BGR, ospeed & 0xff); 1012 r = SAB_READ(sc, SAB_CCR2); 1013 r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8); 1014 r |= (ospeed >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8); 1015 SAB_WRITE(sc, SAB_CCR2, r); 1016 } 1017 1018 r = SAB_READ(sc, SAB_MODE); 1019 r |= SAB_MODE_RAC; 1020 if (cflag & CRTSCTS) { 1021 r &= ~(SAB_MODE_RTS | SAB_MODE_FCTS); 1022 r |= SAB_MODE_FRTS; 1023 sc->sc_imr1 &= ~SAB_IMR1_CSC; 1024 } else { 1025 r |= SAB_MODE_RTS | SAB_MODE_FCTS; 1026 r &= ~SAB_MODE_FRTS; 1027 sc->sc_imr1 |= SAB_IMR1_CSC; 1028 } 1029 SAB_WRITE(sc, SAB_MODE, r); 1030 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1031 1032 tp->t_cflag = cflag; 1033 1034 splx(s); 1035 return (0); 1036 } 1037 1038 int 1039 sabtty_param(struct tty *tp, struct termios *t) 1040 { 1041 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev)); 1042 1043 return (sabttyparam(sc, tp, t)); 1044 } 1045 1046 void 1047 sabtty_start(struct tty *tp) 1048 { 1049 struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev)); 1050 int s; 1051 1052 s = spltty(); 1053 if ((tp->t_state & (TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) == 0) { 1054 if (tp->t_outq.c_cc <= tp->t_lowat) { 1055 if (tp->t_state & TS_ASLEEP) { 1056 tp->t_state &= ~TS_ASLEEP; 1057 wakeup(&tp->t_outq); 1058 } 1059 selwakeup(&tp->t_wsel); 1060 } 1061 if (tp->t_outq.c_cc) { 1062 sc->sc_txc = ndqb(&tp->t_outq, 0); 1063 sc->sc_txp = tp->t_outq.c_cf; 1064 tp->t_state |= TS_BUSY; 1065 sc->sc_imr1 &= ~(SAB_ISR1_XPR | SAB_ISR1_ALLS); 1066 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1067 } 1068 } 1069 splx(s); 1070 } 1071 1072 void 1073 sabtty_cec_wait(struct sabtty_softc *sc) 1074 { 1075 int i = 50000; 1076 1077 for (;;) { 1078 if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0) 1079 return; 1080 if (--i == 0) 1081 break; 1082 DELAY(1); 1083 } 1084 } 1085 1086 void 1087 sabtty_tec_wait(struct sabtty_softc *sc) 1088 { 1089 int i = 200000; 1090 1091 for (;;) { 1092 if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0) 1093 return; 1094 if (--i == 0) 1095 break; 1096 DELAY(1); 1097 } 1098 } 1099 1100 void 1101 sabtty_reset(struct sabtty_softc *sc) 1102 { 1103 /* power down */ 1104 SAB_WRITE(sc, SAB_CCR0, 0); 1105 1106 /* set basic configuration */ 1107 SAB_WRITE(sc, SAB_CCR0, 1108 SAB_CCR0_MCE | SAB_CCR0_SC_NRZ | SAB_CCR0_SM_ASYNC); 1109 SAB_WRITE(sc, SAB_CCR1, SAB_CCR1_ODS | SAB_CCR1_BCR | SAB_CCR1_CM_7); 1110 SAB_WRITE(sc, SAB_CCR2, SAB_CCR2_BDF | SAB_CCR2_SSEL | SAB_CCR2_TOE); 1111 SAB_WRITE(sc, SAB_CCR3, 0); 1112 SAB_WRITE(sc, SAB_CCR4, SAB_CCR4_MCK4 | SAB_CCR4_EBRG); 1113 SAB_WRITE(sc, SAB_MODE, SAB_MODE_RTS | SAB_MODE_FCTS | SAB_MODE_RAC); 1114 SAB_WRITE(sc, SAB_RFC, 1115 SAB_RFC_DPS | SAB_RFC_RFDF | SAB_RFC_RFTH_32CHAR); 1116 1117 /* clear interrupts */ 1118 sc->sc_imr0 = sc->sc_imr1 = 0xff; 1119 SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0); 1120 SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); 1121 SAB_READ(sc, SAB_ISR0); 1122 SAB_READ(sc, SAB_ISR1); 1123 } 1124 1125 void 1126 sabtty_flush(struct sabtty_softc *sc) 1127 { 1128 /* clear rx fifo */ 1129 sabtty_cec_wait(sc); 1130 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1131 1132 /* clear tx fifo */ 1133 sabtty_cec_wait(sc); 1134 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES); 1135 } 1136 1137 int 1138 sabtty_speed(int rate) 1139 { 1140 int i, len, r; 1141 1142 if (rate == 0) 1143 return (0); 1144 len = sizeof(sabtty_baudtable)/sizeof(sabtty_baudtable[0]); 1145 for (i = 0; i < len; i++) { 1146 if (rate == sabtty_baudtable[i].baud) { 1147 r = sabtty_baudtable[i].n | 1148 (sabtty_baudtable[i].m << 6); 1149 return (r); 1150 } 1151 } 1152 return (-1); 1153 } 1154 1155 void 1156 sabtty_cnputc(struct sabtty_softc *sc, int c) 1157 { 1158 sabtty_tec_wait(sc); 1159 SAB_WRITE(sc, SAB_TIC, c); 1160 sabtty_tec_wait(sc); 1161 } 1162 1163 int 1164 sabtty_cngetc(struct sabtty_softc *sc) 1165 { 1166 uint8_t r, len; 1167 1168 again: 1169 do { 1170 r = SAB_READ(sc, SAB_STAR); 1171 } while ((r & SAB_STAR_RFNE) == 0); 1172 1173 /* 1174 * Ok, at least one byte in RFIFO, ask for permission to access RFIFO 1175 * (I hate this chip... hate hate hate). 1176 */ 1177 sabtty_cec_wait(sc); 1178 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); 1179 1180 /* Wait for RFIFO to come ready */ 1181 do { 1182 r = SAB_READ(sc, SAB_ISR0); 1183 } while ((r & SAB_ISR0_TCD) == 0); 1184 1185 len = SAB_READ(sc, SAB_RBCL) & (32 - 1); 1186 if (len == 0) 1187 goto again; /* Shouldn't happen... */ 1188 1189 r = SAB_READ(sc, SAB_RFIFO); 1190 1191 /* 1192 * Blow away everything left in the FIFO... 1193 */ 1194 sabtty_cec_wait(sc); 1195 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); 1196 return (r); 1197 } 1198 1199 void 1200 sabtty_cnpollc(struct sabtty_softc *sc, int on) 1201 { 1202 uint8_t r; 1203 1204 if (on) { 1205 if (sc->sc_polling) 1206 return; 1207 SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) | SAB_IPC_VIS); 1208 r = sc->sc_pollrfc = SAB_READ(sc, SAB_RFC); 1209 r &= ~(SAB_RFC_RFDF); 1210 SAB_WRITE(sc, SAB_RFC, r); 1211 sabtty_cec_wait(sc); 1212 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1213 sc->sc_polling = 1; 1214 } else { 1215 if (!sc->sc_polling) 1216 return; 1217 SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) & ~SAB_IPC_VIS); 1218 SAB_WRITE(sc, SAB_RFC, sc->sc_pollrfc); 1219 sabtty_cec_wait(sc); 1220 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1221 sc->sc_polling = 0; 1222 } 1223 } 1224 1225 void 1226 sab_cnputc(dev_t dev, int c) 1227 { 1228 struct sabtty_softc *sc = sabtty_cons_output; 1229 1230 if (sc == NULL) 1231 return; 1232 sabtty_cnputc(sc, c); 1233 } 1234 1235 void 1236 sab_cnpollc(dev_t dev, int on) 1237 { 1238 struct sabtty_softc *sc = sabtty_cons_input; 1239 1240 sabtty_cnpollc(sc, on); 1241 } 1242 1243 int 1244 sab_cngetc(dev_t dev) 1245 { 1246 struct sabtty_softc *sc = sabtty_cons_input; 1247 1248 if (sc == NULL) 1249 return (-1); 1250 return (sabtty_cngetc(sc)); 1251 } 1252 1253 void 1254 sabtty_console_flags(struct sabtty_softc *sc) 1255 { 1256 int node, channel, cookie; 1257 char buf[255]; 1258 1259 node = sc->sc_parent->sc_node; 1260 channel = sc->sc_portno; 1261 1262 /* Default to channel 0 if there are no explicit prom args */ 1263 cookie = 0; 1264 1265 if (node == prom_instance_to_package(prom_stdin())) { 1266 if (prom_getoption("input-device", buf, sizeof buf) == 0 && 1267 strcmp("ttyb", buf) == 0) 1268 cookie = 1; 1269 1270 if (channel == cookie) 1271 sc->sc_flags |= SABTTYF_CONS_IN; 1272 } 1273 1274 /* Default to same channel if there are no explicit prom args */ 1275 1276 if (node == prom_instance_to_package(prom_stdout())) { 1277 if (prom_getoption("output-device", buf, sizeof buf) == 0 && 1278 strcmp("ttyb", buf) == 0) 1279 cookie = 1; 1280 1281 if (channel == cookie) 1282 sc->sc_flags |= SABTTYF_CONS_OUT; 1283 } 1284 } 1285 1286 void 1287 sabtty_shutdown(void *vsc) 1288 { 1289 struct sabtty_softc *sc = vsc; 1290 1291 /* Have to put the chip back into single char mode */ 1292 sc->sc_flags |= SABTTYF_DONTDDB; 1293 SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF); 1294 sabtty_cec_wait(sc); 1295 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES); 1296 sabtty_cec_wait(sc); 1297 } 1298