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