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