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