1 /* $OpenBSD: z8530kbd.c,v 1.27 2015/10/28 05:11:55 jsg Exp $ */ 2 /* $NetBSD: z8530tty.c,v 1.77 2001/05/30 15:24:24 lukem Exp $ */ 3 4 /*- 5 * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999 6 * Charles M. Hannum. 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 Charles M. Hannum. 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 WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1994 Gordon W. Ross 36 * Copyright (c) 1992, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * This software was developed by the Computer Systems Engineering group 40 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 41 * contributed to Berkeley. 42 * 43 * All advertising materials mentioning features or use of this software 44 * must display the following acknowledgement: 45 * This product includes software developed by the University of 46 * California, Lawrence Berkeley Laboratory. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)zs.c 8.1 (Berkeley) 7/19/93 73 */ 74 75 /* 76 * Zilog Z8530 Dual UART driver (tty interface) 77 * 78 * This is the "slave" driver that will be attached to 79 * the "zsc" driver for plain "tty" async. serial lines. 80 * 81 * Credits, history: 82 * 83 * The original version of this code was the sparc/dev/zs.c driver 84 * as distributed with the Berkeley 4.4 Lite release. Since then, 85 * Gordon Ross reorganized the code into the current parent/child 86 * driver scheme, separating the Sun keyboard and mouse support 87 * into independent child drivers. 88 * 89 * RTS/CTS flow-control support was a collaboration of: 90 * Gordon Ross <gwr@netbsd.org>, 91 * Bill Studenmund <wrstuden@loki.stanford.edu> 92 * Ian Dall <Ian.Dall@dsto.defence.gov.au> 93 * 94 * The driver was massively overhauled in November 1997 by Charles Hannum, 95 * fixing *many* bugs, and substantially improving performance. 96 */ 97 98 #include <sys/param.h> 99 #include <sys/systm.h> 100 #include <sys/proc.h> 101 #include <sys/device.h> 102 #include <sys/conf.h> 103 #include <sys/file.h> 104 #include <sys/ioctl.h> 105 #include <sys/malloc.h> 106 #include <sys/tty.h> 107 #include <sys/time.h> 108 #include <sys/kernel.h> 109 #include <sys/syslog.h> 110 111 #include <machine/autoconf.h> 112 113 #include <dev/wscons/wsconsio.h> 114 #include <dev/wscons/wskbdvar.h> 115 116 #include <dev/sun/sunkbdreg.h> 117 #include <dev/sun/sunkbdvar.h> 118 119 #include <dev/ic/z8530reg.h> 120 #include <machine/z8530var.h> 121 122 #include <dev/cons.h> 123 124 /* 125 * How many input characters we can buffer. 126 * The port-specific var.h may override this. 127 * Note: must be a power of two! 128 */ 129 #ifndef ZSKBD_RING_SIZE 130 #define ZSKBD_RING_SIZE 2048 131 #endif 132 133 struct cfdriver zskbd_cd = { 134 NULL, "zskbd", DV_TTY 135 }; 136 137 /* 138 * Make this an option variable one can patch. 139 * But be warned: this must be a power of 2! 140 */ 141 u_int zskbd_rbuf_size = ZSKBD_RING_SIZE; 142 143 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 144 u_int zskbd_rbuf_hiwat = (ZSKBD_RING_SIZE * 1) / 4; 145 u_int zskbd_rbuf_lowat = (ZSKBD_RING_SIZE * 3) / 4; 146 147 struct zskbd_softc { 148 struct sunkbd_softc sc_base; 149 150 struct zs_chanstate *zst_cs; 151 152 struct timeout zst_diag_ch; 153 154 u_int zst_overflows, 155 zst_floods, 156 zst_errors; 157 158 int zst_hwflags, /* see z8530var.h */ 159 zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */ 160 161 u_int zst_r_hiwat, 162 zst_r_lowat; 163 u_char *volatile zst_rbget, 164 *volatile zst_rbput; 165 volatile u_int zst_rbavail; 166 u_char *zst_rbuf, 167 *zst_ebuf; 168 169 /* 170 * The transmit byte count and address are used for pseudo-DMA 171 * output in the hardware interrupt code. PDMA can be suspended 172 * to get pending changes done; heldtbc is used for this. It can 173 * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state. 174 */ 175 u_char *zst_tba; /* transmit buffer address */ 176 u_int zst_tbc, /* transmit byte count */ 177 zst_heldtbc; /* held tbc while xmission stopped */ 178 179 u_char zst_tbuf[ZSKBD_RING_SIZE]; 180 u_char *zst_tbeg, *zst_tend, *zst_tbp; 181 182 /* Flags to communicate with zskbd_softint() */ 183 volatile u_char zst_rx_flags, /* receiver blocked */ 184 #define RX_TTY_BLOCKED 0x01 185 #define RX_TTY_OVERFLOWED 0x02 186 #define RX_IBUF_BLOCKED 0x04 187 #define RX_IBUF_OVERFLOWED 0x08 188 #define RX_ANY_BLOCK 0x0f 189 zst_tx_busy, /* working on an output chunk */ 190 zst_tx_done, /* done with one output chunk */ 191 zst_tx_stopped, /* H/W level stop (lost CTS) */ 192 zst_st_check, /* got a status interrupt */ 193 zst_rx_ready; 194 195 /* PPS signal on DCD, with or without inkernel clock disciplining */ 196 u_char zst_ppsmask; /* pps signal mask */ 197 u_char zst_ppsassert; /* pps leading edge */ 198 u_char zst_ppsclear; /* pps trailing edge */ 199 }; 200 201 /* Definition of the driver for autoconfig. */ 202 static int zskbd_match(struct device *, void *, void *); 203 static void zskbd_attach(struct device *, struct device *, void *); 204 205 struct cfattach zskbd_ca = { 206 sizeof(struct zskbd_softc), zskbd_match, zskbd_attach 207 }; 208 209 struct zsops zsops_kbd; 210 211 static void zs_modem(struct zskbd_softc *, int); 212 static void zs_hwiflow(struct zskbd_softc *); 213 static void zs_maskintr(struct zskbd_softc *); 214 215 /* Low-level routines. */ 216 static void zskbd_rxint(struct zs_chanstate *); 217 static void zskbd_stint(struct zs_chanstate *, int); 218 static void zskbd_txint(struct zs_chanstate *); 219 static void zskbd_softint(struct zs_chanstate *); 220 static void zskbd_diag(void *); 221 222 int zskbd_init(struct zskbd_softc *); 223 void zskbd_putc(struct zskbd_softc *, u_int8_t); 224 void zskbd_raw(struct zskbd_softc *, u_int8_t); 225 226 /* wskbd glue */ 227 void zskbd_cngetc(void *, u_int *, int *); 228 void zskbd_cnpollc(void *, int); 229 230 void zsstart_tx(struct zskbd_softc *); 231 int zsenqueue_tx(void *, u_int8_t *, u_int); 232 233 struct wskbd_consops zskbd_consops = { 234 zskbd_cngetc, 235 zskbd_cnpollc 236 }; 237 238 #define ZSKBDUNIT(x) (minor(x) & 0x7ffff) 239 240 /* 241 * zskbd_match: how is this zs channel configured? 242 */ 243 int 244 zskbd_match(parent, vcf, aux) 245 struct device *parent; 246 void *vcf; 247 void *aux; 248 { 249 struct cfdata *cf = vcf; 250 struct zsc_attach_args *args = aux; 251 int ret; 252 253 /* If we're not looking for a keyboard, just exit */ 254 if (strcmp(args->type, "keyboard") != 0) 255 return (0); 256 257 ret = 10; 258 259 /* Exact match is better than wildcard. */ 260 if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel) 261 ret += 2; 262 263 /* This driver accepts wildcard. */ 264 if (cf->cf_loc[ZSCCF_CHANNEL] == ZSCCF_CHANNEL_DEFAULT) 265 ret += 1; 266 267 return (ret); 268 } 269 270 void 271 zskbd_attach(parent, self, aux) 272 struct device *parent, *self; 273 void *aux; 274 275 { 276 struct zsc_softc *zsc = (void *)parent; 277 struct zskbd_softc *zst = (void *)self; 278 struct sunkbd_softc *ss = (void *)self; 279 struct cfdata *cf = self->dv_cfdata; 280 struct zsc_attach_args *args = aux; 281 struct wskbddev_attach_args a; 282 struct zs_chanstate *cs; 283 int channel, s, tty_unit, console = 0; 284 dev_t dev; 285 286 ss->sc_sendcmd = zsenqueue_tx; 287 timeout_set(&ss->sc_bellto, sunkbd_bellstop, zst); 288 289 timeout_set(&zst->zst_diag_ch, zskbd_diag, zst); 290 291 zst->zst_tbp = zst->zst_tba = zst->zst_tbeg = zst->zst_tbuf; 292 zst->zst_tend = zst->zst_tbeg + ZSKBD_RING_SIZE; 293 294 tty_unit = ss->sc_dev.dv_unit; 295 channel = args->channel; 296 cs = zsc->zsc_cs[channel]; 297 cs->cs_private = zst; 298 cs->cs_ops = &zsops_kbd; 299 300 zst->zst_cs = cs; 301 zst->zst_swflags = cf->cf_flags; /* softcar, etc. */ 302 zst->zst_hwflags = args->hwflags; 303 dev = makedev(zs_major, tty_unit); 304 305 if (zst->zst_swflags) 306 printf(" flags 0x%x", zst->zst_swflags); 307 308 /* 309 * Check whether we serve as a console device. 310 * XXX - split console input/output channels aren't 311 * supported yet on /dev/console 312 */ 313 if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) { 314 if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) { 315 args->consdev->cn_dev = dev; 316 cn_tab->cn_pollc = wskbd_cnpollc; 317 cn_tab->cn_getc = wskbd_cngetc; 318 } 319 cn_tab->cn_dev = dev; 320 console = 1; 321 } 322 323 zst->zst_rbuf = malloc(zskbd_rbuf_size << 1, M_DEVBUF, M_WAITOK); 324 zst->zst_ebuf = zst->zst_rbuf + (zskbd_rbuf_size << 1); 325 /* Disable the high water mark. */ 326 zst->zst_r_hiwat = 0; 327 zst->zst_r_lowat = 0; 328 zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf; 329 zst->zst_rbavail = zskbd_rbuf_size; 330 331 /* if there are no enable/disable functions, assume the device 332 is always enabled */ 333 if (!cs->enable) 334 cs->enabled = 1; 335 336 /* 337 * Hardware init 338 */ 339 if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { 340 /* Call zsparam similar to open. */ 341 342 /* Wait a while for previous console output to complete */ 343 DELAY(10000); 344 } else if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_NORESET)) { 345 /* Not the console; may need reset. */ 346 int reset; 347 348 reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; 349 s = splzs(); 350 zs_write_reg(cs, 9, reset); 351 splx(s); 352 } 353 354 /* 355 * Probe for a keyboard. 356 * If one is found, turn on receiver and status interrupts. 357 * We defer the actual write of the register to zsparam(), 358 * but we must make sure status interrupts are turned on by 359 * the time zsparam() reads the initial rr0 state. 360 */ 361 if (zskbd_init(zst)) { 362 SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_SIE); 363 zs_write_reg(cs, 1, cs->cs_creg[1]); 364 365 /* Make sure DTR is on now. */ 366 s = splzs(); 367 zs_modem(zst, 1); 368 splx(s); 369 } else { 370 /* Will raise DTR in open. */ 371 s = splzs(); 372 zs_modem(zst, 0); 373 splx(s); 374 375 return; 376 } 377 378 ss->sc_click = 379 strcmp(getpropstring(optionsnode, "keyboard-click?"), "true") == 0; 380 sunkbd_setclick(ss, ss->sc_click); 381 382 a.console = console; 383 if (ISTYPE5(ss->sc_layout)) { 384 a.keymap = &sunkbd5_keymapdata; 385 #ifndef SUNKBD5_LAYOUT 386 if (ss->sc_layout < MAXSUNLAYOUT && 387 sunkbd_layouts[ss->sc_layout] != -1) 388 sunkbd5_keymapdata.layout = 389 sunkbd_layouts[ss->sc_layout]; 390 #endif 391 } else { 392 a.keymap = &sunkbd_keymapdata; 393 #ifndef SUNKBD_LAYOUT 394 if (ss->sc_layout < MAXSUNLAYOUT && 395 sunkbd_layouts[ss->sc_layout] != -1) 396 sunkbd_keymapdata.layout = 397 sunkbd_layouts[ss->sc_layout]; 398 #endif 399 } 400 a.accessops = &sunkbd_accessops; 401 a.accesscookie = zst; 402 403 if (console) 404 wskbd_cnattach(&zskbd_consops, zst, a.keymap); 405 406 sunkbd_attach(ss, &a); 407 } 408 409 int 410 zskbd_init(zst) 411 struct zskbd_softc *zst; 412 { 413 struct sunkbd_softc *ss = (void *)zst; 414 struct zs_chanstate *cs = zst->zst_cs; 415 int s, tries; 416 u_int8_t v3, v4, v5, rr0; 417 418 /* setup for 1200n81 */ 419 if (zs_set_speed(cs, 1200)) { /* set 1200bps */ 420 printf(": failed to set baudrate\n"); 421 return 0; 422 } 423 if (zs_set_modes(cs, CS8 | CLOCAL)) { 424 printf(": failed to set modes\n"); 425 return 0; 426 } 427 428 s = splzs(); 429 430 zs_maskintr(zst); 431 432 v3 = cs->cs_preg[3]; /* set 8 bit chars */ 433 v5 = cs->cs_preg[5]; 434 CLR(v3, ZSWR3_RXSIZE); 435 CLR(v5, ZSWR5_TXSIZE); 436 SET(v3, ZSWR3_RX_8); 437 SET(v5, ZSWR5_TX_8); 438 cs->cs_preg[3] = v3; 439 cs->cs_preg[5] = v5; 440 441 v4 = cs->cs_preg[4]; /* no parity 1 stop */ 442 CLR(v4, ZSWR4_SBMASK | ZSWR4_PARMASK); 443 SET(v4, ZSWR4_ONESB | ZSWR4_EVENP); 444 cs->cs_preg[4] = v4; 445 446 if (!cs->cs_heldchange) { 447 if (zst->zst_tx_busy) { 448 zst->zst_heldtbc = zst->zst_tbc; 449 zst->zst_tbc = 0; 450 cs->cs_heldchange = 1; 451 } else 452 zs_loadchannelregs(cs); 453 } 454 455 /* 456 * Hardware flow control is disabled, turn off the buffer water 457 * marks and unblock any soft flow control state. Otherwise, enable 458 * the water marks. 459 */ 460 zst->zst_r_hiwat = 0; 461 zst->zst_r_lowat = 0; 462 if (ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { 463 CLR(zst->zst_rx_flags, RX_TTY_OVERFLOWED); 464 zst->zst_rx_ready = 1; 465 cs->cs_softreq = 1; 466 } 467 if (ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 468 CLR(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 469 zs_hwiflow(zst); 470 } 471 472 /* 473 * Force a recheck of the hardware carrier and flow control status, 474 * since we may have changed which bits we're looking at. 475 */ 476 zskbd_stint(cs, 1); 477 478 splx(s); 479 480 /* 481 * Hardware flow control is disabled, unblock any hard flow control 482 * state. 483 */ 484 if (zst->zst_tx_stopped) { 485 zst->zst_tx_stopped = 0; 486 zsstart_tx(zst); 487 } 488 489 zskbd_softint(cs); 490 491 /* Ok, start the reset sequence... */ 492 493 s = splhigh(); 494 495 for (tries = 5; tries != 0; tries--) { 496 int ltries; 497 498 ss->sc_leds = 0; 499 ss->sc_layout = -1; 500 501 /* Send reset request */ 502 zskbd_putc(zst, SKBD_CMD_RESET); 503 504 ltries = 1000; 505 while (--ltries > 0) { 506 rr0 = *cs->cs_reg_csr; 507 if (rr0 & ZSRR0_RX_READY) { 508 sunkbd_raw(ss, *cs->cs_reg_data); 509 if (ss->sc_kbdstate == SKBD_STATE_RESET) 510 break; 511 } 512 DELAY(1000); 513 } 514 if (ltries == 0) 515 continue; 516 517 /* Wait for reset to finish. */ 518 ltries = 1000; 519 while (--ltries > 0) { 520 rr0 = *cs->cs_reg_csr; 521 if (rr0 & ZSRR0_RX_READY) { 522 sunkbd_raw(ss, *cs->cs_reg_data); 523 if (ss->sc_kbdstate == SKBD_STATE_GETKEY) 524 break; 525 } 526 DELAY(1000); 527 } 528 if (ltries == 0) 529 continue; 530 531 /* Some Sun<=>PS/2 converters need some delay here */ 532 DELAY(5000); 533 534 /* Send layout request */ 535 zskbd_putc(zst, SKBD_CMD_LAYOUT); 536 537 ltries = 1000; 538 while (--ltries > 0) { 539 rr0 = *cs->cs_reg_csr; 540 if (rr0 & ZSRR0_RX_READY) { 541 sunkbd_raw(ss, *cs->cs_reg_data); 542 if (ss->sc_layout != -1) 543 break; 544 } 545 DELAY(1000); 546 } 547 if (ltries == 0) 548 continue; 549 break; 550 } 551 if (tries == 0) 552 printf(": no keyboard\n"); 553 else 554 printf(": layout %d\n", ss->sc_layout); 555 splx(s); 556 557 return tries; 558 } 559 560 void 561 zskbd_putc(zst, c) 562 struct zskbd_softc *zst; 563 u_int8_t c; 564 { 565 u_int8_t rr0; 566 int s; 567 568 s = splhigh(); 569 do { 570 rr0 = *zst->zst_cs->cs_reg_csr; 571 } while ((rr0 & ZSRR0_TX_READY) == 0); 572 *zst->zst_cs->cs_reg_data = c; 573 delay(2); 574 splx(s); 575 } 576 577 int 578 zsenqueue_tx(v, str, len) 579 void *v; 580 u_int8_t *str; 581 u_int len; 582 { 583 struct zskbd_softc *zst = v; 584 int s; 585 u_int i; 586 587 s = splzs(); 588 if (zst->zst_tbc + len > ZSKBD_RING_SIZE) { 589 splx(s); 590 return (-1); 591 } 592 zst->zst_tbc += len; 593 for (i = 0; i < len; i++) { 594 *zst->zst_tbp = str[i]; 595 if (++zst->zst_tbp == zst->zst_tend) 596 zst->zst_tbp = zst->zst_tbeg; 597 } 598 splx(s); 599 zsstart_tx(zst); 600 return (0); 601 } 602 603 void 604 zsstart_tx(zst) 605 struct zskbd_softc *zst; 606 { 607 struct zs_chanstate *cs = zst->zst_cs; 608 int s, s1; 609 610 s = spltty(); 611 612 if (zst->zst_tx_stopped) 613 goto out; 614 if (zst->zst_tbc == 0) 615 goto out; 616 617 s1 = splzs(); 618 619 zst->zst_tx_busy = 1; 620 621 if (!ISSET(cs->cs_preg[1], ZSWR1_TIE)) { 622 SET(cs->cs_preg[1], ZSWR1_TIE); 623 cs->cs_creg[1] = cs->cs_preg[1]; 624 zs_write_reg(cs, 1, cs->cs_creg[1]); 625 } 626 627 zs_write_data(cs, *zst->zst_tba); 628 629 zst->zst_tbc--; 630 if (++zst->zst_tba == zst->zst_tend) 631 zst->zst_tba = zst->zst_tbeg; 632 633 splx(s1); 634 635 out: 636 splx(s); 637 } 638 639 /* 640 * Compute interrupt enable bits and set in the pending bits. Called both 641 * in zsparam() and when PPS (pulse per second timing) state changes. 642 * Must be called at splzs(). 643 */ 644 static void 645 zs_maskintr(zst) 646 struct zskbd_softc *zst; 647 { 648 struct zs_chanstate *cs = zst->zst_cs; 649 int tmp15; 650 651 cs->cs_rr0_mask = cs->cs_rr0_cts | cs->cs_rr0_dcd; 652 if (zst->zst_ppsmask != 0) 653 cs->cs_rr0_mask |= cs->cs_rr0_pps; 654 tmp15 = cs->cs_preg[15]; 655 if (ISSET(cs->cs_rr0_mask, ZSRR0_DCD)) 656 SET(tmp15, ZSWR15_DCD_IE); 657 else 658 CLR(tmp15, ZSWR15_DCD_IE); 659 if (ISSET(cs->cs_rr0_mask, ZSRR0_CTS)) 660 SET(tmp15, ZSWR15_CTS_IE); 661 else 662 CLR(tmp15, ZSWR15_CTS_IE); 663 cs->cs_preg[15] = tmp15; 664 } 665 666 667 /* 668 * Raise or lower modem control (DTR/RTS) signals. If a character is 669 * in transmission, the change is deferred. 670 */ 671 static void 672 zs_modem(zst, onoff) 673 struct zskbd_softc *zst; 674 int onoff; 675 { 676 struct zs_chanstate *cs = zst->zst_cs; 677 678 if (cs->cs_wr5_dtr == 0) 679 return; 680 681 if (onoff) 682 SET(cs->cs_preg[5], cs->cs_wr5_dtr); 683 else 684 CLR(cs->cs_preg[5], cs->cs_wr5_dtr); 685 686 if (!cs->cs_heldchange) { 687 if (zst->zst_tx_busy) { 688 zst->zst_heldtbc = zst->zst_tbc; 689 zst->zst_tbc = 0; 690 cs->cs_heldchange = 1; 691 } else 692 zs_loadchannelregs(cs); 693 } 694 } 695 696 /* 697 * Internal version of zshwiflow 698 * called at splzs 699 */ 700 static void 701 zs_hwiflow(zst) 702 struct zskbd_softc *zst; 703 { 704 struct zs_chanstate *cs = zst->zst_cs; 705 706 if (cs->cs_wr5_rts == 0) 707 return; 708 709 if (ISSET(zst->zst_rx_flags, RX_ANY_BLOCK)) { 710 CLR(cs->cs_preg[5], cs->cs_wr5_rts); 711 CLR(cs->cs_creg[5], cs->cs_wr5_rts); 712 } else { 713 SET(cs->cs_preg[5], cs->cs_wr5_rts); 714 SET(cs->cs_creg[5], cs->cs_wr5_rts); 715 } 716 zs_write_reg(cs, 5, cs->cs_creg[5]); 717 } 718 719 720 /**************************************************************** 721 * Interface to the lower layer (zscc) 722 ****************************************************************/ 723 724 #define integrate 725 integrate void zskbd_rxsoft(struct zskbd_softc *); 726 integrate void zskbd_txsoft(struct zskbd_softc *); 727 integrate void zskbd_stsoft(struct zskbd_softc *); 728 /* 729 * receiver ready interrupt. 730 * called at splzs 731 */ 732 static void 733 zskbd_rxint(cs) 734 struct zs_chanstate *cs; 735 { 736 struct zskbd_softc *zst = cs->cs_private; 737 u_char *put, *end; 738 u_int cc; 739 u_char rr0, rr1, c; 740 741 end = zst->zst_ebuf; 742 put = zst->zst_rbput; 743 cc = zst->zst_rbavail; 744 745 while (cc > 0) { 746 /* 747 * First read the status, because reading the received char 748 * destroys the status of this char. 749 */ 750 rr1 = zs_read_reg(cs, 1); 751 c = zs_read_data(cs); 752 753 if (ISSET(rr1, ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 754 /* Clear the receive error. */ 755 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 756 } 757 758 put[0] = c; 759 put[1] = rr1; 760 put += 2; 761 if (put >= end) 762 put = zst->zst_rbuf; 763 cc--; 764 765 rr0 = zs_read_csr(cs); 766 if (!ISSET(rr0, ZSRR0_RX_READY)) 767 break; 768 } 769 770 /* 771 * Current string of incoming characters ended because 772 * no more data was available or we ran out of space. 773 * Schedule a receive event if any data was received. 774 * If we're out of space, turn off receive interrupts. 775 */ 776 zst->zst_rbput = put; 777 zst->zst_rbavail = cc; 778 if (!ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { 779 zst->zst_rx_ready = 1; 780 cs->cs_softreq = 1; 781 } 782 783 /* 784 * See if we are in danger of overflowing a buffer. If 785 * so, use hardware flow control to ease the pressure. 786 */ 787 if (!ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED) && 788 cc < zst->zst_r_hiwat) { 789 SET(zst->zst_rx_flags, RX_IBUF_BLOCKED); 790 zs_hwiflow(zst); 791 } 792 793 /* 794 * If we're out of space, disable receive interrupts 795 * until the queue has drained a bit. 796 */ 797 if (!cc) { 798 SET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED); 799 CLR(cs->cs_preg[1], ZSWR1_RIE); 800 cs->cs_creg[1] = cs->cs_preg[1]; 801 zs_write_reg(cs, 1, cs->cs_creg[1]); 802 } 803 } 804 805 /* 806 * transmitter ready interrupt. (splzs) 807 */ 808 static void 809 zskbd_txint(cs) 810 struct zs_chanstate *cs; 811 { 812 struct zskbd_softc *zst = cs->cs_private; 813 814 /* 815 * If we've delayed a parameter change, do it now, and restart 816 * output. 817 */ 818 if (cs->cs_heldchange) { 819 zs_loadchannelregs(cs); 820 cs->cs_heldchange = 0; 821 zst->zst_tbc = zst->zst_heldtbc; 822 zst->zst_heldtbc = 0; 823 } 824 825 /* Output the next character in the buffer, if any. */ 826 if (zst->zst_tbc > 0) { 827 zs_write_data(cs, *zst->zst_tba); 828 zst->zst_tbc--; 829 if (++zst->zst_tba == zst->zst_tend) 830 zst->zst_tba = zst->zst_tbeg; 831 } else { 832 /* Disable transmit completion interrupts if necessary. */ 833 if (ISSET(cs->cs_preg[1], ZSWR1_TIE)) { 834 CLR(cs->cs_preg[1], ZSWR1_TIE); 835 cs->cs_creg[1] = cs->cs_preg[1]; 836 zs_write_reg(cs, 1, cs->cs_creg[1]); 837 } 838 if (zst->zst_tx_busy) { 839 zst->zst_tx_busy = 0; 840 zst->zst_tx_done = 1; 841 cs->cs_softreq = 1; 842 } 843 } 844 } 845 846 /* 847 * status change interrupt. (splzs) 848 */ 849 static void 850 zskbd_stint(cs, force) 851 struct zs_chanstate *cs; 852 int force; 853 { 854 struct zskbd_softc *zst = cs->cs_private; 855 u_char rr0, delta; 856 857 rr0 = zs_read_csr(cs); 858 zs_write_csr(cs, ZSWR0_RESET_STATUS); 859 860 /* 861 * Check here for console break, so that we can abort 862 * even when interrupts are locking up the machine. 863 */ 864 if (!force) 865 delta = rr0 ^ cs->cs_rr0; 866 else 867 delta = cs->cs_rr0_mask; 868 cs->cs_rr0 = rr0; 869 870 if (ISSET(delta, cs->cs_rr0_mask)) { 871 SET(cs->cs_rr0_delta, delta); 872 873 /* 874 * Stop output immediately if we lose the output 875 * flow control signal or carrier detect. 876 */ 877 if (ISSET(~rr0, cs->cs_rr0_mask)) { 878 zst->zst_tbc = 0; 879 zst->zst_heldtbc = 0; 880 } 881 882 zst->zst_st_check = 1; 883 cs->cs_softreq = 1; 884 } 885 } 886 887 void 888 zskbd_diag(arg) 889 void *arg; 890 { 891 struct zskbd_softc *zst = arg; 892 struct sunkbd_softc *ss = arg; 893 int overflows, floods; 894 int s; 895 896 s = splzs(); 897 overflows = zst->zst_overflows; 898 zst->zst_overflows = 0; 899 floods = zst->zst_floods; 900 zst->zst_floods = 0; 901 zst->zst_errors = 0; 902 splx(s); 903 904 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", 905 ss->sc_dev.dv_xname, 906 overflows, overflows == 1 ? "" : "s", 907 floods, floods == 1 ? "" : "s"); 908 } 909 910 integrate void 911 zskbd_rxsoft(zst) 912 struct zskbd_softc *zst; 913 { 914 struct sunkbd_softc *ss = (void *)zst; 915 struct zs_chanstate *cs = zst->zst_cs; 916 u_char *get, *end; 917 u_int cc, scc; 918 u_char rr1; 919 int code; 920 int s; 921 u_int8_t cbuf[SUNKBD_MAX_INPUT_SIZE], *c; 922 923 end = zst->zst_ebuf; 924 get = zst->zst_rbget; 925 scc = cc = zskbd_rbuf_size - zst->zst_rbavail; 926 927 if (cc == zskbd_rbuf_size) { 928 zst->zst_floods++; 929 if (zst->zst_errors++ == 0) 930 timeout_add_sec(&zst->zst_diag_ch, 60); 931 } 932 933 c = cbuf; 934 while (cc) { 935 code = get[0]; 936 rr1 = get[1]; 937 if (ISSET(rr1, ZSRR1_DO | ZSRR1_FE | ZSRR1_PE)) { 938 if (ISSET(rr1, ZSRR1_DO)) { 939 zst->zst_overflows++; 940 if (zst->zst_errors++ == 0) 941 timeout_add_sec(&zst->zst_diag_ch, 60); 942 } 943 if (ISSET(rr1, ZSRR1_FE)) 944 SET(code, TTY_FE); 945 if (ISSET(rr1, ZSRR1_PE)) 946 SET(code, TTY_PE); 947 } 948 949 *c++ = code; 950 if (c - cbuf == sizeof cbuf) { 951 sunkbd_input(ss, cbuf, c - cbuf); 952 c = cbuf; 953 } 954 955 get += 2; 956 if (get >= end) 957 get = zst->zst_rbuf; 958 cc--; 959 } 960 if (c != cbuf) 961 sunkbd_input(ss, cbuf, c - cbuf); 962 963 if (cc != scc) { 964 zst->zst_rbget = get; 965 s = splzs(); 966 cc = zst->zst_rbavail += scc - cc; 967 /* Buffers should be ok again, release possible block. */ 968 if (cc >= zst->zst_r_lowat) { 969 if (ISSET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED)) { 970 CLR(zst->zst_rx_flags, RX_IBUF_OVERFLOWED); 971 SET(cs->cs_preg[1], ZSWR1_RIE); 972 cs->cs_creg[1] = cs->cs_preg[1]; 973 zs_write_reg(cs, 1, cs->cs_creg[1]); 974 } 975 if (ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED)) { 976 CLR(zst->zst_rx_flags, RX_IBUF_BLOCKED); 977 zs_hwiflow(zst); 978 } 979 } 980 splx(s); 981 } 982 } 983 984 integrate void 985 zskbd_txsoft(zst) 986 struct zskbd_softc *zst; 987 { 988 } 989 990 integrate void 991 zskbd_stsoft(zst) 992 struct zskbd_softc *zst; 993 { 994 struct zs_chanstate *cs = zst->zst_cs; 995 u_char rr0, delta; 996 int s; 997 998 s = splzs(); 999 rr0 = cs->cs_rr0; 1000 delta = cs->cs_rr0_delta; 1001 cs->cs_rr0_delta = 0; 1002 splx(s); 1003 1004 if (ISSET(delta, cs->cs_rr0_cts)) { 1005 /* Block or unblock output according to flow control. */ 1006 if (ISSET(rr0, cs->cs_rr0_cts)) 1007 zst->zst_tx_stopped = 0; 1008 else 1009 zst->zst_tx_stopped = 1; 1010 } 1011 } 1012 1013 /* 1014 * Software interrupt. Called at zssoft 1015 * 1016 * The main job to be done here is to empty the input ring 1017 * by passing its contents up to the tty layer. The ring is 1018 * always emptied during this operation, therefore the ring 1019 * must not be larger than the space after "high water" in 1020 * the tty layer, or the tty layer might drop our input. 1021 * 1022 * Note: an "input blockage" condition is assumed to exist if 1023 * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set. 1024 */ 1025 static void 1026 zskbd_softint(cs) 1027 struct zs_chanstate *cs; 1028 { 1029 struct zskbd_softc *zst = cs->cs_private; 1030 int s; 1031 1032 s = spltty(); 1033 1034 if (zst->zst_rx_ready) { 1035 zst->zst_rx_ready = 0; 1036 zskbd_rxsoft(zst); 1037 } 1038 1039 if (zst->zst_st_check) { 1040 zst->zst_st_check = 0; 1041 zskbd_stsoft(zst); 1042 } 1043 1044 if (zst->zst_tx_done) { 1045 zst->zst_tx_done = 0; 1046 zskbd_txsoft(zst); 1047 } 1048 1049 splx(s); 1050 } 1051 1052 struct zsops zsops_kbd = { 1053 zskbd_rxint, /* receive char available */ 1054 zskbd_stint, /* external/status */ 1055 zskbd_txint, /* xmit buffer empty */ 1056 zskbd_softint, /* process software interrupt */ 1057 }; 1058 1059 void 1060 zskbd_cnpollc(v, on) 1061 void *v; 1062 int on; 1063 { 1064 extern int swallow_zsintrs; 1065 1066 if (on) 1067 swallow_zsintrs++; 1068 else 1069 swallow_zsintrs--; 1070 } 1071 1072 void 1073 zskbd_cngetc(v, type, data) 1074 void *v; 1075 u_int *type; 1076 int *data; 1077 { 1078 struct zskbd_softc *zst = v; 1079 int s; 1080 u_int8_t c, rr0; 1081 1082 s = splhigh(); 1083 do { 1084 rr0 = *zst->zst_cs->cs_reg_csr; 1085 } while ((rr0 & ZSRR0_RX_READY) == 0); 1086 1087 c = *zst->zst_cs->cs_reg_data; 1088 splx(s); 1089 1090 sunkbd_decode(c, type, data); 1091 } 1092