1 /* $NetBSD: ewskbd.c,v 1.14 2021/09/18 15:14:40 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2005 Izumi Tsutsui. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * Copyright (c) 2004 Steve Rumble 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 3. The name of the author may not be used to endorse or promote products 40 * derived from this software without specific prior written permission. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 */ 53 54 /* 55 * EWS4800 serial keyboard driver attached to zs channel 0 at 4800 bps. 56 * This layer is the parent of wskbd. 57 * 58 * This driver is taken from sgimips. 59 */ 60 61 #include <sys/cdefs.h> 62 __KERNEL_RCSID(0, "$NetBSD: ewskbd.c,v 1.14 2021/09/18 15:14:40 tsutsui Exp $"); 63 64 #include <sys/param.h> 65 #include <sys/kmem.h> 66 #include <sys/systm.h> 67 #include <sys/conf.h> 68 #include <sys/device.h> 69 70 #include <dev/wscons/wsconsio.h> 71 #include <dev/wscons/wskbdvar.h> 72 #include <dev/wscons/wsksymdef.h> 73 #include <dev/wscons/wsksymvar.h> 74 75 #include <dev/ic/z8530reg.h> 76 #include <machine/z8530var.h> 77 78 #include <ews4800mips/dev/ews4800keymap.h> 79 80 #define EWSKBD_BAUD 4800 81 82 #define EWSKBD_TXQ_LEN 16 /* power of 2 */ 83 #define EWSKBD_TXQ_LEN_MASK (EWSKBD_TXQ_LEN - 1) 84 #define EWSKBD_NEXTTXQ(x) (((x) + 1) & EWSKBD_TXQ_LEN_MASK) 85 86 #define EWSKBD_RXQ_LEN 64 /* power of 2 */ 87 #define EWSKBD_RXQ_LEN_MASK (EWSKBD_RXQ_LEN - 1) 88 #define EWSKBD_NEXTRXQ(x) (((x) + 1) & EWSKBD_RXQ_LEN_MASK) 89 90 #define EWSKBD_KEY_UP 0x80 91 #define EWSKBD_KEY_MASK 0x7f 92 93 #ifdef EWSKBD_DEBUG 94 int ewskbd_debug = 0; 95 #define DPRINTF(_x) if (ewskbd_debug) printf _x 96 #else 97 #define DPRINTF(_x) 98 #endif 99 100 struct ewskbd_softc { 101 device_t sc_dev; 102 struct ewskbd_devconfig *sc_dc; 103 }; 104 105 struct ewskbd_devconfig { 106 /* transmit tail-chasing fifo */ 107 uint8_t txq[EWSKBD_TXQ_LEN]; 108 u_int txq_head; 109 u_int txq_tail; 110 111 /* receive tail-chasing fifo */ 112 uint8_t rxq[EWSKBD_RXQ_LEN]; 113 u_int rxq_head; 114 u_int rxq_tail; 115 116 /* state */ 117 u_int state; 118 #define TX_READY 0x01 119 120 /* LED status */ 121 uint8_t leds; 122 #define EWSKBD_SETLEDS 0x90 123 #define EWSKBD_CAPSLOCK 0x02 124 #define EWSKBD_KANA 0x04 125 126 /* wscons glue */ 127 device_t wskbddev; 128 int enabled; 129 }; 130 131 static int ewskbd_zsc_match(device_t, cfdata_t, void *); 132 static void ewskbd_zsc_attach(device_t, device_t, void *); 133 static int ewskbd_zsc_init(struct zs_chanstate *); 134 static void ewskbd_zsc_rxint(struct zs_chanstate *); 135 static void ewskbd_zsc_stint(struct zs_chanstate *, int); 136 static void ewskbd_zsc_txint(struct zs_chanstate *); 137 static void ewskbd_zsc_softint(struct zs_chanstate *); 138 static void ewskbd_zsc_send(struct zs_chanstate *, uint8_t *, u_int); 139 140 static void ewskbd_wskbd_input(struct zs_chanstate *, u_char); 141 static int ewskbd_wskbd_enable(void *, int); 142 static void ewskbd_wskbd_set_leds(void *, int); 143 static int ewskbd_wskbd_get_leds(void *); 144 static int ewskbd_wskbd_ioctl(void *, u_long, void *, int, struct lwp *); 145 146 void ewskbd_zsc_cnattach(uint32_t, uint32_t, int); 147 static void ewskbd_zsc_wskbd_getc(void *, u_int *, int *); 148 static void ewskbd_wskbd_pollc(void *, int); 149 static void ewskbd_wskbd_bell(void *, u_int, u_int, u_int); 150 151 CFATTACH_DECL_NEW(ewskbd_zsc, sizeof(struct ewskbd_softc), 152 ewskbd_zsc_match, ewskbd_zsc_attach, NULL, NULL); 153 154 static struct zsops ewskbd_zsops = { 155 ewskbd_zsc_rxint, 156 ewskbd_zsc_stint, 157 ewskbd_zsc_txint, 158 ewskbd_zsc_softint 159 }; 160 161 const struct wskbd_mapdata ews4800kbd_wskbd_keymapdata = { 162 ews4800kbd_keydesctab, 163 KB_JP 164 }; 165 166 const struct wskbd_accessops ewskbd_wskbd_accessops = { 167 ewskbd_wskbd_enable, 168 ewskbd_wskbd_set_leds, 169 ewskbd_wskbd_ioctl 170 }; 171 172 const struct wskbd_consops ewskbd_wskbd_consops = { 173 ewskbd_zsc_wskbd_getc, 174 ewskbd_wskbd_pollc, 175 ewskbd_wskbd_bell 176 }; 177 178 static struct ewskbd_devconfig ewskbd_console_dc; 179 static struct zs_chanstate conschan; 180 static int ewskbd_is_console; 181 182 static int 183 ewskbd_zsc_match(device_t parent, cfdata_t cf, void *aux) 184 { 185 struct zsc_attach_args *zsc_args = aux; 186 struct zsc_softc *zsc = device_private(parent); 187 188 /* keyboard is on channel B */ 189 if ((zsc->zsc_flags & 0x0001 /* kbms port */) != 0 && 190 zsc_args->channel == 1) 191 /* prior to generic zstty(4) */ 192 return 3; 193 194 return 0; 195 } 196 197 static void 198 ewskbd_zsc_attach(device_t parent, device_t self, void *aux) 199 { 200 struct ewskbd_softc *sc; 201 struct zsc_softc *zsc; 202 struct zs_chanstate *cs; 203 struct zsc_attach_args *zsc_args; 204 struct wskbddev_attach_args wskaa; 205 int channel; 206 207 sc = device_private(self); 208 zsc = device_private(parent); 209 sc->sc_dev = self; 210 zsc_args = aux; 211 212 /* Establish ourself with the MD z8530 driver */ 213 channel = zsc_args->channel; 214 cs = zsc->zsc_cs[channel]; 215 216 if (ewskbd_is_console) { 217 sc->sc_dc = &ewskbd_console_dc; 218 wskaa.console = 1; 219 sc->sc_dc->enabled = 1; 220 } else { 221 wskaa.console = 0; 222 223 sc->sc_dc = kmem_zalloc(sizeof(struct ewskbd_devconfig), 224 KM_SLEEP); 225 if (sc->sc_dc == NULL) { 226 printf(": can't allocate memory\n"); 227 return; 228 } 229 sc->sc_dc->enabled = 0; 230 } 231 cs->cs_defspeed = EWSKBD_BAUD; 232 cs->cs_ops = &ewskbd_zsops; 233 cs->cs_private = sc; 234 235 sc->sc_dc->txq_head = 0; 236 sc->sc_dc->txq_tail = 0; 237 sc->sc_dc->rxq_head = 0; 238 sc->sc_dc->rxq_tail = 0; 239 sc->sc_dc->state = TX_READY; 240 sc->sc_dc->leds = 0; 241 242 ewskbd_zsc_init(cs); 243 244 /* set default LED */ 245 ewskbd_wskbd_set_leds(cs, 0); 246 247 printf(": baud rate %d\n", EWSKBD_BAUD); 248 249 /* attach wskbd */ 250 wskaa.keymap = &ews4800kbd_wskbd_keymapdata; 251 wskaa.accessops = &ewskbd_wskbd_accessops; 252 wskaa.accesscookie = cs; 253 sc->sc_dc->wskbddev = config_found(self, &wskaa, wskbddevprint, 254 CFARGS_NONE); 255 } 256 257 static int 258 ewskbd_zsc_init(struct zs_chanstate *cs) 259 { 260 int s; 261 262 s = splzs(); 263 264 zs_write_reg(cs, 9, ZSWR9_B_RESET); 265 DELAY(100); 266 zs_write_reg(cs, 9, ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR); 267 268 cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE; 269 cs->cs_preg[2] = 0; 270 cs->cs_preg[3] = ZSWR3_RX_8 | ZSWR3_RX_ENABLE; 271 cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_PARENB; 272 cs->cs_preg[5] = ZSWR5_TX_8 | ZSWR5_RTS | ZSWR5_TX_ENABLE; 273 cs->cs_preg[6] = 0; 274 cs->cs_preg[7] = 0; 275 cs->cs_preg[8] = 0; 276 cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR; 277 cs->cs_preg[10] = 0; 278 cs->cs_preg[11] = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD | 279 ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD; 280 /* reg[11] and reg[12] are set by zs_set_speed() with cs_brg_clk */ 281 zs_set_speed(cs, EWSKBD_BAUD); 282 cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA; 283 cs->cs_preg[15] = 0; 284 285 zs_loadchannelregs(cs); 286 287 splx(s); 288 289 return 0; 290 } 291 292 static void 293 ewskbd_zsc_rxint(struct zs_chanstate *cs) 294 { 295 struct ewskbd_softc *sc; 296 struct ewskbd_devconfig *dc; 297 uint8_t c, r; 298 299 sc = cs->cs_private; 300 dc = sc->sc_dc; 301 302 /* clear errors */ 303 r = zs_read_reg(cs, 1); 304 if (r & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) 305 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 306 307 /* read byte and append to our queue */ 308 c = zs_read_data(cs); 309 310 dc->rxq[dc->rxq_tail] = c; 311 dc->rxq_tail = EWSKBD_NEXTRXQ(dc->rxq_tail); 312 313 cs->cs_softreq = 1; 314 } 315 316 static void 317 ewskbd_zsc_stint(struct zs_chanstate *cs, int force) 318 { 319 320 zs_write_csr(cs, ZSWR0_RESET_STATUS); 321 cs->cs_softreq = 1; 322 } 323 324 static void 325 ewskbd_zsc_txint(struct zs_chanstate *cs) 326 { 327 struct ewskbd_softc *sc; 328 329 sc = cs->cs_private; 330 zs_write_reg(cs, 0, ZSWR0_RESET_TXINT); 331 sc->sc_dc->state |= TX_READY; 332 cs->cs_softreq = 1; 333 } 334 335 static void 336 ewskbd_zsc_softint(struct zs_chanstate *cs) 337 { 338 struct ewskbd_softc *sc; 339 struct ewskbd_devconfig *dc; 340 341 sc = cs->cs_private; 342 dc = sc->sc_dc; 343 344 /* handle pending transmissions */ 345 if (dc->txq_head != dc->txq_tail && (dc->state & TX_READY)) { 346 int s; 347 348 dc->state &= ~TX_READY; 349 350 s = splzs(); 351 zs_write_data(cs, dc->txq[dc->txq_head]); 352 splx(s); 353 354 dc->txq_head = EWSKBD_NEXTTXQ(dc->txq_head); 355 } 356 357 /* don't bother if nobody is listening */ 358 if (!dc->enabled) { 359 dc->rxq_head = dc->rxq_tail; 360 return; 361 } 362 363 /* handle incoming keystrokes/config */ 364 while (dc->rxq_head != dc->rxq_tail) { 365 uint8_t key = dc->rxq[dc->rxq_head]; 366 367 /* toss wskbd a bone */ 368 ewskbd_wskbd_input(cs, key); 369 370 dc->rxq_head = EWSKBD_NEXTRXQ(dc->rxq_head); 371 } 372 } 373 374 /* expects to be in splzs() */ 375 static void 376 ewskbd_zsc_send(struct zs_chanstate *cs, uint8_t *c, u_int len) 377 { 378 struct ewskbd_softc *sc; 379 struct ewskbd_devconfig *dc; 380 int i; 381 382 sc = cs->cs_private; 383 dc = sc->sc_dc; 384 385 for (i = 0; i < len; i++) { 386 if (dc->state & TX_READY) { 387 zs_write_data(cs, c[i]); 388 dc->state &= ~TX_READY; 389 } else { 390 dc->txq[dc->txq_tail] = c[i]; 391 dc->txq_tail = EWSKBD_NEXTTXQ(dc->txq_tail); 392 cs->cs_softreq = 1; 393 } 394 } 395 } 396 397 /****************************************************************************** 398 * wskbd glue 399 ******************************************************************************/ 400 401 static void 402 ewskbd_wskbd_input(struct zs_chanstate *cs, uint8_t key) 403 { 404 struct ewskbd_softc *sc; 405 u_int type; 406 407 sc = cs->cs_private; 408 409 if (key & EWSKBD_KEY_UP) 410 type = WSCONS_EVENT_KEY_UP; 411 else 412 type = WSCONS_EVENT_KEY_DOWN; 413 414 wskbd_input(sc->sc_dc->wskbddev, type, (key & EWSKBD_KEY_MASK)); 415 416 DPRINTF(("ewskbd_wskbd_input: inputted key 0x%x\n", key)); 417 418 #ifdef WSDISPLAY_COMPAT_RAWKBD 419 wskbd_rawinput(sc->sc_dc->wskbddev, &key, 1); 420 #endif 421 } 422 423 static int 424 ewskbd_wskbd_enable(void *cookie, int on) 425 { 426 struct zs_chanstate *cs; 427 struct ewskbd_softc *sc; 428 429 cs = cookie; 430 sc = cs->cs_private; 431 432 if (on) { 433 if (sc->sc_dc->enabled) 434 return EBUSY; 435 else 436 sc->sc_dc->enabled = 1; 437 } else 438 sc->sc_dc->enabled = 0; 439 440 DPRINTF(("ewskbd_wskbd_enable: %s\n", on ? "enabled" : "disabled")); 441 442 return 0; 443 } 444 445 static void 446 ewskbd_wskbd_set_leds(void *cookie, int leds) 447 { 448 struct zs_chanstate *cs; 449 struct ewskbd_softc *sc; 450 int s; 451 uint8_t cmd; 452 453 cs = cookie; 454 sc = cs->cs_private; 455 cmd = 0; 456 457 if (leds & WSKBD_LED_CAPS) 458 cmd |= EWSKBD_CAPSLOCK; 459 460 sc->sc_dc->leds = cmd; 461 462 cmd |= EWSKBD_SETLEDS; 463 464 s = splzs(); 465 ewskbd_zsc_send(cs, &cmd, 1); 466 splx(s); 467 } 468 469 static int 470 ewskbd_wskbd_get_leds(void *cookie) 471 { 472 struct zs_chanstate *cs; 473 struct ewskbd_softc *sc; 474 int leds; 475 476 cs = cookie; 477 sc = cs->cs_private; 478 leds = 0; 479 480 if (sc->sc_dc->leds & EWSKBD_CAPSLOCK) 481 leds |= WSKBD_LED_CAPS; 482 483 return leds; 484 } 485 486 static int 487 ewskbd_wskbd_ioctl(void *cookie, u_long cmd, void *data, int flag, 488 struct lwp *l) 489 { 490 491 switch (cmd) { 492 case WSKBDIO_GTYPE: 493 *(int *)data = WSKBD_TYPE_EWS4800; 494 break; 495 496 #ifdef notyet 497 case WSKBDIO_COMPLEXBELL: 498 case WSKBDIO_SETKEYREPEAT: 499 case WSKBDIO_GETKEYREPEAT: 500 case WSKBDIO_SETDEFAULTKEYREPEAT: 501 case WSKBDIO_GETDEFAULTKEYREPEAT: 502 #endif 503 504 case WSKBDIO_SETLEDS: 505 ewskbd_wskbd_set_leds(cookie, *(int *)data); 506 break; 507 508 case WSKBDIO_GETLEDS: 509 *(int *)data = ewskbd_wskbd_get_leds(cookie); 510 break; 511 512 #ifdef notyet 513 case WSKBDIO_GETMAP: 514 case WSKBDIO_SETMAP: 515 case WSKBDIO_GETENCODING: 516 case WSKBDIO_SETENCODING: 517 case WSKBDIO_SETMODE: 518 case WSKBDIO_GETMODE: 519 case WSKBDIO_SETKEYCLICK: 520 case WSKBDIO_GETKEYCLICK: 521 #endif 522 523 default: 524 return EPASSTHROUGH; 525 } 526 527 return 0; 528 } 529 530 /* 531 * console routines 532 */ 533 void 534 ewskbd_zsc_cnattach(uint32_t csr, uint32_t data, int pclk) 535 { 536 struct zs_chanstate *cs; 537 538 cs = &conschan; 539 540 cs->cs_reg_csr = (void *)csr; 541 cs->cs_reg_data = (void *)data; 542 cs->cs_brg_clk = pclk / 16; 543 cs->cs_defspeed = EWSKBD_BAUD; 544 545 ewskbd_zsc_init(cs); 546 547 zs_putc(cs, EWSKBD_SETLEDS); 548 549 wskbd_cnattach(&ewskbd_wskbd_consops, cs, &ews4800kbd_wskbd_keymapdata); 550 ewskbd_is_console = 1; 551 } 552 553 static void 554 ewskbd_zsc_wskbd_getc(void *cookie, u_int *type, int *data) 555 { 556 int key; 557 558 key = zs_getc(cookie); 559 560 if (key & EWSKBD_KEY_UP) 561 *type = WSCONS_EVENT_KEY_UP; 562 else 563 *type = WSCONS_EVENT_KEY_DOWN; 564 565 *data = key & EWSKBD_KEY_MASK; 566 } 567 568 static void 569 ewskbd_wskbd_pollc(void *cookie, int on) 570 { 571 572 static bool __polling = false; 573 static int s; 574 575 if (on && !__polling) { 576 /* disable interrupt driven I/O */ 577 s = splhigh(); 578 __polling = true; 579 } else if (!on && __polling) { 580 /* enable interrupt driven I/O */ 581 __polling = false; 582 splx(s); 583 } 584 } 585 586 static void 587 ewskbd_wskbd_bell(void *cookie, u_int pitch, u_int period, u_int volume) 588 { 589 590 /* nothing */ 591 } 592