1 /* $OpenBSD: zs.c,v 1.30 2017/12/30 20:46:59 guenther 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 struct cfattach zs_sbus_ca = { 150 sizeof(struct zsc_softc), zs_match_sbus, zs_attach_sbus 151 }; 152 153 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(parent, vcf, aux) 174 struct device *parent; 175 void *vcf; 176 void *aux; 177 { 178 struct cfdata *cf = vcf; 179 struct sbus_attach_args *sa = aux; 180 181 if (strcmp(cf->cf_driver->cd_name, sa->sa_name) != 0) 182 return (0); 183 184 return (1); 185 } 186 187 static int 188 zs_match_fhc(parent, vcf, aux) 189 struct device *parent; 190 void *vcf; 191 void *aux; 192 { 193 struct cfdata *cf = vcf; 194 struct fhc_attach_args *fa = aux; 195 196 if (strcmp(cf->cf_driver->cd_name, fa->fa_name) != 0) 197 return (0); 198 return (1); 199 } 200 201 static void 202 zs_attach_sbus(parent, self, aux) 203 struct device *parent; 204 struct device *self; 205 void *aux; 206 { 207 struct zsc_softc *zsc = (void *) self; 208 struct sbus_attach_args *sa = aux; 209 struct zsdevice *zsaddr; 210 bus_space_handle_t kvaddr; 211 212 if (sa->sa_nintr == 0) { 213 printf(" no interrupt lines\n"); 214 return; 215 } 216 217 /* Only map registers once. */ 218 if (sa->sa_npromvaddrs) { 219 /* 220 * We're converting from a 32-bit pointer to a 64-bit 221 * pointer. Since the 32-bit entity is negative, but 222 * the kernel is still mapped into the lower 4GB 223 * range, this needs to be zero-extended. 224 * 225 * XXXXX If we map the kernel and devices into the 226 * high 4GB range, this needs to be changed to 227 * sign-extend the address. 228 */ 229 zsaddr = (struct zsdevice *) 230 (unsigned long int)sa->sa_promvaddrs[0]; 231 } else { 232 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, 233 sa->sa_size, BUS_SPACE_MAP_LINEAR, 0, &kvaddr) != 0) { 234 printf("%s @ sbus: cannot map registers\n", 235 self->dv_xname); 236 return; 237 } 238 zsaddr = (struct zsdevice *) 239 bus_space_vaddr(sa->sa_bustag, kvaddr); 240 } 241 242 zsc->zsc_bustag = sa->sa_bustag; 243 zsc->zsc_dmatag = sa->sa_dmatag; 244 zsc->zsc_promunit = getpropint(sa->sa_node, "slave", -2); 245 zsc->zsc_node = sa->sa_node; 246 247 zs_attach(zsc, zsaddr, sa->sa_pri); 248 } 249 250 static void 251 zs_attach_fhc(parent, self, aux) 252 struct device *parent; 253 struct device *self; 254 void *aux; 255 { 256 struct zsc_softc *zsc = (void *) self; 257 struct fhc_attach_args *fa = aux; 258 struct zsdevice *zsaddr; 259 bus_space_handle_t kvaddr; 260 261 if (fa->fa_nreg < 1 && fa->fa_npromvaddrs < 1) { 262 printf(": no registers\n"); 263 return; 264 } 265 266 if (fa->fa_nintr < 1) { 267 printf(": no interrupts\n"); 268 return; 269 } 270 271 if (fa->fa_npromvaddrs) { 272 /* 273 * We're converting from a 32-bit pointer to a 64-bit 274 * pointer. Since the 32-bit entity is negative, but 275 * the kernel is still mapped into the lower 4GB 276 * range, this needs to be zero-extended. 277 * 278 * XXXXX If we map the kernel and devices into the 279 * high 4GB range, this needs to be changed to 280 * sign-extend the address. 281 */ 282 zsaddr = (struct zsdevice *) 283 (unsigned long int)fa->fa_promvaddrs[0]; 284 } else { 285 if (fhc_bus_map(fa->fa_bustag, fa->fa_reg[0].fbr_slot, 286 fa->fa_reg[0].fbr_offset, fa->fa_reg[0].fbr_size, 287 BUS_SPACE_MAP_LINEAR, &kvaddr) != 0) { 288 printf("%s @ fhc: cannot map registers\n", 289 self->dv_xname); 290 return; 291 } 292 zsaddr = (struct zsdevice *) 293 bus_space_vaddr(fa->fa_bustag, kvaddr); 294 } 295 296 zsc->zsc_bustag = fa->fa_bustag; 297 zsc->zsc_dmatag = NULL; 298 zsc->zsc_promunit = getpropint(fa->fa_node, "slave", -2); 299 zsc->zsc_node = fa->fa_node; 300 301 zs_attach(zsc, zsaddr, fa->fa_intr[0]); 302 } 303 304 /* 305 * Attach a found zs. 306 * 307 * USE ROM PROPERTY keyboard FOR KEYBOARD/MOUSE? 308 */ 309 static void 310 zs_attach(zsc, zsd, pri) 311 struct zsc_softc *zsc; 312 struct zsdevice *zsd; 313 int pri; 314 { 315 struct zsc_attach_args zsc_args; 316 struct zs_chanstate *cs; 317 int s, channel, softpri = PIL_TTY; 318 319 if (zsd == NULL) { 320 printf("configuration incomplete\n"); 321 return; 322 } 323 324 printf(" softpri %d\n", softpri); 325 326 /* 327 * Initialize software state for each channel. 328 */ 329 for (channel = 0; channel < 2; channel++) { 330 struct zschan *zc; 331 struct device *child; 332 333 zsc_args.type = "serial"; 334 if (getproplen(zsc->zsc_node, "keyboard") == 0) { 335 if (channel == 0) 336 zsc_args.type = "keyboard"; 337 if (channel == 1) 338 zsc_args.type = "mouse"; 339 } 340 341 zsc_args.channel = channel; 342 cs = &zsc->zsc_cs_store[channel]; 343 zsc->zsc_cs[channel] = cs; 344 345 cs->cs_channel = channel; 346 cs->cs_private = NULL; 347 cs->cs_ops = &zsops_null; 348 cs->cs_brg_clk = PCLK / 16; 349 350 zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b; 351 352 zsc_args.consdev = NULL; 353 zsc_args.hwflags = zs_console_flags(zsc->zsc_promunit, 354 zsc->zsc_node, 355 channel); 356 357 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) { 358 zsc_args.hwflags |= ZS_HWFLAG_USE_CONSDEV; 359 zsc_args.consdev = &zs_consdev; 360 } 361 362 if (getproplen(zsc->zsc_node, channel == 0 ? 363 "port-a-ignore-cd" : "port-b-ignore-cd") == 0) { 364 zsc_args.hwflags |= ZS_HWFLAG_NO_DCD; 365 } 366 367 if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) { 368 zs_conschan_get = zc; 369 } 370 if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) { 371 zs_conschan_put = zc; 372 } 373 /* Childs need to set cn_dev, etc */ 374 375 cs->cs_reg_csr = &zc->zc_csr; 376 cs->cs_reg_data = &zc->zc_data; 377 378 bcopy(zs_init_reg, cs->cs_creg, 16); 379 bcopy(zs_init_reg, cs->cs_preg, 16); 380 381 /* XXX: Consult PROM properties for this?! */ 382 cs->cs_defspeed = zs_get_speed(cs); 383 cs->cs_defcflag = zs_def_cflag; 384 385 /* Make these correspond to cs_defcflag (-crtscts) */ 386 cs->cs_rr0_dcd = ZSRR0_DCD; 387 cs->cs_rr0_cts = 0; 388 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 389 cs->cs_wr5_rts = 0; 390 391 /* 392 * Clear the master interrupt enable. 393 * The INTENA is common to both channels, 394 * so just do it on the A channel. 395 */ 396 if (channel == 0) { 397 zs_write_reg(cs, 9, 0); 398 } 399 400 /* 401 * Look for a child driver for this channel. 402 * The child attach will setup the hardware. 403 */ 404 if (!(child = 405 config_found(&zsc->zsc_dev, (void *)&zsc_args, zs_print))) { 406 /* No sub-driver. Just reset it. */ 407 u_char reset = (channel == 0) ? 408 ZSWR9_A_RESET : ZSWR9_B_RESET; 409 s = splzs(); 410 zs_write_reg(cs, 9, reset); 411 splx(s); 412 } 413 } 414 415 /* 416 * Now safe to install interrupt handlers. 417 */ 418 if (bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, 0, zshard, 419 zsc, zsc->zsc_dev.dv_xname) == NULL) 420 panic("zsattach: could not establish interrupt"); 421 if (!(zsc->zsc_softintr = softintr_establish(softpri, zssoft, zsc))) 422 panic("zsattach: could not establish soft interrupt"); 423 424 /* 425 * Set the master interrupt enable and interrupt vector. 426 * (common to both channels, do it on A) 427 */ 428 cs = zsc->zsc_cs[0]; 429 s = splhigh(); 430 /* interrupt vector */ 431 zs_write_reg(cs, 2, zs_init_reg[2]); 432 /* master interrupt control (enable) */ 433 zs_write_reg(cs, 9, zs_init_reg[9]); 434 splx(s); 435 436 } 437 438 static int 439 zs_print(aux, name) 440 void *aux; 441 const char *name; 442 { 443 struct zsc_attach_args *args = aux; 444 445 if (name != NULL) 446 printf("%s: ", name); 447 448 if (args->channel != -1) 449 printf(" channel %d", args->channel); 450 451 return (UNCONF); 452 } 453 454 static int 455 zshard(arg) 456 void *arg; 457 { 458 struct zsc_softc *zsc = (struct zsc_softc *)arg; 459 int rval = 0; 460 461 while (zsc_intr_hard(zsc)) 462 rval = 1; 463 if ((zsc->zsc_cs[0] && zsc->zsc_cs[0]->cs_softreq) || 464 (zsc->zsc_cs[1] && zsc->zsc_cs[1]->cs_softreq)) 465 softintr_schedule(zsc->zsc_softintr); 466 return (rval); 467 } 468 469 /* 470 * We need this only for TTY_DEBUG purposes. 471 */ 472 static void 473 zssoft(arg) 474 void *arg; 475 { 476 struct zsc_softc *zsc = (struct zsc_softc *)arg; 477 int s; 478 479 /* Make sure we call the tty layer at spltty. */ 480 s = spltty(); 481 (void)zsc_intr_soft(zsc); 482 #ifdef TTY_DEBUG 483 { 484 struct zstty_softc *zst0 = zsc->zsc_cs[0]->cs_private; 485 struct zstty_softc *zst1 = zsc->zsc_cs[1]->cs_private; 486 if (zst0->zst_overflows || zst1->zst_overflows ) { 487 struct trapframe *frame = (struct trapframe *)arg; 488 489 printf("zs silo overflow from %p\n", 490 (long)frame->tf_pc); 491 } 492 } 493 #endif 494 splx(s); 495 } 496 497 498 /* 499 * Compute the current baud rate given a ZS channel. 500 */ 501 static int 502 zs_get_speed(cs) 503 struct zs_chanstate *cs; 504 { 505 int tconst; 506 507 tconst = zs_read_reg(cs, 12); 508 tconst |= zs_read_reg(cs, 13) << 8; 509 return (TCONST_TO_BPS(cs->cs_brg_clk, tconst)); 510 } 511 512 /* 513 * MD functions for setting the baud rate and control modes. 514 */ 515 int 516 zs_set_speed(cs, bps) 517 struct zs_chanstate *cs; 518 int bps; /* bits per second */ 519 { 520 int tconst, real_bps; 521 522 if (bps == 0) 523 return (0); 524 525 #ifdef DIAGNOSTIC 526 if (cs->cs_brg_clk == 0) 527 panic("zs_set_speed"); 528 #endif 529 530 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 531 if (tconst < 0) 532 return (EINVAL); 533 534 /* Convert back to make sure we can do it. */ 535 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 536 537 /* XXX - Allow some tolerance here? */ 538 if (real_bps != bps) 539 return (EINVAL); 540 541 cs->cs_preg[12] = tconst; 542 cs->cs_preg[13] = tconst >> 8; 543 544 /* Caller will stuff the pending registers. */ 545 return (0); 546 } 547 548 int 549 zs_set_modes(cs, cflag) 550 struct zs_chanstate *cs; 551 int cflag; 552 { 553 int s; 554 555 /* 556 * Output hardware flow control on the chip is horrendous: 557 * if carrier detect drops, the receiver is disabled, and if 558 * CTS drops, the transmitter is stopped IN MID CHARACTER! 559 * Therefore, NEVER set the HFC bit, and instead use the 560 * status interrupt to detect CTS changes. 561 */ 562 s = splzs(); 563 cs->cs_rr0_pps = 0; 564 if ((cflag & (CLOCAL | MDMBUF)) != 0) { 565 cs->cs_rr0_dcd = 0; 566 if ((cflag & MDMBUF) == 0) 567 cs->cs_rr0_pps = ZSRR0_DCD; 568 } else 569 cs->cs_rr0_dcd = ZSRR0_DCD; 570 if ((cflag & CRTSCTS) != 0) { 571 cs->cs_wr5_dtr = ZSWR5_DTR; 572 cs->cs_wr5_rts = ZSWR5_RTS; 573 cs->cs_rr0_cts = ZSRR0_CTS; 574 #if 0 /* JLW */ 575 } else if ((cflag & CDTRCTS) != 0) { 576 cs->cs_wr5_dtr = 0; 577 cs->cs_wr5_rts = ZSWR5_DTR; 578 cs->cs_rr0_cts = ZSRR0_CTS; 579 #endif 580 } else if ((cflag & MDMBUF) != 0) { 581 cs->cs_wr5_dtr = 0; 582 cs->cs_wr5_rts = ZSWR5_DTR; 583 cs->cs_rr0_cts = ZSRR0_DCD; 584 } else { 585 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 586 cs->cs_wr5_rts = 0; 587 cs->cs_rr0_cts = 0; 588 } 589 splx(s); 590 591 /* Caller will stuff the pending registers. */ 592 return (0); 593 } 594 595 596 /* 597 * Read or write the chip with suitable delays. 598 */ 599 600 u_char 601 zs_read_reg(cs, reg) 602 struct zs_chanstate *cs; 603 u_char reg; 604 { 605 u_char val; 606 607 *cs->cs_reg_csr = reg; 608 ZS_DELAY(); 609 val = *cs->cs_reg_csr; 610 ZS_DELAY(); 611 return (val); 612 } 613 614 void 615 zs_write_reg(cs, reg, val) 616 struct zs_chanstate *cs; 617 u_char reg, val; 618 { 619 *cs->cs_reg_csr = reg; 620 ZS_DELAY(); 621 *cs->cs_reg_csr = val; 622 ZS_DELAY(); 623 } 624 625 u_char 626 zs_read_csr(cs) 627 struct zs_chanstate *cs; 628 { 629 u_char val; 630 631 val = *cs->cs_reg_csr; 632 ZS_DELAY(); 633 return (val); 634 } 635 636 void 637 zs_write_csr(cs, val) 638 struct zs_chanstate *cs; 639 u_char val; 640 { 641 *cs->cs_reg_csr = val; 642 ZS_DELAY(); 643 } 644 645 u_char 646 zs_read_data(cs) 647 struct zs_chanstate *cs; 648 { 649 u_char val; 650 651 val = *cs->cs_reg_data; 652 ZS_DELAY(); 653 return (val); 654 } 655 656 void 657 zs_write_data(cs, val) 658 struct zs_chanstate *cs; 659 u_char val; 660 { 661 *cs->cs_reg_data = val; 662 ZS_DELAY(); 663 } 664 665 /**************************************************************** 666 * Console support functions (Sun specific!) 667 * Note: this code is allowed to know about the layout of 668 * the chip registers, and uses that to keep things simple. 669 * XXX - I think I like the mvme167 code better. -gwr 670 ****************************************************************/ 671 672 /* 673 * Handle user request to enter kernel debugger. 674 */ 675 void 676 zs_abort(cs) 677 struct zs_chanstate *cs; 678 { 679 volatile struct zschan *zc = zs_conschan_get; 680 int rr0; 681 682 /* Wait for end of break to avoid PROM abort. */ 683 /* XXX - Limit the wait? */ 684 do { 685 rr0 = zc->zc_csr; 686 ZS_DELAY(); 687 } while (rr0 & ZSRR0_BREAK); 688 689 #if defined(DDB) 690 { 691 extern int db_active; 692 693 if (!db_active) 694 db_enter(); 695 else 696 /* Debugger is probably hozed */ 697 callrom(); 698 } 699 #else 700 printf("stopping on keyboard abort\n"); 701 callrom(); 702 #endif 703 } 704 705 706 /* 707 * Polled input char. 708 */ 709 int 710 zs_getc(arg) 711 void *arg; 712 { 713 volatile struct zschan *zc = arg; 714 int s, c, rr0; 715 716 s = splhigh(); 717 /* Wait for a character to arrive. */ 718 do { 719 rr0 = zc->zc_csr; 720 ZS_DELAY(); 721 } while ((rr0 & ZSRR0_RX_READY) == 0); 722 723 c = zc->zc_data; 724 ZS_DELAY(); 725 splx(s); 726 727 return (c); 728 } 729 730 /* 731 * Polled output char. 732 */ 733 void 734 zs_putc(arg, c) 735 void *arg; 736 int c; 737 { 738 volatile struct zschan *zc = arg; 739 int s, rr0; 740 741 s = splhigh(); 742 743 /* Wait for transmitter to become ready. */ 744 do { 745 rr0 = zc->zc_csr; 746 ZS_DELAY(); 747 } while ((rr0 & ZSRR0_TX_READY) == 0); 748 749 /* 750 * Send the next character. 751 * Now you'd think that this could be followed by a ZS_DELAY() 752 * just like all the other chip accesses, but it turns out that 753 * the `transmit-ready' interrupt isn't de-asserted until 754 * some period of time after the register write completes 755 * (more than a couple instructions). So to avoid stray 756 * interrupts we put in the 2us delay regardless of cpu model. 757 */ 758 zc->zc_data = c; 759 delay(2); 760 761 splx(s); 762 } 763 764 /*****************************************************************/ 765 766 767 768 769 /* 770 * Polled console input putchar. 771 */ 772 static int 773 zscngetc(dev) 774 dev_t dev; 775 { 776 return (zs_getc(zs_conschan_get)); 777 } 778 779 /* 780 * Polled console output putchar. 781 */ 782 static void 783 zscnputc(dev, c) 784 dev_t dev; 785 int c; 786 { 787 zs_putc(zs_conschan_put, c); 788 } 789 790 int swallow_zsintrs; 791 792 static void 793 zscnpollc(dev, on) 794 dev_t dev; 795 int on; 796 { 797 /* 798 * Need to tell zs driver to acknowledge all interrupts or we get 799 * annoying spurious interrupt messages. This is because mucking 800 * with spl() levels during polling does not prevent interrupts from 801 * being generated. 802 */ 803 804 if (on) 805 swallow_zsintrs++; 806 else 807 swallow_zsintrs--; 808 } 809 810 int 811 zs_console_flags(promunit, node, channel) 812 int promunit; 813 int node; 814 int channel; 815 { 816 int cookie, flags = 0; 817 u_int options; 818 char buf[255]; 819 820 /* 821 * We'll just to the OBP grovelling down here since that's 822 * the only type of firmware we support. 823 */ 824 options = OF_finddevice("/options"); 825 826 /* Default to channel 0 if there are no explicit prom args */ 827 cookie = 0; 828 829 if (node == OF_instance_to_package(OF_stdin())) { 830 if (OF_getprop(options, "input-device", 831 buf, sizeof(buf)) != -1) { 832 if (strncmp("ttyb", buf, strlen("ttyb")) == 0) 833 cookie = 1; 834 } 835 836 if (channel == cookie) 837 flags |= ZS_HWFLAG_CONSOLE_INPUT; 838 } 839 840 if (node == OF_instance_to_package(OF_stdout())) { 841 if (OF_getprop(options, "output-device", 842 buf, sizeof(buf)) != -1) { 843 if (strncmp("ttyb", buf, strlen("ttyb")) == 0) 844 cookie = 1; 845 } 846 847 if (channel == cookie) 848 flags |= ZS_HWFLAG_CONSOLE_OUTPUT; 849 } 850 851 return (flags); 852 } 853