1 /* $NetBSD: lunaws.c,v 1.42 2023/01/15 05:08:33 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 33 34 __KERNEL_RCSID(0, "$NetBSD: lunaws.c,v 1.42 2023/01/15 05:08:33 tsutsui Exp $"); 35 36 #include "opt_wsdisplay_compat.h" 37 #include "wsmouse.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/conf.h> 42 #include <sys/device.h> 43 #include <sys/rndsource.h> 44 45 #include <dev/wscons/wsconsio.h> 46 #include <dev/wscons/wskbdvar.h> 47 #include <dev/wscons/wsksymdef.h> 48 #include <dev/wscons/wsksymvar.h> 49 #include <dev/wscons/wsmousevar.h> 50 51 #include <luna68k/dev/omkbdmap.h> 52 #include <luna68k/dev/sioreg.h> 53 #include <luna68k/dev/siovar.h> 54 55 #include <machine/board.h> 56 57 #include "ioconf.h" 58 59 #define OMKBD_RXQ_LEN 64 60 #define OMKBD_RXQ_LEN_MASK (OMKBD_RXQ_LEN - 1) 61 #define OMKBD_NEXTRXQ(x) (((x) + 1) & OMKBD_RXQ_LEN_MASK) 62 #define OMKBD_TXQ_LEN 16 63 #define OMKBD_TXQ_LEN_MASK (OMKBD_TXQ_LEN - 1) 64 #define OMKBD_NEXTTXQ(x) (((x) + 1) & OMKBD_TXQ_LEN_MASK) 65 66 /* Keyboard commands */ 67 /* 000XXXXXb : LED commands */ 68 #define OMKBD_LED_ON_KANA 0x10 /* kana LED on */ 69 #define OMKBD_LED_OFF_KANA 0x00 /* kana LED off */ 70 #define OMKBD_LED_ON_CAPS 0x11 /* caps LED on */ 71 #define OMKBD_LED_OFF_CAPS 0x01 /* caps LED off */ 72 /* 010XXXXXb : buzzer commands */ 73 #define OMKBD_BUZZER 0x40 74 #define OMKBD_BUZZER_PERIOD 0x18 75 #define OMKBD_BUZZER_40MS 0x00 76 #define OMKBD_BUZZER_150MS 0x08 77 #define OMKBD_BUZZER_400MS 0x10 78 #define OMKBD_BUZZER_700MS 0x18 79 #define OMKBD_BUZZER_PITCH 0x07 80 #define OMKBD_BUZZER_6000HZ 0x00 81 #define OMKBD_BUZZER_3000HZ 0x01 82 #define OMKBD_BUZZER_1500HZ 0x02 83 #define OMKBD_BUZZER_1000HZ 0x03 84 #define OMKBD_BUZZER_600HZ 0x04 85 #define OMKBD_BUZZER_300HZ 0x05 86 #define OMKBD_BUZZER_150HZ 0x06 87 #define OMKBD_BUZZER_100HZ 0x07 88 /* 011XXXXXb : mouse on command */ 89 #define OMKBD_MOUSE_ON 0x60 90 /* 001XXXXXb : mouse off command */ 91 #define OMKBD_MOUSE_OFF 0x20 92 93 #define OMKBD_BUZZER_DEFAULT \ 94 (OMKBD_BUZZER | OMKBD_BUZZER_40MS | OMKBD_BUZZER_1500HZ) 95 96 static const uint8_t ch1_regs[6] = { 97 WR0_RSTINT, /* Reset E/S Interrupt */ 98 WR1_RXALLS | WR1_TXENBL, /* Rx per char, Tx */ 99 0, /* */ 100 WR3_RX8BIT | WR3_RXENBL, /* Rx */ 101 WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY, /* Tx/Rx */ 102 WR5_TX8BIT | WR5_TXENBL, /* Tx */ 103 }; 104 105 struct ws_conscookie { 106 struct sioreg *cc_sio; 107 int cc_polling; 108 struct ws_softc *cc_sc; 109 }; 110 111 struct ws_softc { 112 device_t sc_dev; 113 struct sioreg *sc_ctl; 114 uint8_t sc_wr[6]; 115 device_t sc_wskbddev; 116 uint8_t sc_rxq[OMKBD_RXQ_LEN]; 117 u_int sc_rxqhead; 118 u_int sc_rxqtail; 119 uint8_t sc_txq[OMKBD_TXQ_LEN]; 120 u_int sc_txqhead; 121 u_int sc_txqtail; 122 bool sc_tx_busy; 123 bool sc_tx_done; 124 int sc_leds; 125 #if NWSMOUSE > 0 126 device_t sc_wsmousedev; 127 int sc_msbuttons, sc_msdx, sc_msdy; 128 #endif 129 int sc_msreport; 130 void *sc_si; 131 int sc_rawkbd; 132 133 struct ws_conscookie *sc_conscookie; 134 krndsource_t sc_rndsource; 135 }; 136 137 static void omkbd_input(struct ws_softc *, int); 138 static void omkbd_send(struct ws_softc *, uint8_t); 139 static void omkbd_decode(struct ws_softc *, int, u_int *, int *); 140 141 static int omkbd_enable(void *, int); 142 static void omkbd_set_leds(void *, int); 143 static int omkbd_ioctl(void *, u_long, void *, int, struct lwp *); 144 145 static void omkbd_complex_buzzer(struct ws_softc *, struct wskbd_bell_data *); 146 static uint8_t omkbd_get_buzcmd(struct ws_softc *, struct wskbd_bell_data *, 147 uint8_t); 148 149 static const struct wskbd_mapdata omkbd_keymapdata = { 150 .keydesc = omkbd_keydesctab, 151 .layout = KB_JP, 152 }; 153 static const struct wskbd_accessops omkbd_accessops = { 154 .enable = omkbd_enable, 155 .set_leds = omkbd_set_leds, 156 .ioctl = omkbd_ioctl, 157 }; 158 159 void ws_cnattach(void); 160 static void ws_cngetc(void *, u_int *, int *); 161 static void ws_cnpollc(void *, int); 162 static void ws_cnbell(void *, u_int, u_int, u_int); 163 static const struct wskbd_consops ws_consops = { 164 .getc = ws_cngetc, 165 .pollc = ws_cnpollc, 166 .bell = ws_cnbell, 167 }; 168 static struct ws_conscookie ws_conscookie; 169 170 #if NWSMOUSE > 0 171 static int omms_enable(void *); 172 static int omms_ioctl(void *, u_long, void *, int, struct lwp *); 173 static void omms_disable(void *); 174 175 static const struct wsmouse_accessops omms_accessops = { 176 .enable = omms_enable, 177 .ioctl = omms_ioctl, 178 .disable = omms_disable, 179 }; 180 #endif 181 182 static void wsintr(void *); 183 static void wssoftintr(void *); 184 185 static int wsmatch(device_t, cfdata_t, void *); 186 static void wsattach(device_t, device_t, void *); 187 188 CFATTACH_DECL_NEW(ws, sizeof(struct ws_softc), 189 wsmatch, wsattach, NULL, NULL); 190 191 /* #define LUNAWS_DEBUG */ 192 193 #ifdef LUNAWS_DEBUG 194 #define DEBUG_KBDTX 0x01 195 #define DEBUG_RXSOFT 0x02 196 #define DEBUG_BUZZER 0x04 197 uint32_t lunaws_debug = 0x00 /* | DEBUG_BUZZER | DEBUG_KBDTX | DEBUG_RXSOFT */; 198 #define DPRINTF(x, y) if (lunaws_debug & (x)) printf y 199 #else 200 #define DPRINTF(x, y) __nothing 201 #endif 202 203 static int 204 wsmatch(device_t parent, cfdata_t cf, void *aux) 205 { 206 struct sio_attach_args *args = aux; 207 208 if (args->channel != 1) 209 return 0; 210 return 1; 211 } 212 213 static void 214 wsattach(device_t parent, device_t self, void *aux) 215 { 216 struct ws_softc *sc = device_private(self); 217 struct sio_softc *siosc = device_private(parent); 218 struct sio_attach_args *args = aux; 219 int channel = args->channel; 220 struct wskbddev_attach_args a; 221 222 sc->sc_dev = self; 223 sc->sc_ctl = &siosc->sc_ctl[channel]; 224 memcpy(sc->sc_wr, ch1_regs, sizeof(ch1_regs)); 225 siosc->sc_intrhand[channel].ih_func = wsintr; 226 siosc->sc_intrhand[channel].ih_arg = sc; 227 228 sc->sc_conscookie = &ws_conscookie; 229 sc->sc_conscookie->cc_sc = sc; 230 sc->sc_conscookie->cc_polling = 0; 231 232 setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); 233 setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); 234 setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); 235 setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); 236 setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); 237 238 sc->sc_rxqhead = 0; 239 sc->sc_rxqtail = 0; 240 sc->sc_txqhead = 0; 241 sc->sc_txqtail = 0; 242 sc->sc_tx_busy = false; 243 sc->sc_tx_done = false; 244 245 sc->sc_si = softint_establish(SOFTINT_SERIAL, wssoftintr, sc); 246 rnd_attach_source(&sc->sc_rndsource, device_xname(self), 247 RND_TYPE_TTY, RND_FLAG_DEFAULT); 248 249 /* enable interrupt */ 250 setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); 251 252 aprint_normal("\n"); 253 254 /* keep mouse quiet */ 255 omkbd_send(sc, OMKBD_MOUSE_OFF); 256 257 a.console = (args->hwflags == 1); 258 a.keymap = &omkbd_keymapdata; 259 a.accessops = &omkbd_accessops; 260 a.accesscookie = (void *)sc; 261 sc->sc_wskbddev = config_found(self, &a, wskbddevprint, 262 CFARGS(.iattr = "wskbddev")); 263 264 #if NWSMOUSE > 0 265 { 266 struct wsmousedev_attach_args b; 267 b.accessops = &omms_accessops; 268 b.accesscookie = (void *)sc; 269 sc->sc_wsmousedev = config_found(self, &b, wsmousedevprint, 270 CFARGS(.iattr = "wsmousedev")); 271 } 272 #endif 273 sc->sc_msreport = 0; 274 } 275 276 static void 277 wsintr(void *arg) 278 { 279 struct ws_softc *sc = arg; 280 struct sioreg *sio = sc->sc_ctl; 281 uint8_t code = 0; 282 uint16_t rr, rndcsr = 0; 283 bool handled = false; 284 285 rr = getsiocsr(sio); 286 rndcsr = rr; 287 if ((rr & RR_RXRDY) != 0) { 288 do { 289 code = sio->sio_data; 290 if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { 291 sio->sio_cmd = WR0_ERRRST; 292 continue; 293 } 294 sc->sc_rxq[sc->sc_rxqtail] = code; 295 sc->sc_rxqtail = OMKBD_NEXTRXQ(sc->sc_rxqtail); 296 } while (((rr = getsiocsr(sio)) & RR_RXRDY) != 0); 297 handled = true; 298 } 299 if ((rr & RR_TXRDY) != 0) { 300 sio->sio_cmd = WR0_RSTPEND; 301 if (sc->sc_tx_busy) { 302 sc->sc_tx_busy = false; 303 sc->sc_tx_done = true; 304 handled = true; 305 } 306 } 307 if (handled) { 308 softint_schedule(sc->sc_si); 309 rnd_add_uint32(&sc->sc_rndsource, (rndcsr << 8) | code); 310 } 311 } 312 313 static void 314 wssoftintr(void *arg) 315 { 316 struct ws_softc *sc = arg; 317 uint8_t code; 318 319 /* handle pending keyboard commands */ 320 if (sc->sc_tx_done) { 321 int s; 322 323 s = splserial(); 324 sc->sc_tx_done = false; 325 DPRINTF(DEBUG_KBDTX, ("%s: tx complete\n", __func__)); 326 if (sc->sc_txqhead != sc->sc_txqtail) { 327 struct sioreg *sio = sc->sc_ctl; 328 329 sc->sc_tx_busy = true; 330 sio->sio_data = sc->sc_txq[sc->sc_txqhead]; 331 DPRINTF(DEBUG_KBDTX, 332 ("%s: sio_data <- txq[%2d] (%02x)\n", __func__, 333 sc->sc_txqhead, sc->sc_txq[sc->sc_txqhead])); 334 335 sc->sc_txqhead = OMKBD_NEXTTXQ(sc->sc_txqhead); 336 } 337 splx(s); 338 } 339 340 /* handle received keyboard and mouse data */ 341 while (sc->sc_rxqhead != sc->sc_rxqtail) { 342 code = sc->sc_rxq[sc->sc_rxqhead]; 343 DPRINTF(DEBUG_RXSOFT, ("%s: %02x <- rxq[%2d]\n", __func__, 344 code, sc->sc_rxqhead)); 345 sc->sc_rxqhead = OMKBD_NEXTRXQ(sc->sc_rxqhead); 346 /* 347 * if (code >= 0x80 && code <= 0x87), i.e. 348 * if ((code & 0xf8) == 0x80), then 349 * it's the first byte of 3 byte long mouse report 350 * code[0] & 07 -> LMR button condition 351 * code[1], [2] -> x,y delta 352 * otherwise, key press or release event. 353 */ 354 if (sc->sc_msreport == 1) { 355 #if NWSMOUSE > 0 356 sc->sc_msdx = (int8_t)code; 357 #endif 358 sc->sc_msreport = 2; 359 continue; 360 } else if (sc->sc_msreport == 2) { 361 #if NWSMOUSE > 0 362 sc->sc_msdy = (int8_t)code; 363 wsmouse_input(sc->sc_wsmousedev, 364 sc->sc_msbuttons, sc->sc_msdx, sc->sc_msdy, 0, 0, 365 WSMOUSE_INPUT_DELTA); 366 #endif 367 sc->sc_msreport = 0; 368 continue; 369 } 370 if ((code & 0xf8) == 0x80) { 371 #if NWSMOUSE > 0 372 /* buttons: Negative logic to positive */ 373 code = ~code; 374 /* LMR->RML: wsevent counts 0 for leftmost */ 375 sc->sc_msbuttons = 376 ((code & 1) << 2) | (code & 2) | ((code & 4) >> 2); 377 #endif 378 sc->sc_msreport = 1; 379 continue; 380 } 381 omkbd_input(sc, code); 382 } 383 } 384 385 static void 386 omkbd_send(struct ws_softc *sc, uint8_t txdata) 387 { 388 int s; 389 390 if (!sc->sc_tx_busy) { 391 struct sioreg *sio = sc->sc_ctl; 392 393 DPRINTF(DEBUG_KBDTX, 394 ("%s: sio_data <- %02x\n", __func__, txdata)); 395 s = splserial(); 396 sc->sc_tx_busy = true; 397 sio->sio_data = txdata; 398 splx(s); 399 } else { 400 s = splsoftserial(); 401 sc->sc_txq[sc->sc_txqtail] = txdata; 402 DPRINTF(DEBUG_KBDTX, 403 ("%s: txq[%2d] <- %02x\n", __func__, 404 sc->sc_txqtail, sc->sc_txq[sc->sc_txqtail])); 405 sc->sc_txqtail = OMKBD_NEXTTXQ(sc->sc_txqtail); 406 splx(s); 407 softint_schedule(sc->sc_si); 408 } 409 } 410 411 static void 412 omkbd_input(struct ws_softc *sc, int data) 413 { 414 u_int type; 415 int key; 416 417 omkbd_decode(sc, data, &type, &key); 418 419 #ifdef WSDISPLAY_COMPAT_RAWKBD 420 if (sc->sc_rawkbd) { 421 uint8_t cbuf[2]; 422 int c, j = 0; 423 424 c = omkbd_raw[key]; 425 if (c == 0x70 /* Kana */ || 426 c == 0x3a /* CAP */) { 427 /* See comment in !sc->sc_rawkbd case */ 428 cbuf[0] = c; 429 wskbd_rawinput(sc->sc_wskbddev, cbuf, 1); 430 cbuf[0] = c | 0x80; 431 wskbd_rawinput(sc->sc_wskbddev, cbuf, 1); 432 } else 433 if (c != 0x00) { 434 /* fake extended scancode if necessary */ 435 if (c & 0x80) 436 cbuf[j++] = 0xe0; 437 cbuf[j] = c & 0x7f; 438 if (type == WSCONS_EVENT_KEY_UP) 439 cbuf[j] |= 0x80; 440 j++; 441 442 wskbd_rawinput(sc->sc_wskbddev, cbuf, j); 443 } 444 } else 445 #endif 446 { 447 if (sc->sc_wskbddev != NULL) { 448 if (key == 0x0b /* Kana */ || 449 key == 0x0e /* CAP */) { 450 /* 451 * LUNA's keyboard doesn't send any keycode 452 * when these modifier keys are released. 453 * Instead, it sends a pressed or released code 454 * per how each modifier LED status will be 455 * changed when the modifier keys are pressed. 456 * To handle this quirk in MI wskbd(4) layer, 457 * we have to send a faked 458 * "pressed and released" sequence here. 459 */ 460 wskbd_input(sc->sc_wskbddev, 461 WSCONS_EVENT_KEY_DOWN, key); 462 wskbd_input(sc->sc_wskbddev, 463 WSCONS_EVENT_KEY_UP, key); 464 } else { 465 wskbd_input(sc->sc_wskbddev, type, key); 466 } 467 } 468 } 469 } 470 471 static void 472 omkbd_decode(struct ws_softc *sc, int datain, u_int *type, int *dataout) 473 { 474 475 *type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 476 *dataout = datain & 0x7f; 477 } 478 479 static void 480 omkbd_complex_buzzer(struct ws_softc *sc, struct wskbd_bell_data *wbd) 481 { 482 uint8_t buzcmd; 483 484 buzcmd = omkbd_get_buzcmd(sc, wbd, OMKBD_BUZZER_DEFAULT); 485 omkbd_send(sc, buzcmd); 486 } 487 488 static uint8_t 489 omkbd_get_buzcmd(struct ws_softc *sc, struct wskbd_bell_data *wbd, 490 uint8_t obuzcmd) 491 { 492 u_int pitch, period; 493 uint8_t buzcmd; 494 495 pitch = wbd->pitch; 496 period = wbd->period; 497 buzcmd = OMKBD_BUZZER; 498 499 if ((wbd->which & WSKBD_BELL_DOPERIOD) == 0) 500 buzcmd |= obuzcmd & OMKBD_BUZZER_PERIOD; 501 else if (period >= 700) 502 buzcmd |= OMKBD_BUZZER_700MS; 503 else if (period >= 400) 504 buzcmd |= OMKBD_BUZZER_400MS; 505 else if (period >= 150) 506 buzcmd |= OMKBD_BUZZER_150MS; 507 else 508 buzcmd |= OMKBD_BUZZER_40MS; 509 510 if ((wbd->which & WSKBD_BELL_DOPITCH) == 0) 511 buzcmd |= obuzcmd & OMKBD_BUZZER_PITCH; 512 else if (pitch >= 6000) 513 buzcmd |= OMKBD_BUZZER_6000HZ; 514 else if (pitch >= 3000) 515 buzcmd |= OMKBD_BUZZER_3000HZ; 516 else if (pitch >= 1500) 517 buzcmd |= OMKBD_BUZZER_1500HZ; 518 else if (pitch >= 1000) 519 buzcmd |= OMKBD_BUZZER_1000HZ; 520 else if (pitch >= 600) 521 buzcmd |= OMKBD_BUZZER_600HZ; 522 else if (pitch >= 300) 523 buzcmd |= OMKBD_BUZZER_300HZ; 524 else if (pitch >= 150) 525 buzcmd |= OMKBD_BUZZER_150HZ; 526 else 527 buzcmd |= OMKBD_BUZZER_100HZ; 528 529 /* no volume control for buzzer on the LUNA keyboards */ 530 531 return buzcmd; 532 } 533 534 static void 535 ws_cngetc(void *cookie, u_int *type, int *data) 536 { 537 struct ws_conscookie *conscookie = cookie; 538 struct sioreg *sio = conscookie->cc_sio; 539 struct ws_softc *sc = conscookie->cc_sc; /* currently unused */ 540 int code; 541 542 code = siogetc(sio); 543 omkbd_decode(sc, code, type, data); 544 } 545 546 static void 547 ws_cnpollc(void *cookie, int on) 548 { 549 struct ws_conscookie *conscookie = cookie; 550 551 conscookie->cc_polling = on; 552 } 553 554 static void 555 ws_cnbell(void *cookie, u_int pitch, u_int period, u_int volume) 556 { 557 struct ws_conscookie *conscookie = cookie; 558 struct sioreg *sio = conscookie->cc_sio; 559 struct ws_softc *sc = conscookie->cc_sc; /* currently unused */ 560 struct wskbd_bell_data wbd; 561 uint8_t buzcmd; 562 563 /* 564 * XXX cnbell(9) man page should describe each args.. 565 * (it looks similar to the struct wskbd_bell_data) 566 * pitch: bell frequency in hertz 567 * period: bell period in ms 568 * volume: bell volume as a percentage (0-100) (as spkr(4)) 569 */ 570 wbd.which = WSKBD_BELL_DOALL; 571 wbd.period = period; 572 wbd.pitch = pitch; 573 wbd.volume = volume; 574 buzcmd = omkbd_get_buzcmd(sc, &wbd, OMKBD_BUZZER_DEFAULT); 575 576 sioputc(sio, buzcmd); 577 } 578 579 /* EXPORT */ void 580 ws_cnattach(void) 581 { 582 struct sioreg *sio_base; 583 584 sio_base = (struct sioreg *)OBIO_SIO; 585 ws_conscookie.cc_sio = &sio_base[1]; /* channel B */ 586 587 /* XXX need CH.B initialization XXX */ 588 589 wskbd_cnattach(&ws_consops, &ws_conscookie, &omkbd_keymapdata); 590 } 591 592 static int 593 omkbd_enable(void *cookie, int on) 594 { 595 596 return 0; 597 } 598 599 static void 600 omkbd_set_leds(void *cookie, int leds) 601 { 602 struct ws_softc *sc = cookie; 603 uint8_t capsledcmd, kanaledcmd; 604 605 if (sc == NULL) { 606 /* 607 * This has been checked by the caller in wskbd(9) layer 608 * for the early console, but just for sanity. 609 */ 610 return; 611 } 612 613 sc->sc_leds = leds; 614 if ((leds & WSKBD_LED_CAPS) != 0) { 615 capsledcmd = OMKBD_LED_ON_CAPS; 616 } else { 617 capsledcmd = OMKBD_LED_OFF_CAPS; 618 } 619 620 #if 0 /* no KANA lock support in wskbd */ 621 if ((leds & WSKBD_LED_KANA) != 0) { 622 kanaledcmd = OMKBD_LED_ON_KANA; 623 } else 624 #endif 625 { 626 kanaledcmd = OMKBD_LED_OFF_KANA; 627 } 628 629 if (sc->sc_conscookie->cc_polling != 0) { 630 struct sioreg *sio = sc->sc_ctl; 631 632 sioputc(sio, capsledcmd); 633 sioputc(sio, kanaledcmd); 634 } else { 635 omkbd_send(sc, capsledcmd); 636 omkbd_send(sc, kanaledcmd); 637 } 638 } 639 640 static int 641 omkbd_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l) 642 { 643 struct ws_softc *sc = cookie; 644 struct wskbd_bell_data *wbd; 645 646 switch (cmd) { 647 case WSKBDIO_GTYPE: 648 *(int *)data = WSKBD_TYPE_LUNA; 649 return 0; 650 case WSKBDIO_SETLEDS: 651 omkbd_set_leds(cookie, *(int *)data); 652 return 0; 653 case WSKBDIO_GETLEDS: 654 *(int *)data = sc->sc_leds; 655 return 0; 656 657 /* 658 * Note all WSKBDIO_*BELL ioctl(2)s except WSKBDIO_COMPLEXBELL 659 * are handled MI wskbd(4) layer. 660 * (wskbd_displayioctl() in src/sys/dev/wscons/wskbd.c) 661 */ 662 case WSKBDIO_COMPLEXBELL: 663 wbd = data; 664 DPRINTF(DEBUG_BUZZER, 665 ("%s: WSKBDIO_COMPLEXBELL: pitch = %d, period = %d\n", 666 __func__, wbd->pitch, wbd->period)); 667 omkbd_complex_buzzer(sc, wbd); 668 return 0; 669 670 #ifdef WSDISPLAY_COMPAT_RAWKBD 671 case WSKBDIO_SETMODE: 672 sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 673 return 0; 674 case WSKBDIO_GETMODE: 675 *(int *)data = sc->sc_rawkbd; 676 return 0; 677 #endif 678 } 679 return EPASSTHROUGH; 680 } 681 682 #if NWSMOUSE > 0 683 684 static int 685 omms_enable(void *cookie) 686 { 687 struct ws_softc *sc = cookie; 688 689 /* enable 3 byte long mouse reporting */ 690 omkbd_send(sc, OMKBD_MOUSE_ON); 691 692 return 0; 693 } 694 695 /*ARGUSED*/ 696 static int 697 omms_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l) 698 { 699 700 if (cmd == WSMOUSEIO_GTYPE) { 701 *(u_int *)data = 0x19991005; /* XXX */ 702 return 0; 703 } 704 return EPASSTHROUGH; 705 } 706 707 static void 708 omms_disable(void *cookie) 709 { 710 struct ws_softc *sc = cookie; 711 712 omkbd_send(sc, OMKBD_MOUSE_OFF); 713 } 714 #endif 715