xref: /illumos-gate/usr/src/cmd/bhyve/ps2kbd.c (revision b0de25cb)
1bf21cd93STycho Nightingale /*-
24c87aefeSPatrick Mooney  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
34c87aefeSPatrick Mooney  *
4bf21cd93STycho Nightingale  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5bf21cd93STycho Nightingale  * Copyright (c) 2015 Nahanni Systems Inc.
6bf21cd93STycho Nightingale  * All rights reserved.
7bf21cd93STycho Nightingale  *
8bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
9bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
10bf21cd93STycho Nightingale  * are met:
11bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
12bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
13bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
14bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
15bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
16bf21cd93STycho Nightingale  *
17bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27bf21cd93STycho Nightingale  * SUCH DAMAGE.
28bf21cd93STycho Nightingale  */
29bf21cd93STycho Nightingale 
30bf21cd93STycho Nightingale #include <sys/cdefs.h>
31bf21cd93STycho Nightingale __FBSDID("$FreeBSD$");
32bf21cd93STycho Nightingale 
33bf21cd93STycho Nightingale #include <sys/types.h>
34bf21cd93STycho Nightingale 
35bf21cd93STycho Nightingale #include <assert.h>
36bf21cd93STycho Nightingale #include <stdbool.h>
37bf21cd93STycho Nightingale #include <stdio.h>
38bf21cd93STycho Nightingale #include <stdlib.h>
39bf21cd93STycho Nightingale #include <strings.h>
40bf21cd93STycho Nightingale #include <pthread.h>
41bf21cd93STycho Nightingale #include <pthread_np.h>
42bf21cd93STycho Nightingale 
43bf21cd93STycho Nightingale #include "atkbdc.h"
44154972afSPatrick Mooney #include "debug.h"
45bf21cd93STycho Nightingale #include "console.h"
46bf21cd93STycho Nightingale 
47bf21cd93STycho Nightingale /* keyboard device commands */
48bf21cd93STycho Nightingale #define	PS2KC_RESET_DEV		0xff
49bf21cd93STycho Nightingale #define	PS2KC_DISABLE		0xf5
50bf21cd93STycho Nightingale #define	PS2KC_ENABLE		0xf4
51bf21cd93STycho Nightingale #define	PS2KC_SET_TYPEMATIC	0xf3
52bf21cd93STycho Nightingale #define	PS2KC_SEND_DEV_ID	0xf2
53bf21cd93STycho Nightingale #define	PS2KC_SET_SCANCODE_SET	0xf0
54bf21cd93STycho Nightingale #define	PS2KC_ECHO		0xee
55bf21cd93STycho Nightingale #define	PS2KC_SET_LEDS		0xed
56bf21cd93STycho Nightingale 
57bf21cd93STycho Nightingale #define	PS2KC_BAT_SUCCESS	0xaa
58bf21cd93STycho Nightingale #define	PS2KC_ACK		0xfa
59bf21cd93STycho Nightingale 
60bf21cd93STycho Nightingale #define	PS2KBD_FIFOSZ		16
61bf21cd93STycho Nightingale 
62bf21cd93STycho Nightingale struct fifo {
63bf21cd93STycho Nightingale 	uint8_t	buf[PS2KBD_FIFOSZ];
64bf21cd93STycho Nightingale 	int	rindex;		/* index to read from */
65bf21cd93STycho Nightingale 	int	windex;		/* index to write to */
66bf21cd93STycho Nightingale 	int	num;		/* number of bytes in the fifo */
67bf21cd93STycho Nightingale 	int	size;		/* size of the fifo */
68bf21cd93STycho Nightingale };
69bf21cd93STycho Nightingale 
70bf21cd93STycho Nightingale struct ps2kbd_softc {
71bf21cd93STycho Nightingale 	struct atkbdc_softc	*atkbdc_sc;
72bf21cd93STycho Nightingale 	pthread_mutex_t		mtx;
73bf21cd93STycho Nightingale 
74bf21cd93STycho Nightingale 	bool			enabled;
75bf21cd93STycho Nightingale 	struct fifo		fifo;
76bf21cd93STycho Nightingale 
77bf21cd93STycho Nightingale 	uint8_t			curcmd;	/* current command for next byte */
78bf21cd93STycho Nightingale };
79bf21cd93STycho Nightingale 
804c87aefeSPatrick Mooney #define SCANCODE_E0_PREFIX 1
814c87aefeSPatrick Mooney struct extended_translation {
824c87aefeSPatrick Mooney 	uint32_t keysym;
834c87aefeSPatrick Mooney 	uint8_t scancode;
844c87aefeSPatrick Mooney 	int flags;
854c87aefeSPatrick Mooney };
864c87aefeSPatrick Mooney 
874c87aefeSPatrick Mooney /*
884c87aefeSPatrick Mooney  * FIXME: Pause/break and Print Screen/SysRq require special handling.
894c87aefeSPatrick Mooney  */
904c87aefeSPatrick Mooney static const struct extended_translation extended_translations[] = {
914c87aefeSPatrick Mooney 		{0xff08, 0x66},		/* Back space */
924c87aefeSPatrick Mooney 		{0xff09, 0x0d},		/* Tab */
934c87aefeSPatrick Mooney 		{0xff0d, 0x5a},		/* Return */
944c87aefeSPatrick Mooney 		{0xff1b, 0x76},		/* Escape */
954c87aefeSPatrick Mooney 		{0xff50, 0x6c, SCANCODE_E0_PREFIX}, 	/* Home */
964c87aefeSPatrick Mooney 		{0xff51, 0x6b, SCANCODE_E0_PREFIX}, 	/* Left arrow */
974c87aefeSPatrick Mooney 		{0xff52, 0x75, SCANCODE_E0_PREFIX}, 	/* Up arrow */
984c87aefeSPatrick Mooney 		{0xff53, 0x74, SCANCODE_E0_PREFIX}, 	/* Right arrow */
994c87aefeSPatrick Mooney 		{0xff54, 0x72, SCANCODE_E0_PREFIX}, 	/* Down arrow */
1004c87aefeSPatrick Mooney 		{0xff55, 0x7d, SCANCODE_E0_PREFIX}, 	/* PgUp */
1014c87aefeSPatrick Mooney 		{0xff56, 0x7a, SCANCODE_E0_PREFIX}, 	/* PgDown */
1024c87aefeSPatrick Mooney 		{0xff57, 0x69, SCANCODE_E0_PREFIX}, 	/* End */
1034c87aefeSPatrick Mooney 		{0xff63, 0x70, SCANCODE_E0_PREFIX}, 	/* Ins */
1044c87aefeSPatrick Mooney 		{0xff8d, 0x5a, SCANCODE_E0_PREFIX}, 	/* Keypad Enter */
1054c87aefeSPatrick Mooney 		{0xffe1, 0x12},		/* Left shift */
1064c87aefeSPatrick Mooney 		{0xffe2, 0x59},		/* Right shift */
1074c87aefeSPatrick Mooney 		{0xffe3, 0x14},		/* Left control */
1084c87aefeSPatrick Mooney 		{0xffe4, 0x14, SCANCODE_E0_PREFIX}, 	/* Right control */
1094c87aefeSPatrick Mooney 		/* {0xffe7, XXX}, Left meta */
1104c87aefeSPatrick Mooney 		/* {0xffe8, XXX}, Right meta */
1114c87aefeSPatrick Mooney 		{0xffe9, 0x11},		/* Left alt */
1124c87aefeSPatrick Mooney 		{0xfe03, 0x11, SCANCODE_E0_PREFIX}, 	/* AltGr */
1134c87aefeSPatrick Mooney 		{0xffea, 0x11, SCANCODE_E0_PREFIX}, 	/* Right alt */
1144c87aefeSPatrick Mooney 		{0xffeb, 0x1f, SCANCODE_E0_PREFIX}, 	/* Left Windows */
1154c87aefeSPatrick Mooney 		{0xffec, 0x27, SCANCODE_E0_PREFIX}, 	/* Right Windows */
1164c87aefeSPatrick Mooney 		{0xffbe, 0x05},		/* F1 */
1174c87aefeSPatrick Mooney 		{0xffbf, 0x06},		/* F2 */
1184c87aefeSPatrick Mooney 		{0xffc0, 0x04},		/* F3 */
1194c87aefeSPatrick Mooney 		{0xffc1, 0x0c},		/* F4 */
1204c87aefeSPatrick Mooney 		{0xffc2, 0x03},		/* F5 */
1214c87aefeSPatrick Mooney 		{0xffc3, 0x0b},		/* F6 */
1224c87aefeSPatrick Mooney 		{0xffc4, 0x83},		/* F7 */
1234c87aefeSPatrick Mooney 		{0xffc5, 0x0a},		/* F8 */
1244c87aefeSPatrick Mooney 		{0xffc6, 0x01},		/* F9 */
1254c87aefeSPatrick Mooney 		{0xffc7, 0x09},		/* F10 */
1264c87aefeSPatrick Mooney 		{0xffc8, 0x78},		/* F11 */
1274c87aefeSPatrick Mooney 		{0xffc9, 0x07},		/* F12 */
1284c87aefeSPatrick Mooney 		{0xffff, 0x71, SCANCODE_E0_PREFIX},	/* Del */
1294c87aefeSPatrick Mooney 		{0xff14, 0x7e},		/* ScrollLock */
1304c87aefeSPatrick Mooney 		/* NumLock and Keypads*/
1314c87aefeSPatrick Mooney 		{0xff7f, 0x77}, 	/* NumLock */
1324c87aefeSPatrick Mooney 		{0xffaf, 0x4a, SCANCODE_E0_PREFIX}, 	/* Keypad slash */
1334c87aefeSPatrick Mooney 		{0xffaa, 0x7c}, 	/* Keypad asterisk */
1344c87aefeSPatrick Mooney 		{0xffad, 0x7b}, 	/* Keypad minus */
1354c87aefeSPatrick Mooney 		{0xffab, 0x79}, 	/* Keypad plus */
1364c87aefeSPatrick Mooney 		{0xffb7, 0x6c}, 	/* Keypad 7 */
1374c87aefeSPatrick Mooney 		{0xff95, 0x6c}, 	/* Keypad home */
1384c87aefeSPatrick Mooney 		{0xffb8, 0x75}, 	/* Keypad 8 */
1394c87aefeSPatrick Mooney 		{0xff97, 0x75}, 	/* Keypad up arrow */
1404c87aefeSPatrick Mooney 		{0xffb9, 0x7d}, 	/* Keypad 9 */
1414c87aefeSPatrick Mooney 		{0xff9a, 0x7d}, 	/* Keypad PgUp */
1424c87aefeSPatrick Mooney 		{0xffb4, 0x6b}, 	/* Keypad 4 */
1434c87aefeSPatrick Mooney 		{0xff96, 0x6b}, 	/* Keypad left arrow */
1444c87aefeSPatrick Mooney 		{0xffb5, 0x73}, 	/* Keypad 5 */
1454c87aefeSPatrick Mooney 		{0xff9d, 0x73}, 	/* Keypad empty */
1464c87aefeSPatrick Mooney 		{0xffb6, 0x74}, 	/* Keypad 6 */
1474c87aefeSPatrick Mooney 		{0xff98, 0x74}, 	/* Keypad right arrow */
1484c87aefeSPatrick Mooney 		{0xffb1, 0x69}, 	/* Keypad 1 */
1494c87aefeSPatrick Mooney 		{0xff9c, 0x69}, 	/* Keypad end */
1504c87aefeSPatrick Mooney 		{0xffb2, 0x72}, 	/* Keypad 2 */
1514c87aefeSPatrick Mooney 		{0xff99, 0x72}, 	/* Keypad down arrow */
1524c87aefeSPatrick Mooney 		{0xffb3, 0x7a}, 	/* Keypad 3 */
1534c87aefeSPatrick Mooney 		{0xff9b, 0x7a}, 	/* Keypad PgDown */
1544c87aefeSPatrick Mooney 		{0xffb0, 0x70}, 	/* Keypad 0 */
1554c87aefeSPatrick Mooney 		{0xff9e, 0x70}, 	/* Keypad ins */
1564c87aefeSPatrick Mooney 		{0xffae, 0x71}, 	/* Keypad . */
1574c87aefeSPatrick Mooney 		{0xff9f, 0x71}, 	/* Keypad del */
1584c87aefeSPatrick Mooney 		{0, 0, 0} 		/* Terminator */
1594c87aefeSPatrick Mooney };
1604c87aefeSPatrick Mooney 
1614c87aefeSPatrick Mooney /* ASCII to type 2 scancode lookup table */
1624c87aefeSPatrick Mooney static const uint8_t ascii_translations[128] = {
1634c87aefeSPatrick Mooney 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1644c87aefeSPatrick Mooney 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654c87aefeSPatrick Mooney 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664c87aefeSPatrick Mooney 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1674c87aefeSPatrick Mooney 		0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52,
1684c87aefeSPatrick Mooney 		0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a,
1694c87aefeSPatrick Mooney 		0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d,
1704c87aefeSPatrick Mooney 		0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a,
1714c87aefeSPatrick Mooney 		0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
1724c87aefeSPatrick Mooney 		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
1734c87aefeSPatrick Mooney 		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
1744c87aefeSPatrick Mooney 		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e,
1754c87aefeSPatrick Mooney 		0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
1764c87aefeSPatrick Mooney 		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
1774c87aefeSPatrick Mooney 		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
1784c87aefeSPatrick Mooney 		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
1794c87aefeSPatrick Mooney };
1804c87aefeSPatrick Mooney 
181*b0de25cbSAndy Fiddaman /* ScanCode set1 to set2 lookup table */
182*b0de25cbSAndy Fiddaman const uint8_t keyset1to2_translations[128] = {
183*b0de25cbSAndy Fiddaman 		   0, 0x76, 0x16, 0x1E, 0x26, 0x25, 0x2e, 0x36,
184*b0de25cbSAndy Fiddaman 		0x3d, 0x3e, 0x46, 0x45, 0x4e, 0x55, 0x66, 0x0d,
185*b0de25cbSAndy Fiddaman 		0x15, 0x1d, 0x24, 0x2d, 0x2c, 0x35, 0x3c, 0x43,
186*b0de25cbSAndy Fiddaman 		0x44, 0x4d, 0x54, 0x5b, 0x5a, 0x14, 0x1c, 0x1b,
187*b0de25cbSAndy Fiddaman 		0x23, 0x2b, 0x34, 0x33, 0x3b, 0x42, 0x4b, 0x4c,
188*b0de25cbSAndy Fiddaman 		0x52, 0x0e, 0x12, 0x5d, 0x1a, 0x22, 0x21, 0x2a,
189*b0de25cbSAndy Fiddaman 		0x32, 0x31, 0x3a, 0x41, 0x49, 0x4a, 0x59, 0x7c,
190*b0de25cbSAndy Fiddaman 		0x11, 0x29, 0x58, 0x05, 0x06, 0x04, 0x0c, 0x03,
191*b0de25cbSAndy Fiddaman 		0x0b, 0x83, 0x0a, 0x01, 0x09, 0x77, 0x7e, 0x6c,
192*b0de25cbSAndy Fiddaman 		0x75, 0x7d, 0x7b, 0x6b, 0x73, 0x74, 0x79, 0x69,
193*b0de25cbSAndy Fiddaman 		0x72, 0x7a, 0x70, 0x71, 0x84, 0x60, 0x61, 0x78,
194*b0de25cbSAndy Fiddaman 		0x07, 0x0f, 0x17, 0x1f, 0x27, 0x2f, 0x37, 0x3f,
195*b0de25cbSAndy Fiddaman 		0x47, 0x4f, 0x56, 0x5e, 0x08, 0x10, 0x18, 0x20,
196*b0de25cbSAndy Fiddaman 		0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x57, 0x6f,
197*b0de25cbSAndy Fiddaman 		0x13, 0x19, 0x39, 0x51, 0x53, 0x5c, 0x5f, 0x62,
198*b0de25cbSAndy Fiddaman 		0x63, 0x64, 0x65, 0x67, 0x68, 0x6a, 0x6d, 0x6e,
199*b0de25cbSAndy Fiddaman };
200*b0de25cbSAndy Fiddaman 
201bf21cd93STycho Nightingale static void
202bf21cd93STycho Nightingale fifo_init(struct ps2kbd_softc *sc)
203bf21cd93STycho Nightingale {
204bf21cd93STycho Nightingale 	struct fifo *fifo;
205bf21cd93STycho Nightingale 
206bf21cd93STycho Nightingale 	fifo = &sc->fifo;
207bf21cd93STycho Nightingale 	fifo->size = sizeof(((struct fifo *)0)->buf);
208bf21cd93STycho Nightingale }
209bf21cd93STycho Nightingale 
210bf21cd93STycho Nightingale static void
211bf21cd93STycho Nightingale fifo_reset(struct ps2kbd_softc *sc)
212bf21cd93STycho Nightingale {
213bf21cd93STycho Nightingale 	struct fifo *fifo;
214bf21cd93STycho Nightingale 
215bf21cd93STycho Nightingale 	fifo = &sc->fifo;
216bf21cd93STycho Nightingale 	bzero(fifo, sizeof(struct fifo));
217bf21cd93STycho Nightingale 	fifo->size = sizeof(((struct fifo *)0)->buf);
218bf21cd93STycho Nightingale }
219bf21cd93STycho Nightingale 
220bf21cd93STycho Nightingale static void
221bf21cd93STycho Nightingale fifo_put(struct ps2kbd_softc *sc, uint8_t val)
222bf21cd93STycho Nightingale {
223bf21cd93STycho Nightingale 	struct fifo *fifo;
224bf21cd93STycho Nightingale 
225bf21cd93STycho Nightingale 	fifo = &sc->fifo;
226bf21cd93STycho Nightingale 	if (fifo->num < fifo->size) {
227bf21cd93STycho Nightingale 		fifo->buf[fifo->windex] = val;
228bf21cd93STycho Nightingale 		fifo->windex = (fifo->windex + 1) % fifo->size;
229bf21cd93STycho Nightingale 		fifo->num++;
230bf21cd93STycho Nightingale 	}
231bf21cd93STycho Nightingale }
232bf21cd93STycho Nightingale 
233bf21cd93STycho Nightingale static int
234bf21cd93STycho Nightingale fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
235bf21cd93STycho Nightingale {
236bf21cd93STycho Nightingale 	struct fifo *fifo;
237bf21cd93STycho Nightingale 
238bf21cd93STycho Nightingale 	fifo = &sc->fifo;
239bf21cd93STycho Nightingale 	if (fifo->num > 0) {
240bf21cd93STycho Nightingale 		*val = fifo->buf[fifo->rindex];
241bf21cd93STycho Nightingale 		fifo->rindex = (fifo->rindex + 1) % fifo->size;
242bf21cd93STycho Nightingale 		fifo->num--;
243bf21cd93STycho Nightingale 		return (0);
244bf21cd93STycho Nightingale 	}
245bf21cd93STycho Nightingale 
246bf21cd93STycho Nightingale 	return (-1);
247bf21cd93STycho Nightingale }
248bf21cd93STycho Nightingale 
249bf21cd93STycho Nightingale int
250bf21cd93STycho Nightingale ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
251bf21cd93STycho Nightingale {
252bf21cd93STycho Nightingale 	int retval;
253bf21cd93STycho Nightingale 
254bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
255bf21cd93STycho Nightingale 	retval = fifo_get(sc, val);
256bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
257bf21cd93STycho Nightingale 
258bf21cd93STycho Nightingale 	return (retval);
259bf21cd93STycho Nightingale }
260bf21cd93STycho Nightingale 
261bf21cd93STycho Nightingale void
262bf21cd93STycho Nightingale ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
263bf21cd93STycho Nightingale {
264bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
265bf21cd93STycho Nightingale 	if (sc->curcmd) {
266bf21cd93STycho Nightingale 		switch (sc->curcmd) {
267bf21cd93STycho Nightingale 		case PS2KC_SET_TYPEMATIC:
268bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
269bf21cd93STycho Nightingale 			break;
270bf21cd93STycho Nightingale 		case PS2KC_SET_SCANCODE_SET:
271bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
272bf21cd93STycho Nightingale 			break;
273bf21cd93STycho Nightingale 		case PS2KC_SET_LEDS:
274bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
275bf21cd93STycho Nightingale 			break;
276bf21cd93STycho Nightingale 		default:
277154972afSPatrick Mooney 			EPRINTLN("Unhandled ps2 keyboard current "
278154972afSPatrick Mooney 			    "command byte 0x%02x", val);
279bf21cd93STycho Nightingale 			break;
280bf21cd93STycho Nightingale 		}
281bf21cd93STycho Nightingale 		sc->curcmd = 0;
282bf21cd93STycho Nightingale 	} else {
283bf21cd93STycho Nightingale 		switch (val) {
2844c87aefeSPatrick Mooney 		case 0x00:
2854c87aefeSPatrick Mooney 			fifo_put(sc, PS2KC_ACK);
2864c87aefeSPatrick Mooney 			break;
287bf21cd93STycho Nightingale 		case PS2KC_RESET_DEV:
288bf21cd93STycho Nightingale 			fifo_reset(sc);
289bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
290bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_BAT_SUCCESS);
291bf21cd93STycho Nightingale 			break;
292bf21cd93STycho Nightingale 		case PS2KC_DISABLE:
293bf21cd93STycho Nightingale 			sc->enabled = false;
294bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
295bf21cd93STycho Nightingale 			break;
296bf21cd93STycho Nightingale 		case PS2KC_ENABLE:
297bf21cd93STycho Nightingale 			sc->enabled = true;
298bf21cd93STycho Nightingale 			fifo_reset(sc);
299bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
300bf21cd93STycho Nightingale 			break;
301bf21cd93STycho Nightingale 		case PS2KC_SET_TYPEMATIC:
302bf21cd93STycho Nightingale 			sc->curcmd = val;
303bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
304bf21cd93STycho Nightingale 			break;
305bf21cd93STycho Nightingale 		case PS2KC_SEND_DEV_ID:
306bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
307bf21cd93STycho Nightingale 			fifo_put(sc, 0xab);
308bf21cd93STycho Nightingale 			fifo_put(sc, 0x83);
309bf21cd93STycho Nightingale 			break;
310bf21cd93STycho Nightingale 		case PS2KC_SET_SCANCODE_SET:
311bf21cd93STycho Nightingale 			sc->curcmd = val;
312bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
313bf21cd93STycho Nightingale 			break;
314bf21cd93STycho Nightingale 		case PS2KC_ECHO:
315bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ECHO);
316bf21cd93STycho Nightingale 			break;
317bf21cd93STycho Nightingale 		case PS2KC_SET_LEDS:
318bf21cd93STycho Nightingale 			sc->curcmd = val;
319bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
320bf21cd93STycho Nightingale 			break;
321bf21cd93STycho Nightingale 		default:
322154972afSPatrick Mooney 			EPRINTLN("Unhandled ps2 keyboard command "
323154972afSPatrick Mooney 			    "0x%02x", val);
324bf21cd93STycho Nightingale 			break;
325bf21cd93STycho Nightingale 		}
326bf21cd93STycho Nightingale 	}
327bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
328bf21cd93STycho Nightingale }
329bf21cd93STycho Nightingale 
330bf21cd93STycho Nightingale /*
331bf21cd93STycho Nightingale  * Translate keysym to type 2 scancode and insert into keyboard buffer.
332bf21cd93STycho Nightingale  */
333bf21cd93STycho Nightingale static void
334bf21cd93STycho Nightingale ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
335*b0de25cbSAndy Fiddaman     int down, uint32_t keysym, uint32_t keycode)
336bf21cd93STycho Nightingale {
337bf21cd93STycho Nightingale 	assert(pthread_mutex_isowned_np(&sc->mtx));
3384c87aefeSPatrick Mooney 	int e0_prefix, found;
3394c87aefeSPatrick Mooney 	uint8_t code;
3404c87aefeSPatrick Mooney 	const struct extended_translation *trans;
3414c87aefeSPatrick Mooney 
342*b0de25cbSAndy Fiddaman 	if (keycode) {
343*b0de25cbSAndy Fiddaman 		code =  keyset1to2_translations[(uint8_t)(keycode & 0x7f)];
344*b0de25cbSAndy Fiddaman 		e0_prefix = ((keycode & 0x80) ?  SCANCODE_E0_PREFIX : 0);
3454c87aefeSPatrick Mooney 		found = 1;
3464c87aefeSPatrick Mooney 	} else {
347*b0de25cbSAndy Fiddaman 		found = 0;
348*b0de25cbSAndy Fiddaman 		if (keysym < 0x80) {
349*b0de25cbSAndy Fiddaman 			code = ascii_translations[keysym];
350*b0de25cbSAndy Fiddaman 			e0_prefix = 0;
351*b0de25cbSAndy Fiddaman 			found = 1;
352*b0de25cbSAndy Fiddaman 		} else {
353*b0de25cbSAndy Fiddaman 			for (trans = &(extended_translations[0]); trans->keysym != 0;
354*b0de25cbSAndy Fiddaman 		    	trans++) {
355*b0de25cbSAndy Fiddaman 				if (keysym == trans->keysym) {
356*b0de25cbSAndy Fiddaman 					code = trans->scancode;
357*b0de25cbSAndy Fiddaman 					e0_prefix = trans->flags & SCANCODE_E0_PREFIX;
358*b0de25cbSAndy Fiddaman 					found = 1;
359*b0de25cbSAndy Fiddaman 					break;
360*b0de25cbSAndy Fiddaman 				}
3614c87aefeSPatrick Mooney 			}
3624c87aefeSPatrick Mooney 		}
3634c87aefeSPatrick Mooney 	}
364bf21cd93STycho Nightingale 
3654c87aefeSPatrick Mooney 	if (!found) {
366154972afSPatrick Mooney 		EPRINTLN("Unhandled ps2 keyboard keysym 0x%x", keysym);
3674c87aefeSPatrick Mooney 		return;
368bf21cd93STycho Nightingale 	}
3694c87aefeSPatrick Mooney 
3704c87aefeSPatrick Mooney 	if (e0_prefix)
3714c87aefeSPatrick Mooney 		fifo_put(sc, 0xe0);
3724c87aefeSPatrick Mooney 	if (!down)
3734c87aefeSPatrick Mooney 		fifo_put(sc, 0xf0);
3744c87aefeSPatrick Mooney 	fifo_put(sc, code);
375bf21cd93STycho Nightingale }
376bf21cd93STycho Nightingale 
377bf21cd93STycho Nightingale static void
378*b0de25cbSAndy Fiddaman ps2kbd_event(int down, uint32_t keysym, uint32_t keycode, void *arg)
379bf21cd93STycho Nightingale {
380bf21cd93STycho Nightingale 	struct ps2kbd_softc *sc = arg;
3814c87aefeSPatrick Mooney 	int fifo_full;
382bf21cd93STycho Nightingale 
383bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
384bf21cd93STycho Nightingale 	if (!sc->enabled) {
385bf21cd93STycho Nightingale 		pthread_mutex_unlock(&sc->mtx);
386bf21cd93STycho Nightingale 		return;
387bf21cd93STycho Nightingale 	}
3884c87aefeSPatrick Mooney 	fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
389*b0de25cbSAndy Fiddaman 	ps2kbd_keysym_queue(sc, down, keysym, keycode);
390bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
391bf21cd93STycho Nightingale 
3924c87aefeSPatrick Mooney 	if (!fifo_full)
3934c87aefeSPatrick Mooney 		atkbdc_event(sc->atkbdc_sc, 1);
394bf21cd93STycho Nightingale }
395bf21cd93STycho Nightingale 
396bf21cd93STycho Nightingale struct ps2kbd_softc *
397bf21cd93STycho Nightingale ps2kbd_init(struct atkbdc_softc *atkbdc_sc)
398bf21cd93STycho Nightingale {
399bf21cd93STycho Nightingale 	struct ps2kbd_softc *sc;
400bf21cd93STycho Nightingale 
401bf21cd93STycho Nightingale 	sc = calloc(1, sizeof (struct ps2kbd_softc));
402bf21cd93STycho Nightingale 	pthread_mutex_init(&sc->mtx, NULL);
403bf21cd93STycho Nightingale 	fifo_init(sc);
404bf21cd93STycho Nightingale 	sc->atkbdc_sc = atkbdc_sc;
405bf21cd93STycho Nightingale 
4064c87aefeSPatrick Mooney 	console_kbd_register(ps2kbd_event, sc, 1);
407bf21cd93STycho Nightingale 
408bf21cd93STycho Nightingale 	return (sc);
409bf21cd93STycho Nightingale }
4104c87aefeSPatrick Mooney 
411