]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/uart/uart_kbd_sun.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / uart / uart_kbd_sun.c
1 /*-
2  * Copyright (c) 2003 Jake Burkholder.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_compat.h"
31 #include "opt_kbd.h"
32 #include "opt_sunkbd.h"
33
34 #if (defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)) ||   \
35     !defined(SUNKBD_EMULATE_ATKBD)
36 #define KBD_DFLT_KEYMAP
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/bus.h>
42 #include <sys/interrupt.h>
43 #include <sys/kbio.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46
47 #include <machine/bus.h>
48
49 #include <dev/kbd/kbdreg.h>
50 #include <dev/kbd/kbdtables.h>
51
52 #include <dev/uart/uart.h>
53 #include <dev/uart/uart_bus.h>
54 #include <dev/uart/uart_cpu.h>
55
56 #include <dev/uart/uart_kbd_sun.h>
57 #if !defined(SUNKBD_EMULATE_ATKBD)
58 #include <dev/uart/uart_kbd_sun_tables.h>
59 #endif
60
61 #if defined(SUNKBD_EMULATE_ATKBD) && defined(SUNKBD_DFLT_KEYMAP)
62 #include "sunkbdmap.h"
63 #endif
64 #include "uart_if.h"
65
66 #define SUNKBD_DRIVER_NAME      "sunkbd"
67
68 #define TODO    printf("%s: unimplemented", __func__)
69
70 struct sunkbd_softc {
71         keyboard_t              sc_kbd;
72         struct uart_softc       *sc_uart;
73         struct uart_devinfo     *sc_sysdev;
74
75         struct callout          sc_repeat_callout;
76         int                     sc_repeat_key;
77
78         int                     sc_accents;
79         int                     sc_composed_char;
80         int                     sc_flags;
81 #define KPCOMPOSE                       (1 << 0)
82         int                     sc_mode;
83         int                     sc_polling;
84         int                     sc_repeating;
85         int                     sc_state;
86
87 #if defined(SUNKBD_EMULATE_ATKBD)
88         int                     sc_buffered_char[2];
89 #endif
90 };
91
92 static int sunkbd_configure(int flags);
93 static int sunkbd_probe_keyboard(struct uart_devinfo *di);
94
95 static int sunkbd_probe(int unit, void *arg, int flags);
96 static int sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags);
97 static int sunkbd_term(keyboard_t *kbd);
98 static int sunkbd_intr(keyboard_t *kbd, void *arg);
99 static int sunkbd_test_if(keyboard_t *kbd);
100 static int sunkbd_enable(keyboard_t *kbd);
101 static int sunkbd_disable(keyboard_t *kbd);
102 static int sunkbd_read(keyboard_t *kbd, int wait);
103 static int sunkbd_check(keyboard_t *kbd);
104 static u_int sunkbd_read_char(keyboard_t *kbd, int wait);
105 static int sunkbd_check_char(keyboard_t *kbd);
106 static int sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data);
107 static int sunkbd_lock(keyboard_t *kbd, int lock);
108 static void sunkbd_clear_state(keyboard_t *kbd);
109 static int sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len);
110 static int sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len);
111 static int sunkbd_poll_mode(keyboard_t *kbd, int on);
112 static void sunkbd_diag(keyboard_t *kbd, int level);
113
114 static void sunkbd_repeat(void *v);
115 #if defined(SUNKBD_EMULATE_ATKBD)
116 static int keycode2scancode(int keycode, int shift, int up);
117 #endif
118
119 static keyboard_switch_t sunkbdsw = {
120         sunkbd_probe,
121         sunkbd_init,
122         sunkbd_term,
123         sunkbd_intr,
124         sunkbd_test_if,
125         sunkbd_enable,
126         sunkbd_disable,
127         sunkbd_read,
128         sunkbd_check,
129         sunkbd_read_char,
130         sunkbd_check_char,
131         sunkbd_ioctl,
132         sunkbd_lock,
133         sunkbd_clear_state,
134         sunkbd_get_state,
135         sunkbd_set_state,
136         genkbd_get_fkeystr,
137         sunkbd_poll_mode,
138         sunkbd_diag
139 };
140
141 KEYBOARD_DRIVER(sunkbd, sunkbdsw, sunkbd_configure);
142
143 static struct sunkbd_softc sunkbd_softc;
144 static struct uart_devinfo uart_keyboard;
145
146 #if defined(SUNKBD_EMULATE_ATKBD)
147
148 #define SCAN_PRESS              0x000
149 #define SCAN_RELEASE            0x080
150 #define SCAN_PREFIX_E0          0x100
151 #define SCAN_PREFIX_E1          0x200
152 #define SCAN_PREFIX_CTL         0x400
153 #define SCAN_PREFIX_SHIFT       0x800
154 #define SCAN_PREFIX             (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 |      \
155                                 SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT)
156
157 #define NOTR    0x0     /* no translation */
158
159 static const uint8_t sunkbd_trtab[] = {
160         NOTR, 0x6d, 0x78, 0x6e, 0x79, 0x3b, 0x3c, 0x44, /* 0x00 - 0x07 */
161         0x3d, 0x57, 0x3e, 0x58, 0x3f, 0x5d, 0x40, NOTR, /* 0x08 - 0x0f */
162         0x41, 0x42, 0x43, 0x38, 0x5f, 0x68, 0x5c, 0x46, /* 0x10 - 0x17 */
163         0x61, 0x6f, 0x70, 0x64, 0x62, 0x01, 0x02, 0x03, /* 0x18 - 0x1f */
164         0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 0x20 - 0x27 */
165         0x0c, 0x0d, 0x29, 0x0e, 0x66, 0x77, 0x5b, 0x37, /* 0x28 - 0x2f */
166         0x7a, 0x71, 0x53, 0x74, 0x5e, 0x0f, 0x10, 0x11, /* 0x30 - 0x37 */
167         0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* 0x38 - 0x3f */
168         0x1a, 0x1b, 0x67, 0x6b, 0x47, 0x48, 0x49, 0x4a, /* 0x40 - 0x47 */
169         0x73, 0x72, 0x63, NOTR, 0x1d, 0x1e, 0x1f, 0x20, /* 0x48 - 0x4f */
170         0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* 0x50 - 0x57 */
171         0x2b, 0x1c, 0x59, 0x4b, 0x4c, 0x4d, 0x52, 0x75, /* 0x58 - 0x5f */
172         0x60, 0x76, 0x45, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x60 - 0x67 */
173         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, NOTR, /* 0x68 - 0x6f */
174         0x4f, 0x50, 0x51, NOTR, NOTR, NOTR, 0x6c, 0x3a, /* 0x70 - 0x77 */
175         0x69, 0x39, 0x6a, 0x65, 0x56, 0x4e, NOTR, NOTR  /* 0x78 - 0x7f */
176 };
177
178 #endif
179
180 static int
181 sunkbd_probe_keyboard(struct uart_devinfo *di)
182 {
183         int c, id, ltries, tries;
184
185         for (tries = 5; tries != 0; tries--) {
186                 uart_putc(di, SKBD_CMD_RESET);
187                 for (ltries = 1000; ltries != 0; ltries--) {
188                         if (uart_poll(di) == SKBD_RSP_RESET)
189                                 break;
190                         DELAY(1000);
191                 }
192                 if (ltries == 0)
193                         continue;
194                 id = -1;
195                 for (ltries = 1000; ltries != 0; ltries--) {
196                         switch (c = uart_poll(di)) {
197                         case -1:
198                                 break;
199                         case SKBD_RSP_IDLE:
200                                 return (id);
201                         default:
202                                 id = c;
203                         }
204                         DELAY(1000);
205                 }
206         }
207         return (-1);
208 }
209
210 static int sunkbd_attach(struct uart_softc *sc);
211 static void sunkbd_uart_intr(void *arg);
212
213 static int
214 sunkbd_configure(int flags)
215 {
216         struct sunkbd_softc *sc;
217
218         /*
219          * We are only prepared to be used for the high-level console
220          * when the keyboard is both configured and attached.
221          */
222         if (!(flags & KB_CONF_PROBE_ONLY)) {
223                 if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd))
224                         goto found;
225                 else
226                         return (0);
227         }
228
229         if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard))
230                 return (0);
231         if (uart_probe(&uart_keyboard))
232                 return (0);
233         uart_init(&uart_keyboard);
234
235         uart_keyboard.type = UART_DEV_KEYBOARD;
236         uart_keyboard.attach = sunkbd_attach;
237         uart_add_sysdev(&uart_keyboard);
238
239         if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4)
240                 return (0);
241
242         sc = &sunkbd_softc;
243         callout_init(&sc->sc_repeat_callout, 0);
244         sunkbd_clear_state(&sc->sc_kbd);
245
246 #if defined(SUNKBD_EMULATE_ATKBD)
247         kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
248         kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
249             sizeof(fkey_tab) / sizeof(fkey_tab[0]));
250 #else
251         kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0);
252         kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd,
253             &accentmap_sun_us_unix_kbd, fkey_tab,
254             sizeof(fkey_tab) / sizeof(fkey_tab[0]));
255 #endif
256         sc->sc_mode = K_XLATE;
257         kbd_register(&sc->sc_kbd);
258
259         sc->sc_sysdev = &uart_keyboard;
260
261  found:
262         /* Return number of found keyboards. */
263         return (1);
264 }
265
266 static int
267 sunkbd_attach(struct uart_softc *sc)
268 {
269
270         /*
271          * Don't attach if we didn't probe the keyboard. Note that
272          * the UART is still marked as a system device in that case.
273          */
274         if (sunkbd_softc.sc_sysdev == NULL) {
275                 device_printf(sc->sc_dev, "keyboard not present\n");
276                 return (0);
277         }
278
279         if (sc->sc_sysdev != NULL) {
280                 sunkbd_softc.sc_uart = sc;
281
282 #ifdef KBD_INSTALL_CDEV
283                 kbd_attach(&sunkbd_softc.sc_kbd);
284 #endif
285                 sunkbd_enable(&sunkbd_softc.sc_kbd);
286
287                 swi_add(&tty_intr_event, uart_driver_name, sunkbd_uart_intr,
288                     &sunkbd_softc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih);
289
290                 sc->sc_opened = 1;
291                 KBD_INIT_DONE(&sunkbd_softc.sc_kbd);
292         }
293
294         return (0);
295 }
296
297 static void
298 sunkbd_uart_intr(void *arg)
299 {
300         struct sunkbd_softc *sc = arg;
301         int pend;
302
303         if (sc->sc_uart->sc_leaving)
304                 return;
305
306         pend = atomic_readandclear_32(&sc->sc_uart->sc_ttypend);
307         if (!(pend & SER_INT_MASK))
308                 return;
309
310         if (pend & SER_INT_RXREADY) {
311                 if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
312                         sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
313                             KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
314                 }
315         }
316 }
317
318 static int
319 sunkbd_probe(int unit, void *arg, int flags)
320 {
321
322         TODO;
323         return (0);
324 }
325
326 static int
327 sunkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
328 {
329
330         TODO;
331         return (0);
332 }
333
334 static int
335 sunkbd_term(keyboard_t *kbd)
336 {
337
338         TODO;
339         return (0);
340 }
341
342 static int
343 sunkbd_intr(keyboard_t *kbd, void *arg)
344 {
345
346         TODO;
347         return (0);
348 }
349
350 static int
351 sunkbd_test_if(keyboard_t *kbd)
352 {
353
354         TODO;
355         return (0);
356 }
357
358 static int
359 sunkbd_enable(keyboard_t *kbd)
360 {
361
362         KBD_ACTIVATE(kbd);
363         return (0);
364 }
365
366 static int
367 sunkbd_disable(keyboard_t *kbd)
368 {
369
370         KBD_DEACTIVATE(kbd);
371         return (0);
372 }
373
374 static int
375 sunkbd_read(keyboard_t *kbd, int wait)
376 {
377
378         TODO;
379         return (0);
380 }
381
382 static int
383 sunkbd_check(keyboard_t *kbd)
384 {
385         struct sunkbd_softc *sc;
386
387         if (!KBD_IS_ACTIVE(kbd))
388                 return (FALSE);
389
390         sc = (struct sunkbd_softc *)kbd;
391
392 #if defined(SUNKBD_EMULATE_ATKBD)
393         if (sc->sc_buffered_char[0])
394                 return (TRUE);
395 #endif
396
397         if (sc->sc_repeating)
398                 return (TRUE);
399
400         if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart))
401                 return (TRUE);
402
403         if (sc->sc_polling != 0 && sc->sc_sysdev != NULL &&
404             uart_rxready(sc->sc_sysdev))
405                 return (TRUE);
406
407         return (FALSE);
408 }
409
410 static u_int
411 sunkbd_read_char(keyboard_t *kbd, int wait)
412 {
413         struct sunkbd_softc *sc;
414         int key, release, repeated, suncode;
415
416         sc = (struct sunkbd_softc *)kbd;
417
418 #if defined(SUNKBD_EMULATE_ATKBD)
419         if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) {
420                 key = sc->sc_buffered_char[0];
421                 if (key & SCAN_PREFIX) {
422                         sc->sc_buffered_char[0] = key & ~SCAN_PREFIX;
423                         return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
424                 } else {
425                         sc->sc_buffered_char[0] = sc->sc_buffered_char[1];
426                         sc->sc_buffered_char[1] = 0;
427                         return (key);
428                 }
429         }
430 #endif
431
432         repeated = 0;
433         if (sc->sc_repeating) {
434                 repeated = 1;
435                 sc->sc_repeating = 0;
436                 callout_reset(&sc->sc_repeat_callout, hz / 10,
437                     sunkbd_repeat, sc);
438                 suncode = sc->sc_repeat_key;
439                 goto process_code;
440         }
441
442         for (;;) {
443  next_code:
444                 if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) {
445                         key = sc->sc_composed_char;
446                         sc->sc_composed_char = 0;
447                         if (key > UCHAR_MAX)
448                                 return (ERRKEY);
449                         return (key);
450                 }
451
452                 if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) {
453                         suncode = uart_rx_get(sc->sc_uart);
454                 } else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) {
455                         if (wait)
456                                 suncode = uart_getc(sc->sc_sysdev);
457                         else if ((suncode = uart_poll(sc->sc_sysdev)) == -1)
458                                 return (NOKEY);
459                 } else {
460                         return (NOKEY);
461                 }
462
463                 switch (suncode) {
464                 case SKBD_RSP_IDLE:
465                         break;
466                 default:
467  process_code:
468                         ++kbd->kb_count;
469                         key = SKBD_KEY_CHAR(suncode);
470                         release = suncode & SKBD_KEY_RELEASE;
471                         if (!repeated) {
472                                 if (release == 0) {
473                                         callout_reset(&sc->sc_repeat_callout,
474                                             hz / 2, sunkbd_repeat, sc);
475                                         sc->sc_repeat_key = suncode;
476                                 } else if (sc->sc_repeat_key == key) {
477                                         callout_stop(&sc->sc_repeat_callout);
478                                         sc->sc_repeat_key = -1;
479                                 }
480                         }
481
482 #if defined(SUNKBD_EMULATE_ATKBD)
483                         key = sunkbd_trtab[key];
484                         if (key == NOTR)
485                                 return (NOKEY);
486
487                         if (!repeated) {
488                                 switch (key) {
489                                 case 0x1d:      /* ctrl */
490                                         if (release != 0)
491                                                 sc->sc_flags &= ~CTLS;
492                                         else
493                                                 sc->sc_flags |= CTLS;
494                                         break;
495                                 case 0x2a:      /* left shift */
496                                 case 0x36:      /* right shift */
497                                         if (release != 0)
498                                                 sc->sc_flags &= ~SHIFTS;
499                                         else
500                                                 sc->sc_flags |= SHIFTS;
501                                         break;
502                                 case 0x38:      /* alt */
503                                 case 0x5d:      /* altgr */
504                                         if (release != 0)
505                                                 sc->sc_flags &= ~ALTS;
506                                         else
507                                                 sc->sc_flags |= ALTS;
508                                         break;
509                                 }
510                         }
511                         if (sc->sc_mode == K_RAW) {
512                                 key = keycode2scancode(key, sc->sc_flags,
513                                     release);
514                                 if (key & SCAN_PREFIX) {
515                                         if (key & SCAN_PREFIX_CTL) {
516                                                 sc->sc_buffered_char[0] =
517                                                     0x1d | (key & SCAN_RELEASE);
518                                                 sc->sc_buffered_char[1] =
519                                                     key & ~SCAN_PREFIX;
520                                         } else if (key & SCAN_PREFIX_SHIFT) {
521                                                 sc->sc_buffered_char[0] =
522                                                     0x2a | (key & SCAN_RELEASE);
523                                                 sc->sc_buffered_char[1] =
524                                                     key & ~SCAN_PREFIX_SHIFT;
525                                         } else {
526                                                 sc->sc_buffered_char[0] =
527                                                     key & ~SCAN_PREFIX;
528                                                 sc->sc_buffered_char[1] = 0;
529                                         }
530                                         return ((key & SCAN_PREFIX_E0) ?
531                                             0xe0 : 0xe1);
532                                 }
533                                 return (key);
534                         }
535                         switch (key) {
536                         case 0x5c:      /* print screen */
537                                 if (sc->sc_flags & ALTS)
538                                         key = 0x54;     /* sysrq */
539                                 break;
540                         case 0x68:      /* pause/break */
541                                 if (sc->sc_flags & CTLS)
542                                         key = 0x6c;     /* break */
543                                 break;
544                         }
545
546                         if (sc->sc_mode == K_CODE)
547                                 return (key | release);
548 #else
549                         if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE)
550                                 return (suncode);
551 #endif
552
553 #if defined(SUNKBD_EMULATE_ATKBD)
554                         if (key == 0x38) {      /* left alt (KP compose key) */
555 #else
556                         if (key == 0x13) {      /* left alt (KP compose key) */
557 #endif
558                                 if (release != 0) {
559                                         if (sc->sc_flags & KPCOMPOSE) {
560                                                 sc->sc_flags &= ~KPCOMPOSE;
561                                                 if (sc->sc_composed_char >
562                                                     UCHAR_MAX)
563                                                         sc->sc_composed_char =
564                                                             0;
565                                         }
566                                 } else {
567                                         if (!(sc->sc_flags & KPCOMPOSE)) {
568                                                 sc->sc_flags |= KPCOMPOSE;
569                                                 sc->sc_composed_char = 0;
570                                         }
571                                 }
572                         }
573                         if (sc->sc_flags & KPCOMPOSE) {
574                                 switch (suncode) {
575                                 case 0x44:                      /* KP 7 */
576                                 case 0x45:                      /* KP 8 */
577                                 case 0x46:                      /* KP 9 */
578                                         sc->sc_composed_char *= 10;
579                                         sc->sc_composed_char += suncode - 0x3d;
580                                         if (sc->sc_composed_char > UCHAR_MAX)
581                                                 return (ERRKEY);
582                                         goto next_code;
583                                 case 0x5b:                      /* KP 4 */
584                                 case 0x5c:                      /* KP 5 */
585                                 case 0x5d:                      /* KP 6 */
586                                         sc->sc_composed_char *= 10;
587                                         sc->sc_composed_char += suncode - 0x58;
588                                         if (sc->sc_composed_char > UCHAR_MAX)
589                                                 return (ERRKEY);
590                                         goto next_code;
591                                 case 0x70:                      /* KP 1 */
592                                 case 0x71:                      /* KP 2 */
593                                 case 0x72:                      /* KP 3 */
594                                         sc->sc_composed_char *= 10;
595                                         sc->sc_composed_char += suncode - 0x6f;
596                                         if (sc->sc_composed_char > UCHAR_MAX)
597                                                 return (ERRKEY);
598                                         goto next_code;
599                                 case 0x5e:                      /* KP 0 */
600                                         sc->sc_composed_char *= 10;
601                                         if (sc->sc_composed_char > UCHAR_MAX)
602                                                 return (ERRKEY);
603                                         goto next_code;
604
605                                 case 0x44 | SKBD_KEY_RELEASE:   /* KP 7 */
606                                 case 0x45 | SKBD_KEY_RELEASE:   /* KP 8 */
607                                 case 0x46 | SKBD_KEY_RELEASE:   /* KP 9 */
608                                 case 0x5b | SKBD_KEY_RELEASE:   /* KP 4 */
609                                 case 0x5c | SKBD_KEY_RELEASE:   /* KP 5 */
610                                 case 0x5d | SKBD_KEY_RELEASE:   /* KP 6 */
611                                 case 0x70 | SKBD_KEY_RELEASE:   /* KP 1 */
612                                 case 0x71 | SKBD_KEY_RELEASE:   /* KP 2 */
613                                 case 0x72 | SKBD_KEY_RELEASE:   /* KP 3 */
614                                 case 0x5e | SKBD_KEY_RELEASE:   /* KP 0 */
615                                         goto next_code;
616                                 default:
617                                         if (sc->sc_composed_char > 0) {
618                                                 sc->sc_flags &= ~KPCOMPOSE;
619                                                 sc->sc_composed_char = 0;
620                                                 return (ERRKEY);
621                                         }
622                                 }
623                         }
624
625                         key = genkbd_keyaction(kbd, key, release,
626                             &sc->sc_state, &sc->sc_accents);
627                         if (key != NOKEY || repeated)
628                                 return (key);
629                 }
630         }
631         return (0);
632 }
633
634 static int
635 sunkbd_check_char(keyboard_t *kbd)
636 {
637         struct sunkbd_softc *sc;
638
639         if (!KBD_IS_ACTIVE(kbd))
640                 return (FALSE);
641
642         sc = (struct sunkbd_softc *)kbd;
643         if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0))
644                 return (TRUE);
645
646         return (sunkbd_check(kbd));
647 }
648
649 static int
650 sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
651 {
652         struct sunkbd_softc *sc;
653         int c, error;
654 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
655         int ival;
656 #endif
657
658         sc = (struct sunkbd_softc *)kbd;
659         error = 0;
660         switch (cmd) {
661         case KDGKBMODE:
662                 *(int *)data = sc->sc_mode;
663                 break;
664 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
665         case _IO('K', 7):
666                 ival = IOCPARM_IVAL(data);
667                 data = (caddr_t)&ival;
668                 /* FALLTHROUGH */
669 #endif
670         case KDSKBMODE:
671                 switch (*(int *)data) {
672                 case K_XLATE:
673                         if (sc->sc_mode != K_XLATE) {
674                                 /* make lock key state and LED state match */
675                                 sc->sc_state &= ~LOCK_MASK;
676                                 sc->sc_state |= KBD_LED_VAL(kbd);
677                         }
678                         /* FALLTHROUGH */
679                 case K_RAW:
680                 case K_CODE:
681                         if (sc->sc_mode != *(int *)data) {
682                                 sunkbd_clear_state(kbd);
683                                 sc->sc_mode = *(int *)data;
684                         }
685                         break;
686                 default:
687                         error = EINVAL;
688                         break;
689                 }
690                 break;
691         case KDGETLED:
692                 *(int *)data = KBD_LED_VAL(kbd);
693                 break;
694 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
695         case _IO('K', 66):
696                 ival = IOCPARM_IVAL(data);
697                 data = (caddr_t)&ival;
698                 /* FALLTHROUGH */
699 #endif
700         case KDSETLED:
701                 if (*(int *)data & ~LOCK_MASK) {
702                         error = EINVAL;
703                         break;
704                 }
705                 if (sc->sc_sysdev == NULL)
706                         break;
707                 c = 0;
708                 if (*(int *)data & CLKED)
709                         c |= SKBD_LED_CAPSLOCK;
710                 if (*(int *)data & NLKED)
711                         c |= SKBD_LED_NUMLOCK;
712                 if (*(int *)data & SLKED)
713                         c |= SKBD_LED_SCROLLLOCK;
714                 uart_lock(sc->sc_sysdev->hwmtx);
715                 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
716                 sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c);
717                 uart_unlock(sc->sc_sysdev->hwmtx);
718                 KBD_LED_VAL(kbd) = *(int *)data;
719                 break;
720         case KDGKBSTATE:
721                 *(int *)data = sc->sc_state & LOCK_MASK;
722                 break;
723 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
724         case _IO('K', 20):
725                 ival = IOCPARM_IVAL(data);
726                 data = (caddr_t)&ival;
727                 /* FALLTHROUGH */
728 #endif
729         case KDSKBSTATE:
730                 if (*(int *)data & ~LOCK_MASK) {
731                         error = EINVAL;
732                         break;
733                 }
734                 sc->sc_state &= ~LOCK_MASK;
735                 sc->sc_state |= *(int *)data;
736                 /* set LEDs and quit */
737                 return (sunkbd_ioctl(kbd, KDSETLED, data));
738         case KDSETREPEAT:
739         case KDSETRAD:
740                 break;
741         case PIO_KEYMAP:
742         case OPIO_KEYMAP:
743         case PIO_KEYMAPENT:
744         case PIO_DEADKEYMAP:
745         default:
746                 return (genkbd_commonioctl(kbd, cmd, data));
747         }
748         return (error);
749 }
750
751 static int
752 sunkbd_lock(keyboard_t *kbd, int lock)
753 {
754
755         TODO;
756         return (0);
757 }
758
759 static void
760 sunkbd_clear_state(keyboard_t *kbd)
761 {
762         struct sunkbd_softc *sc;
763
764         sc = (struct sunkbd_softc *)kbd;
765         sc->sc_repeat_key = -1;
766         sc->sc_accents = 0;
767         sc->sc_composed_char = 0;
768         sc->sc_flags = 0;
769         sc->sc_polling = 0;
770         sc->sc_repeating = 0;
771         sc->sc_state &= LOCK_MASK;      /* Preserve locking key state. */
772
773 #if defined(SUNKBD_EMULATE_ATKBD)
774         sc->sc_buffered_char[0] = 0;
775         sc->sc_buffered_char[1] = 0;
776 #endif
777 }
778
779 static int
780 sunkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
781 {
782
783         TODO;
784         return (0);
785 }
786
787 static int
788 sunkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
789 {
790
791         TODO;
792         return (0);
793 }
794
795 static int
796 sunkbd_poll_mode(keyboard_t *kbd, int on)
797 {
798         struct sunkbd_softc *sc;
799
800         sc = (struct sunkbd_softc *)kbd;
801         if (on)
802                 sc->sc_polling++;
803         else
804                 sc->sc_polling--;
805         return (0);
806 }
807
808 static void
809 sunkbd_diag(keyboard_t *kbd, int level)
810 {
811
812         TODO;
813 }
814
815 static void
816 sunkbd_repeat(void *v)
817 {
818         struct sunkbd_softc *sc = v;
819
820         if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
821                 if (sc->sc_repeat_key != -1) {
822                         sc->sc_repeating = 1;
823                         sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
824                             KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
825                 }
826         }
827 }
828
829 #if defined(SUNKBD_EMULATE_ATKBD)
830 static int
831 keycode2scancode(int keycode, int shift, int up)
832 {
833         static const int scan[] = {
834                 /* KP enter, right ctrl, KP divide */
835                 0x1c , 0x1d , 0x35 ,
836                 /* print screen */
837                 0x37 | SCAN_PREFIX_SHIFT,
838                 /* right alt, home, up, page up, left, right, end */
839                 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f,
840                 /* down, page down, insert, delete */
841                 0x50, 0x51, 0x52, 0x53,
842                 /* pause/break (see also below) */
843                 0x46,
844                 /*
845                  * MS: left window, right window, menu
846                  * also Sun: left meta, right meta, compose
847                  */
848                 0x5b, 0x5c, 0x5d,
849                 /* Sun type 6 USB */
850                 /* help, stop, again, props, undo, front, copy */
851                 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
852                 /* open, paste, find, cut, audiomute, audiolower, audioraise */
853                 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e,
854                 /* power */
855                 0x20
856         };
857         int scancode;
858
859         scancode = keycode;
860         if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0])))
861         scancode = scan[keycode - 89] | SCAN_PREFIX_E0;
862         /* pause/break */
863         if ((keycode == 104) && !(shift & CTLS))
864                 scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL;
865         if (shift & SHIFTS)
866                 scancode &= ~SCAN_PREFIX_SHIFT;
867         return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS));
868 }
869 #endif