1 /* $OpenBSD: zs.c,v 1.32 2021/10/24 17:05:04 mpi Exp $ */ 2 /* $NetBSD: zs.c,v 1.29 2001/05/30 15:24:24 lukem Exp $ */ 3 4 /*- 5 * Copyright (c) 1996 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Gordon W. Ross. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Zilog Z8530 Dual UART driver (machine-dependent part) 35 * 36 * Runs two serial lines per chip using slave drivers. 37 * Plain tty/async lines use the zstty slave. 38 * Sun keyboard/mouse uses the zskbd/zsms slaves. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/conf.h> 44 #include <sys/device.h> 45 #include <sys/ioctl.h> 46 #include <sys/kernel.h> 47 #include <sys/proc.h> 48 #include <sys/tty.h> 49 #include <sys/time.h> 50 #include <sys/syslog.h> 51 52 #include <machine/autoconf.h> 53 #include <machine/openfirm.h> 54 #include <machine/conf.h> 55 #include <machine/cpu.h> 56 #include <machine/psl.h> 57 #include <machine/z8530var.h> 58 59 #include <dev/cons.h> 60 #include <dev/ic/z8530reg.h> 61 #include <sparc64/dev/fhcvar.h> 62 #include <ddb/db_output.h> 63 64 #include <sparc64/dev/cons.h> 65 66 struct cfdriver zs_cd = { 67 NULL, "zs", DV_TTY 68 }; 69 70 /* 71 * Some warts needed by z8530tty.c - 72 * The default parity REALLY needs to be the same as the PROM uses, 73 * or you can not see messages done with printf during boot-up... 74 */ 75 int zs_def_cflag = (CREAD | CS8 | HUPCL); 76 int zs_major = 12; 77 78 /* 79 * The Sun provides a 4.9152 MHz clock to the ZS chips. 80 */ 81 #define PCLK (9600 * 512) /* PCLK pin input clock rate */ 82 83 #define ZS_DELAY() 84 85 /* The layout of this is hardware-dependent (padding, order). */ 86 struct zschan { 87 volatile u_char zc_csr; /* ctrl,status, and indirect access */ 88 u_char zc_xxx0; 89 volatile u_char zc_data; /* data */ 90 u_char zc_xxx1; 91 }; 92 struct zsdevice { 93 /* Yes, they are backwards. */ 94 struct zschan zs_chan_b; 95 struct zschan zs_chan_a; 96 }; 97 98 /* ZS channel used as the console device (if any) */ 99 void *zs_conschan_get, *zs_conschan_put; 100 101 static u_char zs_init_reg[16] = { 102 0, /* 0: CMD (reset, etc.) */ 103 0, /* 1: No interrupts yet. */ 104 0, /* 2: IVECT */ 105 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 106 ZSWR4_CLK_X16 | ZSWR4_ONESB, 107 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 108 0, /* 6: TXSYNC/SYNCLO */ 109 0, /* 7: RXSYNC/SYNCHI */ 110 0, /* 8: alias for data port */ 111 ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR, 112 0, /*10: Misc. TX/RX control bits */ 113 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 114 ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */ 115 0, /*13: BAUDHI (default=9600) */ 116 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 117 ZSWR15_BREAK_IE, 118 }; 119 120 /* Console ops */ 121 static int zscngetc(dev_t); 122 static void zscnputc(dev_t, int); 123 static void zscnpollc(dev_t, int); 124 125 struct consdev zs_consdev = { 126 NULL, 127 NULL, 128 zscngetc, 129 zscnputc, 130 zscnpollc, 131 NULL, 132 }; 133 134 135 /**************************************************************** 136 * Autoconfig 137 ****************************************************************/ 138 139 /* Definition of the driver for autoconfig. */ 140 static int zs_match_sbus(struct device *, void *, void *); 141 static void zs_attach_sbus(struct device *, struct device *, void *); 142 143 static int zs_match_fhc(struct device *, void *, void *); 144 static void zs_attach_fhc(struct device *, struct device *, void *); 145 146 static void zs_attach(struct zsc_softc *, struct zsdevice *, int); 147 static int zs_print(void *, const char *name); 148 149 const struct cfattach zs_sbus_ca = { 150 sizeof(struct zsc_softc), zs_match_sbus, zs_attach_sbus 151 }; 152 153 const struct cfattach zs_fhc_ca = { 154 sizeof(struct zsc_softc), zs_match_fhc, zs_attach_fhc 155 }; 156 157 extern int stdinnode; 158 extern int fbnode; 159 160 /* Interrupt handlers. */ 161 static int zshard(void *); 162 static void zssoft(void *); 163 164 static int zs_get_speed(struct zs_chanstate *); 165 166 /* Console device support */ 167 static int zs_console_flags(int, int, int); 168 169 /* 170 * Is the zs chip present? 171 */ 172 static int 173 zs_match_sbus(struct device *parent, void *vcf, void *aux) 174 { 175 struct cfdata *cf = vcf; 176 struct sbus_attach_args *sa = aux; 177 178 if (strcmp(cf->cf_driver->cd_name, sa->sa_name) != 0) 179 return (0); 180 181 return (1); 182 } 183 184 static int 185 zs_match_fhc(struct device *parent, void *vcf, void *aux) 186 { 187 struct cfdata *cf = vcf; 188 struct fhc_attach_args *fa = aux; 189 190 if (strcmp(cf->cf_driver->cd_name, fa->fa_name) != 0) 191 return (0); 192 return (1); 193 } 194 195 static void 196 zs_attach_sbus(struct device *parent, struct device *self, void *aux) 197 { 198 struct zsc_softc *zsc = (void *) self; 199 struct sbus_attach_args *sa = aux; 200 struct zsdevice *zsaddr; 201 bus_space_handle_t kvaddr; 202 203 if (sa->sa_nintr == 0) { 204 printf(" no interrupt lines\n"); 205 return; 206 } 207 208 /* Only map registers once. */ 209 if (sa->sa_npromvaddrs) { 210 /* 211 * We're converting from a 32-bit pointer to a 64-bit 212 * pointer. Since the 32-bit entity is negative, but 213 * the kernel is still mapped into the lower 4GB 214 * range, this needs to be zero-extended. 215 * 216 * XXXXX If we map the kernel and devices into the 217 * high 4GB range, this needs to be changed to 218 * sign-extend the address. 219 */ 220 zsaddr = (struct zsdevice *) 221 (unsigned long int)sa->sa_promvaddrs[0]; 222 } else { 223 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, 224 sa->sa_size, BUS_SPACE_MAP_LINEAR, 0, &kvaddr) != 0) { 225 printf("%s @ sbus: cannot map registers\n", 226 self->dv_xname); 227 return; 228 } 229 zsaddr = (struct zsdevice *) 230 bus_space_vaddr(sa->sa_bustag, kvaddr); 231 } 232 233 zsc->zsc_bustag = sa->sa_bustag; 234 zsc->zsc_dmatag = sa->sa_dmatag; 235 zsc->zsc_promunit = getpropint(sa->sa_node, "slave", -2); 236 zsc->zsc_node = sa->sa_node; 237 238 zs_attach(zsc, zsaddr, sa->sa_pri); 239 } 240 241 static void 242 zs_attach_fhc(struct device *parent, struct device *self, void *aux) 243 { 244 struct zsc_softc *zsc = (void *) self; 245 struct fhc_attach_args *fa = aux; 246 struct zsdevice *zsaddr; 247 bus_space_handle_t kvaddr; 248 249 if (fa->fa_nreg < 1 && fa->fa_npromvaddrs < 1) { 250 printf(": no registers\n"); 251 return; 252 } 253 254 if (fa->fa_nintr < 1) { 255 printf(": no interrupts\n"); 256 return; 257 } 258 259 if (fa->fa_npromvaddrs) { 260 /* 261 * We're converting from a 32-bit pointer to a 64-bit 262 * pointer. Since the 32-bit entity is negative, but 263 * the kernel is still mapped into the lower 4GB 264 * range, this needs to be zero-extended. 265 * 266 * XXXXX If we map the kernel and devices into the 267 * high 4GB range, this needs to be changed to 268 * sign-extend the address. 269 */ 270 zsaddr = (struct zsdevice *) 271 (unsigned long int)fa->fa_promvaddrs[0]; 272 } else { 273 if (fhc_bus_map(fa->fa_bustag, fa->fa_reg[0].fbr_slot, 274 fa->fa_reg[0].fbr_offset, fa->fa_reg[0].fbr_size, 275 BUS_SPACE_MAP_LINEAR, &kvaddr) != 0) { 276 printf("%s @ fhc: cannot map registers\n", 277 self->dv_xname); 278 return; 279 } 280 zsaddr = (struct zsdevice *) 281 bus_space_vaddr(fa->fa_bustag, kvaddr); 282 } 283 284 zsc->zsc_bustag = fa->fa_bustag; 285 zsc->zsc_dmatag = NULL; 286 zsc->zsc_promunit = getpropint(fa->fa_node, "slave", -2); 287 zsc->zsc_node = fa->fa_node; 288 289 zs_attach(zsc, zsaddr, fa->fa_intr[0]); 290 } 291 292 /* 293 * Attach a found zs. 294 * 295 * USE ROM PROPERTY keyboard FOR KEYBOARD/MOUSE? 296 */ 297 static void 298 zs_attach(struct zsc_softc *zsc, struct zsdevice *zsd, int pri) 299 { 300 struct zsc_attach_args zsc_args; 301 struct zs_chanstate *cs; 302 int s, channel, softpri = PIL_TTY; 303 304 if (zsd == NULL) { 305 printf("configuration incomplete\n"); 306 return; 307 } 308 309 printf(" softpri %d\n", softpri); 310 311 /* 312 * Initialize software state for each channel. 313 */ 314 for (channel = 0; channel < 2; channel++) { 315 struct zschan *zc; 316 struct device *child; 317 318 zsc_args.type = "serial"; 319 if (getproplen(zsc->zsc_node, "keyboard") == 0) { 320 if (channel == 0) 321 zsc_args.type = "keyboard"; 322 if (channel == 1) 323 zsc_args.type = "mouse"; 324 } 325 326 zsc_args.channel = channel; 327 cs = &zsc->zsc_cs_store[channel]; 328 zsc->zsc_cs[channel] = cs; 329 330 cs->cs_channel = channel; 331 cs->cs_private = NULL; 332 cs->cs_ops = &zsops_null; 333 cs->cs_brg_clk = PCLK / 16; 334 335 zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b; 336 337 zsc_args.consdev = NULL; 338 zsc_args.hwflags = zs_console_flags(zsc->zsc_promunit, 339 zsc->zsc_node, 340 channel); 341 342 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 343 zsc_args.hwflags |= ZS_HWFLAG_USE_CONSDEV; 344 zsc_args.consdev = &zs_consdev; 345 } 346 347 if (getproplen(zsc->zsc_node, channel == 0 ? 348 "port-a-ignore-cd" : "port-b-ignore-cd") == 0) { 349 zsc_args.hwflags |= ZS_HWFLAG_NO_DCD; 350 } 351 352 if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) { 353 zs_conschan_get = zc; 354 } 355 if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) { 356 zs_conschan_put = zc; 357 } 358 /* Childs need to set cn_dev, etc */ 359 360 cs->cs_reg_csr = &zc->zc_csr; 361 cs->cs_reg_data = &zc->zc_data; 362 363 bcopy(zs_init_reg, cs->cs_creg, 16); 364 bcopy(zs_init_reg, cs->cs_preg, 16); 365 366 /* XXX: Consult PROM properties for this?! */ 367 cs->cs_defspeed = zs_get_speed(cs); 368 cs->cs_defcflag = zs_def_cflag; 369 370 /* Make these correspond to cs_defcflag (-crtscts) */ 371 cs->cs_rr0_dcd = ZSRR0_DCD; 372 cs->cs_rr0_cts = 0; 373 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 374 cs->cs_wr5_rts = 0; 375 376 /* 377 * Clear the master interrupt enable. 378 * The INTENA is common to both channels, 379 * so just do it on the A channel. 380 */ 381 if (channel == 0) { 382 zs_write_reg(cs, 9, 0); 383 } 384 385 /* 386 * Look for a child driver for this channel. 387 * The child attach will setup the hardware. 388 */ 389 if (!(child = 390 config_found(&zsc->zsc_dev, (void *)&zsc_args, zs_print))) { 391 /* No sub-driver. Just reset it. */ 392 u_char reset = (channel == 0) ? 393 ZSWR9_A_RESET : ZSWR9_B_RESET; 394 s = splzs(); 395 zs_write_reg(cs, 9, reset); 396 splx(s); 397 } 398 } 399 400 /* 401 * Now safe to install interrupt handlers. 402 */ 403 if (bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, 0, zshard, 404 zsc, zsc->zsc_dev.dv_xname) == NULL) 405 panic("zsattach: could not establish interrupt"); 406 if (!(zsc->zsc_softintr = softintr_establish(softpri, zssoft, zsc))) 407 panic("zsattach: could not establish soft interrupt"); 408 409 /* 410 * Set the master interrupt enable and interrupt vector. 411 * (common to both channels, do it on A) 412 */ 413 cs = zsc->zsc_cs[0]; 414 s = splhigh(); 415 /* interrupt vector */ 416 zs_write_reg(cs, 2, zs_init_reg[2]); 417 /* master interrupt control (enable) */ 418 zs_write_reg(cs, 9, zs_init_reg[9]); 419 splx(s); 420 421 } 422 423 static int 424 zs_print(void *aux, const char *name) 425 { 426 struct zsc_attach_args *args = aux; 427 428 if (name != NULL) 429 printf("%s: ", name); 430 431 if (args->channel != -1) 432 printf(" channel %d", args->channel); 433 434 return (UNCONF); 435 } 436 437 static int 438 zshard(void *arg) 439 { 440 struct zsc_softc *zsc = (struct zsc_softc *)arg; 441 int rval = 0; 442 443 while (zsc_intr_hard(zsc)) 444 rval = 1; 445 if ((zsc->zsc_cs[0] && zsc->zsc_cs[0]->cs_softreq) || 446 (zsc->zsc_cs[1] && zsc->zsc_cs[1]->cs_softreq)) 447 softintr_schedule(zsc->zsc_softintr); 448 return (rval); 449 } 450 451 /* 452 * We need this only for TTY_DEBUG purposes. 453 */ 454 static void 455 zssoft(void *arg) 456 { 457 struct zsc_softc *zsc = (struct zsc_softc *)arg; 458 int s; 459 460 /* Make sure we call the tty layer at spltty. */ 461 s = spltty(); 462 (void)zsc_intr_soft(zsc); 463 #ifdef TTY_DEBUG 464 { 465 struct zstty_softc *zst0 = zsc->zsc_cs[0]->cs_private; 466 struct zstty_softc *zst1 = zsc->zsc_cs[1]->cs_private; 467 if (zst0->zst_overflows || zst1->zst_overflows ) { 468 struct trapframe *frame = (struct trapframe *)arg; 469 470 printf("zs silo overflow from %p\n", 471 (long)frame->tf_pc); 472 } 473 } 474 #endif 475 splx(s); 476 } 477 478 479 /* 480 * Compute the current baud rate given a ZS channel. 481 */ 482 static int 483 zs_get_speed(struct zs_chanstate *cs) 484 { 485 int tconst; 486 487 tconst = zs_read_reg(cs, 12); 488 tconst |= zs_read_reg(cs, 13) << 8; 489 return (TCONST_TO_BPS(cs->cs_brg_clk, tconst)); 490 } 491 492 /* 493 * MD functions for setting the baud rate and control modes. 494 */ 495 int 496 zs_set_speed(struct zs_chanstate *cs, int bps) 497 { 498 int tconst, real_bps; 499 500 if (bps == 0) 501 return (0); 502 503 #ifdef DIAGNOSTIC 504 if (cs->cs_brg_clk == 0) 505 panic("zs_set_speed"); 506 #endif 507 508 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 509 if (tconst < 0) 510 return (EINVAL); 511 512 /* Convert back to make sure we can do it. */ 513 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 514 515 /* XXX - Allow some tolerance here? */ 516 if (real_bps != bps) 517 return (EINVAL); 518 519 cs->cs_preg[12] = tconst; 520 cs->cs_preg[13] = tconst >> 8; 521 522 /* Caller will stuff the pending registers. */ 523 return (0); 524 } 525 526 int 527 zs_set_modes(struct zs_chanstate *cs, int cflag) 528 { 529 int s; 530 531 /* 532 * Output hardware flow control on the chip is horrendous: 533 * if carrier detect drops, the receiver is disabled, and if 534 * CTS drops, the transmitter is stopped IN MID CHARACTER! 535 * Therefore, NEVER set the HFC bit, and instead use the 536 * status interrupt to detect CTS changes. 537 */ 538 s = splzs(); 539 cs->cs_rr0_pps = 0; 540 if ((cflag & (CLOCAL | MDMBUF)) != 0) { 541 cs->cs_rr0_dcd = 0; 542 if ((cflag & MDMBUF) == 0) 543 cs->cs_rr0_pps = ZSRR0_DCD; 544 } else 545 cs->cs_rr0_dcd = ZSRR0_DCD; 546 if ((cflag & CRTSCTS) != 0) { 547 cs->cs_wr5_dtr = ZSWR5_DTR; 548 cs->cs_wr5_rts = ZSWR5_RTS; 549 cs->cs_rr0_cts = ZSRR0_CTS; 550 #if 0 /* JLW */ 551 } else if ((cflag & CDTRCTS) != 0) { 552 cs->cs_wr5_dtr = 0; 553 cs->cs_wr5_rts = ZSWR5_DTR; 554 cs->cs_rr0_cts = ZSRR0_CTS; 555 #endif 556 } else if ((cflag & MDMBUF) != 0) { 557 cs->cs_wr5_dtr = 0; 558 cs->cs_wr5_rts = ZSWR5_DTR; 559 cs->cs_rr0_cts = ZSRR0_DCD; 560 } else { 561 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 562 cs->cs_wr5_rts = 0; 563 cs->cs_rr0_cts = 0; 564 } 565 splx(s); 566 567 /* Caller will stuff the pending registers. */ 568 return (0); 569 } 570 571 572 /* 573 * Read or write the chip with suitable delays. 574 */ 575 576 u_char 577 zs_read_reg(struct zs_chanstate *cs, u_char reg) 578 { 579 u_char val; 580 581 *cs->cs_reg_csr = reg; 582 ZS_DELAY(); 583 val = *cs->cs_reg_csr; 584 ZS_DELAY(); 585 return (val); 586 } 587 588 void 589 zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val) 590 { 591 *cs->cs_reg_csr = reg; 592 ZS_DELAY(); 593 *cs->cs_reg_csr = val; 594 ZS_DELAY(); 595 } 596 597 u_char 598 zs_read_csr(struct zs_chanstate *cs) 599 { 600 u_char val; 601 602 val = *cs->cs_reg_csr; 603 ZS_DELAY(); 604 return (val); 605 } 606 607 void 608 zs_write_csr(struct zs_chanstate *cs, u_char val) 609 { 610 *cs->cs_reg_csr = val; 611 ZS_DELAY(); 612 } 613 614 u_char 615 zs_read_data(struct zs_chanstate *cs) 616 { 617 u_char val; 618 619 val = *cs->cs_reg_data; 620 ZS_DELAY(); 621 return (val); 622 } 623 624 void 625 zs_write_data(struct zs_chanstate *cs, u_char val) 626 { 627 *cs->cs_reg_data = val; 628 ZS_DELAY(); 629 } 630 631 /**************************************************************** 632 * Console support functions (Sun specific!) 633 * Note: this code is allowed to know about the layout of 634 * the chip registers, and uses that to keep things simple. 635 * XXX - I think I like the mvme167 code better. -gwr 636 ****************************************************************/ 637 638 /* 639 * Handle user request to enter kernel debugger. 640 */ 641 void 642 zs_abort(struct zs_chanstate *cs) 643 { 644 volatile struct zschan *zc = zs_conschan_get; 645 int rr0; 646 647 /* Wait for end of break to avoid PROM abort. */ 648 /* XXX - Limit the wait? */ 649 do { 650 rr0 = zc->zc_csr; 651 ZS_DELAY(); 652 } while (rr0 & ZSRR0_BREAK); 653 654 #if defined(DDB) 655 { 656 extern int db_active; 657 658 if (!db_active) 659 db_enter(); 660 else 661 /* Debugger is probably hozed */ 662 callrom(); 663 } 664 #else 665 printf("stopping on keyboard abort\n"); 666 callrom(); 667 #endif 668 } 669 670 671 /* 672 * Polled input char. 673 */ 674 int 675 zs_getc(void *arg) 676 { 677 volatile struct zschan *zc = arg; 678 int s, c, rr0; 679 680 s = splhigh(); 681 /* Wait for a character to arrive. */ 682 do { 683 rr0 = zc->zc_csr; 684 ZS_DELAY(); 685 } while ((rr0 & ZSRR0_RX_READY) == 0); 686 687 c = zc->zc_data; 688 ZS_DELAY(); 689 splx(s); 690 691 return (c); 692 } 693 694 /* 695 * Polled output char. 696 */ 697 void 698 zs_putc(void *arg, int c) 699 { 700 volatile struct zschan *zc = arg; 701 int s, rr0; 702 703 s = splhigh(); 704 705 /* Wait for transmitter to become ready. */ 706 do { 707 rr0 = zc->zc_csr; 708 ZS_DELAY(); 709 } while ((rr0 & ZSRR0_TX_READY) == 0); 710 711 /* 712 * Send the next character. 713 * Now you'd think that this could be followed by a ZS_DELAY() 714 * just like all the other chip accesses, but it turns out that 715 * the `transmit-ready' interrupt isn't de-asserted until 716 * some period of time after the register write completes 717 * (more than a couple instructions). So to avoid stray 718 * interrupts we put in the 2us delay regardless of cpu model. 719 */ 720 zc->zc_data = c; 721 delay(2); 722 723 splx(s); 724 } 725 726 /*****************************************************************/ 727 728 729 730 731 /* 732 * Polled console input putchar. 733 */ 734 static int 735 zscngetc(dev_t dev) 736 { 737 return (zs_getc(zs_conschan_get)); 738 } 739 740 /* 741 * Polled console output putchar. 742 */ 743 static void 744 zscnputc(dev_t dev, int c) 745 { 746 zs_putc(zs_conschan_put, c); 747 } 748 749 int swallow_zsintrs; 750 751 static void 752 zscnpollc(dev_t dev, int on) 753 { 754 /* 755 * Need to tell zs driver to acknowledge all interrupts or we get 756 * annoying spurious interrupt messages. This is because mucking 757 * with spl() levels during polling does not prevent interrupts from 758 * being generated. 759 */ 760 761 if (on) 762 swallow_zsintrs++; 763 else 764 swallow_zsintrs--; 765 } 766 767 int 768 zs_console_flags(int promunit, int node, int channel) 769 { 770 int cookie, flags = 0; 771 u_int options; 772 char buf[255]; 773 774 /* 775 * We'll just to the OBP grovelling down here since that's 776 * the only type of firmware we support. 777 */ 778 options = OF_finddevice("/options"); 779 780 /* Default to channel 0 if there are no explicit prom args */ 781 cookie = 0; 782 783 if (node == OF_instance_to_package(OF_stdin())) { 784 if (OF_getprop(options, "input-device", 785 buf, sizeof(buf)) != -1) { 786 if (strncmp("ttyb", buf, strlen("ttyb")) == 0) 787 cookie = 1; 788 } 789 790 if (channel == cookie) 791 flags |= ZS_HWFLAG_CONSOLE_INPUT; 792 } 793 794 if (node == OF_instance_to_package(OF_stdout())) { 795 if (OF_getprop(options, "output-device", 796 buf, sizeof(buf)) != -1) { 797 if (strncmp("ttyb", buf, strlen("ttyb")) == 0) 798 cookie = 1; 799 } 800 801 if (channel == cookie) 802 flags |= ZS_HWFLAG_CONSOLE_OUTPUT; 803 } 804 805 return (flags); 806 } 807