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