xref: /illumos-gate/usr/src/cmd/bhyve/ps2kbd.c (revision bf21cd9318e0a3a51b7f02c14a7c1b1aef2dc861)
1*bf21cd93STycho Nightingale /*-
2*bf21cd93STycho Nightingale  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3*bf21cd93STycho Nightingale  * Copyright (c) 2015 Nahanni Systems Inc.
4*bf21cd93STycho Nightingale  * All rights reserved.
5*bf21cd93STycho Nightingale  *
6*bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
7*bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
8*bf21cd93STycho Nightingale  * are met:
9*bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
10*bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
11*bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
12*bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
13*bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
14*bf21cd93STycho Nightingale  *
15*bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16*bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*bf21cd93STycho Nightingale  * SUCH DAMAGE.
26*bf21cd93STycho Nightingale  */
27*bf21cd93STycho Nightingale 
28*bf21cd93STycho Nightingale #include <sys/cdefs.h>
29*bf21cd93STycho Nightingale __FBSDID("$FreeBSD$");
30*bf21cd93STycho Nightingale 
31*bf21cd93STycho Nightingale #include <sys/types.h>
32*bf21cd93STycho Nightingale 
33*bf21cd93STycho Nightingale #include <assert.h>
34*bf21cd93STycho Nightingale #include <stdbool.h>
35*bf21cd93STycho Nightingale #include <stdio.h>
36*bf21cd93STycho Nightingale #include <stdlib.h>
37*bf21cd93STycho Nightingale #include <strings.h>
38*bf21cd93STycho Nightingale #include <pthread.h>
39*bf21cd93STycho Nightingale #include <pthread_np.h>
40*bf21cd93STycho Nightingale 
41*bf21cd93STycho Nightingale #include "atkbdc.h"
42*bf21cd93STycho Nightingale #include "console.h"
43*bf21cd93STycho Nightingale 
44*bf21cd93STycho Nightingale /* keyboard device commands */
45*bf21cd93STycho Nightingale #define	PS2KC_RESET_DEV		0xff
46*bf21cd93STycho Nightingale #define	PS2KC_DISABLE		0xf5
47*bf21cd93STycho Nightingale #define	PS2KC_ENABLE		0xf4
48*bf21cd93STycho Nightingale #define	PS2KC_SET_TYPEMATIC	0xf3
49*bf21cd93STycho Nightingale #define	PS2KC_SEND_DEV_ID	0xf2
50*bf21cd93STycho Nightingale #define	PS2KC_SET_SCANCODE_SET	0xf0
51*bf21cd93STycho Nightingale #define	PS2KC_ECHO		0xee
52*bf21cd93STycho Nightingale #define	PS2KC_SET_LEDS		0xed
53*bf21cd93STycho Nightingale 
54*bf21cd93STycho Nightingale #define	PS2KC_BAT_SUCCESS	0xaa
55*bf21cd93STycho Nightingale #define	PS2KC_ACK		0xfa
56*bf21cd93STycho Nightingale 
57*bf21cd93STycho Nightingale #define	PS2KBD_FIFOSZ		16
58*bf21cd93STycho Nightingale 
59*bf21cd93STycho Nightingale struct fifo {
60*bf21cd93STycho Nightingale 	uint8_t	buf[PS2KBD_FIFOSZ];
61*bf21cd93STycho Nightingale 	int	rindex;		/* index to read from */
62*bf21cd93STycho Nightingale 	int	windex;		/* index to write to */
63*bf21cd93STycho Nightingale 	int	num;		/* number of bytes in the fifo */
64*bf21cd93STycho Nightingale 	int	size;		/* size of the fifo */
65*bf21cd93STycho Nightingale };
66*bf21cd93STycho Nightingale 
67*bf21cd93STycho Nightingale struct ps2kbd_softc {
68*bf21cd93STycho Nightingale 	struct atkbdc_softc	*atkbdc_sc;
69*bf21cd93STycho Nightingale 	pthread_mutex_t		mtx;
70*bf21cd93STycho Nightingale 
71*bf21cd93STycho Nightingale 	bool			enabled;
72*bf21cd93STycho Nightingale 	struct fifo		fifo;
73*bf21cd93STycho Nightingale 
74*bf21cd93STycho Nightingale 	uint8_t			curcmd;	/* current command for next byte */
75*bf21cd93STycho Nightingale };
76*bf21cd93STycho Nightingale 
77*bf21cd93STycho Nightingale static void
78*bf21cd93STycho Nightingale fifo_init(struct ps2kbd_softc *sc)
79*bf21cd93STycho Nightingale {
80*bf21cd93STycho Nightingale 	struct fifo *fifo;
81*bf21cd93STycho Nightingale 
82*bf21cd93STycho Nightingale 	fifo = &sc->fifo;
83*bf21cd93STycho Nightingale 	fifo->size = sizeof(((struct fifo *)0)->buf);
84*bf21cd93STycho Nightingale }
85*bf21cd93STycho Nightingale 
86*bf21cd93STycho Nightingale static void
87*bf21cd93STycho Nightingale fifo_reset(struct ps2kbd_softc *sc)
88*bf21cd93STycho Nightingale {
89*bf21cd93STycho Nightingale 	struct fifo *fifo;
90*bf21cd93STycho Nightingale 
91*bf21cd93STycho Nightingale 	fifo = &sc->fifo;
92*bf21cd93STycho Nightingale 	bzero(fifo, sizeof(struct fifo));
93*bf21cd93STycho Nightingale 	fifo->size = sizeof(((struct fifo *)0)->buf);
94*bf21cd93STycho Nightingale }
95*bf21cd93STycho Nightingale 
96*bf21cd93STycho Nightingale static int
97*bf21cd93STycho Nightingale fifo_available(struct ps2kbd_softc *sc)
98*bf21cd93STycho Nightingale {
99*bf21cd93STycho Nightingale 	struct fifo *fifo;
100*bf21cd93STycho Nightingale 
101*bf21cd93STycho Nightingale 	fifo = &sc->fifo;
102*bf21cd93STycho Nightingale 	return (fifo->num < fifo->size);
103*bf21cd93STycho Nightingale }
104*bf21cd93STycho Nightingale 
105*bf21cd93STycho Nightingale static void
106*bf21cd93STycho Nightingale fifo_put(struct ps2kbd_softc *sc, uint8_t val)
107*bf21cd93STycho Nightingale {
108*bf21cd93STycho Nightingale 	struct fifo *fifo;
109*bf21cd93STycho Nightingale 
110*bf21cd93STycho Nightingale 	fifo = &sc->fifo;
111*bf21cd93STycho Nightingale 	if (fifo->num < fifo->size) {
112*bf21cd93STycho Nightingale 		fifo->buf[fifo->windex] = val;
113*bf21cd93STycho Nightingale 		fifo->windex = (fifo->windex + 1) % fifo->size;
114*bf21cd93STycho Nightingale 		fifo->num++;
115*bf21cd93STycho Nightingale 	}
116*bf21cd93STycho Nightingale }
117*bf21cd93STycho Nightingale 
118*bf21cd93STycho Nightingale static int
119*bf21cd93STycho Nightingale fifo_get(struct ps2kbd_softc *sc, uint8_t *val)
120*bf21cd93STycho Nightingale {
121*bf21cd93STycho Nightingale 	struct fifo *fifo;
122*bf21cd93STycho Nightingale 
123*bf21cd93STycho Nightingale 	fifo = &sc->fifo;
124*bf21cd93STycho Nightingale 	if (fifo->num > 0) {
125*bf21cd93STycho Nightingale 		*val = fifo->buf[fifo->rindex];
126*bf21cd93STycho Nightingale 		fifo->rindex = (fifo->rindex + 1) % fifo->size;
127*bf21cd93STycho Nightingale 		fifo->num--;
128*bf21cd93STycho Nightingale 		return (0);
129*bf21cd93STycho Nightingale 	}
130*bf21cd93STycho Nightingale 
131*bf21cd93STycho Nightingale 	return (-1);
132*bf21cd93STycho Nightingale }
133*bf21cd93STycho Nightingale 
134*bf21cd93STycho Nightingale int
135*bf21cd93STycho Nightingale ps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
136*bf21cd93STycho Nightingale {
137*bf21cd93STycho Nightingale 	int retval;
138*bf21cd93STycho Nightingale 
139*bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
140*bf21cd93STycho Nightingale 	retval = fifo_get(sc, val);
141*bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
142*bf21cd93STycho Nightingale 
143*bf21cd93STycho Nightingale 	return (retval);
144*bf21cd93STycho Nightingale }
145*bf21cd93STycho Nightingale 
146*bf21cd93STycho Nightingale void
147*bf21cd93STycho Nightingale ps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
148*bf21cd93STycho Nightingale {
149*bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
150*bf21cd93STycho Nightingale 	if (sc->curcmd) {
151*bf21cd93STycho Nightingale 		switch (sc->curcmd) {
152*bf21cd93STycho Nightingale 		case PS2KC_SET_TYPEMATIC:
153*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
154*bf21cd93STycho Nightingale 			break;
155*bf21cd93STycho Nightingale 		case PS2KC_SET_SCANCODE_SET:
156*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
157*bf21cd93STycho Nightingale 			break;
158*bf21cd93STycho Nightingale 		case PS2KC_SET_LEDS:
159*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
160*bf21cd93STycho Nightingale 			break;
161*bf21cd93STycho Nightingale 		default:
162*bf21cd93STycho Nightingale 			fprintf(stderr, "Unhandled ps2 keyboard current "
163*bf21cd93STycho Nightingale 			    "command byte 0x%02x\n", val);
164*bf21cd93STycho Nightingale 			break;
165*bf21cd93STycho Nightingale 		}
166*bf21cd93STycho Nightingale 		sc->curcmd = 0;
167*bf21cd93STycho Nightingale 	} else {
168*bf21cd93STycho Nightingale 		switch (val) {
169*bf21cd93STycho Nightingale 		case PS2KC_RESET_DEV:
170*bf21cd93STycho Nightingale 			fifo_reset(sc);
171*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
172*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_BAT_SUCCESS);
173*bf21cd93STycho Nightingale 			break;
174*bf21cd93STycho Nightingale 		case PS2KC_DISABLE:
175*bf21cd93STycho Nightingale 			sc->enabled = false;
176*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
177*bf21cd93STycho Nightingale 			break;
178*bf21cd93STycho Nightingale 		case PS2KC_ENABLE:
179*bf21cd93STycho Nightingale 			sc->enabled = true;
180*bf21cd93STycho Nightingale 			fifo_reset(sc);
181*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
182*bf21cd93STycho Nightingale 			break;
183*bf21cd93STycho Nightingale 		case PS2KC_SET_TYPEMATIC:
184*bf21cd93STycho Nightingale 			sc->curcmd = val;
185*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
186*bf21cd93STycho Nightingale 			break;
187*bf21cd93STycho Nightingale 		case PS2KC_SEND_DEV_ID:
188*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
189*bf21cd93STycho Nightingale 			fifo_put(sc, 0xab);
190*bf21cd93STycho Nightingale 			fifo_put(sc, 0x83);
191*bf21cd93STycho Nightingale 			break;
192*bf21cd93STycho Nightingale 		case PS2KC_SET_SCANCODE_SET:
193*bf21cd93STycho Nightingale 			sc->curcmd = val;
194*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
195*bf21cd93STycho Nightingale 			break;
196*bf21cd93STycho Nightingale 		case PS2KC_ECHO:
197*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ECHO);
198*bf21cd93STycho Nightingale 			break;
199*bf21cd93STycho Nightingale 		case PS2KC_SET_LEDS:
200*bf21cd93STycho Nightingale 			sc->curcmd = val;
201*bf21cd93STycho Nightingale 			fifo_put(sc, PS2KC_ACK);
202*bf21cd93STycho Nightingale 			break;
203*bf21cd93STycho Nightingale 		default:
204*bf21cd93STycho Nightingale 			fprintf(stderr, "Unhandled ps2 keyboard command "
205*bf21cd93STycho Nightingale 			    "0x%02x\n", val);
206*bf21cd93STycho Nightingale 			break;
207*bf21cd93STycho Nightingale 		}
208*bf21cd93STycho Nightingale 	}
209*bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
210*bf21cd93STycho Nightingale }
211*bf21cd93STycho Nightingale 
212*bf21cd93STycho Nightingale /*
213*bf21cd93STycho Nightingale  * Translate keysym to type 2 scancode and insert into keyboard buffer.
214*bf21cd93STycho Nightingale  */
215*bf21cd93STycho Nightingale static void
216*bf21cd93STycho Nightingale ps2kbd_keysym_queue(struct ps2kbd_softc *sc,
217*bf21cd93STycho Nightingale     int down, uint32_t keysym)
218*bf21cd93STycho Nightingale {
219*bf21cd93STycho Nightingale 	/* ASCII to type 2 scancode lookup table */
220*bf21cd93STycho Nightingale 	const uint8_t translation[128] = {
221*bf21cd93STycho Nightingale 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222*bf21cd93STycho Nightingale 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223*bf21cd93STycho Nightingale 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224*bf21cd93STycho Nightingale 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225*bf21cd93STycho Nightingale 		0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52,
226*bf21cd93STycho Nightingale 		0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a,
227*bf21cd93STycho Nightingale 		0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d,
228*bf21cd93STycho Nightingale 		0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a,
229*bf21cd93STycho Nightingale 		0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
230*bf21cd93STycho Nightingale 		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
231*bf21cd93STycho Nightingale 		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
232*bf21cd93STycho Nightingale 		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e,
233*bf21cd93STycho Nightingale 		0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
234*bf21cd93STycho Nightingale 		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
235*bf21cd93STycho Nightingale 		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
236*bf21cd93STycho Nightingale 		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
237*bf21cd93STycho Nightingale 	};
238*bf21cd93STycho Nightingale 
239*bf21cd93STycho Nightingale 	assert(pthread_mutex_isowned_np(&sc->mtx));
240*bf21cd93STycho Nightingale 
241*bf21cd93STycho Nightingale 	switch (keysym) {
242*bf21cd93STycho Nightingale 	case 0x0 ... 0x7f:
243*bf21cd93STycho Nightingale 		if (!down)
244*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
245*bf21cd93STycho Nightingale 		fifo_put(sc, translation[keysym]);
246*bf21cd93STycho Nightingale 		break;
247*bf21cd93STycho Nightingale 	case 0xff08:	/* Back space */
248*bf21cd93STycho Nightingale 		if (!down)
249*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
250*bf21cd93STycho Nightingale 		fifo_put(sc, 0x66);
251*bf21cd93STycho Nightingale 		break;
252*bf21cd93STycho Nightingale 	case 0xff09:	/* Tab */
253*bf21cd93STycho Nightingale 		if (!down)
254*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
255*bf21cd93STycho Nightingale 		fifo_put(sc, 0x0d);
256*bf21cd93STycho Nightingale 		break;
257*bf21cd93STycho Nightingale 	case 0xff0d:	/* Return  */
258*bf21cd93STycho Nightingale 		if (!down)
259*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
260*bf21cd93STycho Nightingale 		fifo_put(sc, 0x5a);
261*bf21cd93STycho Nightingale 		break;
262*bf21cd93STycho Nightingale 	case 0xff1b:	/* Escape */
263*bf21cd93STycho Nightingale 		if (!down)
264*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
265*bf21cd93STycho Nightingale 		fifo_put(sc, 0x76);
266*bf21cd93STycho Nightingale 		break;
267*bf21cd93STycho Nightingale 	case 0xff51:	/* Left arrow */
268*bf21cd93STycho Nightingale 		fifo_put(sc, 0xe0);
269*bf21cd93STycho Nightingale 		if (!down)
270*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
271*bf21cd93STycho Nightingale 		fifo_put(sc, 0x6b);
272*bf21cd93STycho Nightingale 		break;
273*bf21cd93STycho Nightingale 	case 0xff52:	/* Up arrow */
274*bf21cd93STycho Nightingale 		fifo_put(sc, 0xe0);
275*bf21cd93STycho Nightingale 		if (!down)
276*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
277*bf21cd93STycho Nightingale 		fifo_put(sc, 0x75);
278*bf21cd93STycho Nightingale 		break;
279*bf21cd93STycho Nightingale 	case 0xff53:	/* Right arrow */
280*bf21cd93STycho Nightingale 		fifo_put(sc, 0xe0);
281*bf21cd93STycho Nightingale 		if (!down)
282*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
283*bf21cd93STycho Nightingale 		fifo_put(sc, 0x74);
284*bf21cd93STycho Nightingale 		break;
285*bf21cd93STycho Nightingale 	case 0xff54:	/* Down arrow */
286*bf21cd93STycho Nightingale 		fifo_put(sc, 0xe0);
287*bf21cd93STycho Nightingale 		if (!down)
288*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
289*bf21cd93STycho Nightingale 		fifo_put(sc, 0x72);
290*bf21cd93STycho Nightingale 		break;
291*bf21cd93STycho Nightingale 	case 0xffbe:	/* F1 */
292*bf21cd93STycho Nightingale 		if (!down)
293*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
294*bf21cd93STycho Nightingale 		fifo_put(sc, 0x05);
295*bf21cd93STycho Nightingale 		break;
296*bf21cd93STycho Nightingale 	case 0xffbf:	/* F2 */
297*bf21cd93STycho Nightingale 		if (!down)
298*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
299*bf21cd93STycho Nightingale 		fifo_put(sc, 0x06);
300*bf21cd93STycho Nightingale 		break;
301*bf21cd93STycho Nightingale 	case 0xffc0:	/* F3 */
302*bf21cd93STycho Nightingale 		if (!down)
303*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
304*bf21cd93STycho Nightingale 		fifo_put(sc, 0x04);
305*bf21cd93STycho Nightingale 		break;
306*bf21cd93STycho Nightingale 	case 0xffc1:	/* F4 */
307*bf21cd93STycho Nightingale 		if (!down)
308*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
309*bf21cd93STycho Nightingale 		fifo_put(sc, 0x0c);
310*bf21cd93STycho Nightingale 		break;
311*bf21cd93STycho Nightingale 	case 0xffc2:	/* F5 */
312*bf21cd93STycho Nightingale 		if (!down)
313*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
314*bf21cd93STycho Nightingale 		fifo_put(sc, 0x03);
315*bf21cd93STycho Nightingale 		break;
316*bf21cd93STycho Nightingale 	case 0xffc3:	/* F6 */
317*bf21cd93STycho Nightingale 		if (!down)
318*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
319*bf21cd93STycho Nightingale 		fifo_put(sc, 0x0b);
320*bf21cd93STycho Nightingale 		break;
321*bf21cd93STycho Nightingale 	case 0xffc4:	/* F7 */
322*bf21cd93STycho Nightingale 		if (!down)
323*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
324*bf21cd93STycho Nightingale 		fifo_put(sc, 0x83);
325*bf21cd93STycho Nightingale 		break;
326*bf21cd93STycho Nightingale 	case 0xffc5:	/* F8 */
327*bf21cd93STycho Nightingale 		if (!down)
328*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
329*bf21cd93STycho Nightingale 		fifo_put(sc, 0x0a);
330*bf21cd93STycho Nightingale 		break;
331*bf21cd93STycho Nightingale 	case 0xffc6:	/* F9 */
332*bf21cd93STycho Nightingale 		if (!down)
333*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
334*bf21cd93STycho Nightingale 		fifo_put(sc, 0x01);
335*bf21cd93STycho Nightingale 		break;
336*bf21cd93STycho Nightingale 	case 0xffc7:	/* F10 */
337*bf21cd93STycho Nightingale 		if (!down)
338*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
339*bf21cd93STycho Nightingale 		fifo_put(sc, 0x09);
340*bf21cd93STycho Nightingale 		break;
341*bf21cd93STycho Nightingale 	case 0xffc8:	/* F11 */
342*bf21cd93STycho Nightingale 		if (!down)
343*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
344*bf21cd93STycho Nightingale 		fifo_put(sc, 0x78);
345*bf21cd93STycho Nightingale 		break;
346*bf21cd93STycho Nightingale 	case 0xffc9:	/* F12 */
347*bf21cd93STycho Nightingale 		if (!down)
348*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
349*bf21cd93STycho Nightingale 		fifo_put(sc, 0x07);
350*bf21cd93STycho Nightingale 		break;
351*bf21cd93STycho Nightingale 	case 0xffe1:	/* Left shift */
352*bf21cd93STycho Nightingale 		if (!down)
353*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
354*bf21cd93STycho Nightingale 		fifo_put(sc, 0x12);
355*bf21cd93STycho Nightingale 		break;
356*bf21cd93STycho Nightingale 	case 0xffe2:	/* Right shift */
357*bf21cd93STycho Nightingale 		/* XXX */
358*bf21cd93STycho Nightingale 		break;
359*bf21cd93STycho Nightingale 	case 0xffe3:	/* Left control */
360*bf21cd93STycho Nightingale 		if (!down)
361*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
362*bf21cd93STycho Nightingale 		fifo_put(sc, 0x14);
363*bf21cd93STycho Nightingale 		break;
364*bf21cd93STycho Nightingale 	case 0xffe4:	/* Right control */
365*bf21cd93STycho Nightingale 		/* XXX */
366*bf21cd93STycho Nightingale 		break;
367*bf21cd93STycho Nightingale 	case 0xffe7:	/* Left meta */
368*bf21cd93STycho Nightingale 		/* XXX */
369*bf21cd93STycho Nightingale 		break;
370*bf21cd93STycho Nightingale 	case 0xffe8:	/* Right meta */
371*bf21cd93STycho Nightingale 		/* XXX */
372*bf21cd93STycho Nightingale 		break;
373*bf21cd93STycho Nightingale 	case 0xffe9:	/* Left alt */
374*bf21cd93STycho Nightingale 		if (!down)
375*bf21cd93STycho Nightingale 			fifo_put(sc, 0xf0);
376*bf21cd93STycho Nightingale 		fifo_put(sc, 0x11);
377*bf21cd93STycho Nightingale 		break;
378*bf21cd93STycho Nightingale 	case 0xffea:	/* Right alt */
379*bf21cd93STycho Nightingale 		/* XXX */
380*bf21cd93STycho Nightingale 		break;
381*bf21cd93STycho Nightingale 	default:
382*bf21cd93STycho Nightingale 		fprintf(stderr, "Unhandled ps2 keyboard keysym 0x%x\n",
383*bf21cd93STycho Nightingale 		     keysym);
384*bf21cd93STycho Nightingale 		break;
385*bf21cd93STycho Nightingale 	}
386*bf21cd93STycho Nightingale }
387*bf21cd93STycho Nightingale 
388*bf21cd93STycho Nightingale static void
389*bf21cd93STycho Nightingale ps2kbd_event(int down, uint32_t keysym, void *arg)
390*bf21cd93STycho Nightingale {
391*bf21cd93STycho Nightingale 	struct ps2kbd_softc *sc = arg;
392*bf21cd93STycho Nightingale 
393*bf21cd93STycho Nightingale 	pthread_mutex_lock(&sc->mtx);
394*bf21cd93STycho Nightingale 	if (!sc->enabled) {
395*bf21cd93STycho Nightingale 		pthread_mutex_unlock(&sc->mtx);
396*bf21cd93STycho Nightingale 		return;
397*bf21cd93STycho Nightingale 	}
398*bf21cd93STycho Nightingale 
399*bf21cd93STycho Nightingale 	ps2kbd_keysym_queue(sc, down, keysym);
400*bf21cd93STycho Nightingale 	pthread_mutex_unlock(&sc->mtx);
401*bf21cd93STycho Nightingale 
402*bf21cd93STycho Nightingale 	atkbdc_event(sc->atkbdc_sc);
403*bf21cd93STycho Nightingale }
404*bf21cd93STycho Nightingale 
405*bf21cd93STycho Nightingale struct ps2kbd_softc *
406*bf21cd93STycho Nightingale ps2kbd_init(struct atkbdc_softc *atkbdc_sc)
407*bf21cd93STycho Nightingale {
408*bf21cd93STycho Nightingale 	struct ps2kbd_softc *sc;
409*bf21cd93STycho Nightingale 
410*bf21cd93STycho Nightingale 	sc = calloc(1, sizeof (struct ps2kbd_softc));
411*bf21cd93STycho Nightingale 	pthread_mutex_init(&sc->mtx, NULL);
412*bf21cd93STycho Nightingale 	fifo_init(sc);
413*bf21cd93STycho Nightingale 	sc->atkbdc_sc = atkbdc_sc;
414*bf21cd93STycho Nightingale 
415*bf21cd93STycho Nightingale 	console_kbd_register(ps2kbd_event, sc);
416*bf21cd93STycho Nightingale 
417*bf21cd93STycho Nightingale 	return (sc);
418*bf21cd93STycho Nightingale }
419