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