1300829Sgrehan/*-
2300829Sgrehan * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3300829Sgrehan * Copyright (c) 2015 Nahanni Systems Inc.
4300829Sgrehan * All rights reserved.
5300829Sgrehan *
6300829Sgrehan * Redistribution and use in source and binary forms, with or without
7300829Sgrehan * modification, are permitted provided that the following conditions
8300829Sgrehan * are met:
9300829Sgrehan * 1. Redistributions of source code must retain the above copyright
10300829Sgrehan *    notice, this list of conditions and the following disclaimer.
11300829Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
12300829Sgrehan *    notice, this list of conditions and the following disclaimer in the
13300829Sgrehan *    documentation and/or other materials provided with the distribution.
14300829Sgrehan *
15300829Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16300829Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17300829Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18300829Sgrehan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19300829Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20300829Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21300829Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22300829Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23300829Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24300829Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25300829Sgrehan * SUCH DAMAGE.
26300829Sgrehan */
27300829Sgrehan
28300829Sgrehan#include <sys/cdefs.h>
29300829Sgrehan__FBSDID("$FreeBSD: releng/11.0/usr.sbin/bhyve/ps2kbd.c 302408 2016-07-08 00:04:57Z gjb $");
30300829Sgrehan
31300829Sgrehan#include <sys/types.h>
32300829Sgrehan
33300829Sgrehan#include <assert.h>
34300829Sgrehan#include <stdbool.h>
35300829Sgrehan#include <stdio.h>
36300829Sgrehan#include <stdlib.h>
37300829Sgrehan#include <strings.h>
38300829Sgrehan#include <pthread.h>
39300829Sgrehan#include <pthread_np.h>
40300829Sgrehan
41300829Sgrehan#include "atkbdc.h"
42300829Sgrehan#include "console.h"
43300829Sgrehan
44300829Sgrehan/* keyboard device commands */
45300829Sgrehan#define	PS2KC_RESET_DEV		0xff
46300829Sgrehan#define	PS2KC_DISABLE		0xf5
47300829Sgrehan#define	PS2KC_ENABLE		0xf4
48300829Sgrehan#define	PS2KC_SET_TYPEMATIC	0xf3
49300829Sgrehan#define	PS2KC_SEND_DEV_ID	0xf2
50300829Sgrehan#define	PS2KC_SET_SCANCODE_SET	0xf0
51300829Sgrehan#define	PS2KC_ECHO		0xee
52300829Sgrehan#define	PS2KC_SET_LEDS		0xed
53300829Sgrehan
54300829Sgrehan#define	PS2KC_BAT_SUCCESS	0xaa
55300829Sgrehan#define	PS2KC_ACK		0xfa
56300829Sgrehan
57300829Sgrehan#define	PS2KBD_FIFOSZ		16
58300829Sgrehan
59300829Sgrehanstruct fifo {
60300829Sgrehan	uint8_t	buf[PS2KBD_FIFOSZ];
61300829Sgrehan	int	rindex;		/* index to read from */
62300829Sgrehan	int	windex;		/* index to write to */
63300829Sgrehan	int	num;		/* number of bytes in the fifo */
64300829Sgrehan	int	size;		/* size of the fifo */
65300829Sgrehan};
66300829Sgrehan
67300829Sgrehanstruct ps2kbd_softc {
68300829Sgrehan	struct atkbdc_softc	*atkbdc_sc;
69300829Sgrehan	pthread_mutex_t		mtx;
70300829Sgrehan
71300829Sgrehan	bool			enabled;
72300829Sgrehan	struct fifo		fifo;
73300829Sgrehan
74300829Sgrehan	uint8_t			curcmd;	/* current command for next byte */
75300829Sgrehan};
76300829Sgrehan
77300829Sgrehanstatic void
78300829Sgrehanfifo_init(struct ps2kbd_softc *sc)
79300829Sgrehan{
80300829Sgrehan	struct fifo *fifo;
81300829Sgrehan
82300829Sgrehan	fifo = &sc->fifo;
83300829Sgrehan	fifo->size = sizeof(((struct fifo *)0)->buf);
84300829Sgrehan}
85300829Sgrehan
86300829Sgrehanstatic void
87300829Sgrehanfifo_reset(struct ps2kbd_softc *sc)
88300829Sgrehan{
89300829Sgrehan	struct fifo *fifo;
90300829Sgrehan
91300829Sgrehan	fifo = &sc->fifo;
92300829Sgrehan	bzero(fifo, sizeof(struct fifo));
93300829Sgrehan	fifo->size = sizeof(((struct fifo *)0)->buf);
94300829Sgrehan}
95300829Sgrehan
96300829Sgrehanstatic void
97300829Sgrehanfifo_put(struct ps2kbd_softc *sc, uint8_t val)
98300829Sgrehan{
99300829Sgrehan	struct fifo *fifo;
100300829Sgrehan
101300829Sgrehan	fifo = &sc->fifo;
102300829Sgrehan	if (fifo->num < fifo->size) {
103300829Sgrehan		fifo->buf[fifo->windex] = val;
104300829Sgrehan		fifo->windex = (fifo->windex + 1) % fifo->size;
105300829Sgrehan		fifo->num++;
106300829Sgrehan	}
107300829Sgrehan}
108300829Sgrehan
109300829Sgrehanstatic int
110300829Sgrehanfifo_get(struct ps2kbd_softc *sc, uint8_t *val)
111300829Sgrehan{
112300829Sgrehan	struct fifo *fifo;
113300829Sgrehan
114300829Sgrehan	fifo = &sc->fifo;
115300829Sgrehan	if (fifo->num > 0) {
116300829Sgrehan		*val = fifo->buf[fifo->rindex];
117300829Sgrehan		fifo->rindex = (fifo->rindex + 1) % fifo->size;
118300829Sgrehan		fifo->num--;
119300829Sgrehan		return (0);
120300829Sgrehan	}
121300829Sgrehan
122300829Sgrehan	return (-1);
123300829Sgrehan}
124300829Sgrehan
125300829Sgrehanint
126300829Sgrehanps2kbd_read(struct ps2kbd_softc *sc, uint8_t *val)
127300829Sgrehan{
128300829Sgrehan	int retval;
129300829Sgrehan
130300829Sgrehan	pthread_mutex_lock(&sc->mtx);
131300829Sgrehan	retval = fifo_get(sc, val);
132300829Sgrehan	pthread_mutex_unlock(&sc->mtx);
133300829Sgrehan
134300829Sgrehan	return (retval);
135300829Sgrehan}
136300829Sgrehan
137300829Sgrehanvoid
138300829Sgrehanps2kbd_write(struct ps2kbd_softc *sc, uint8_t val)
139300829Sgrehan{
140300829Sgrehan	pthread_mutex_lock(&sc->mtx);
141300829Sgrehan	if (sc->curcmd) {
142300829Sgrehan		switch (sc->curcmd) {
143300829Sgrehan		case PS2KC_SET_TYPEMATIC:
144300829Sgrehan			fifo_put(sc, PS2KC_ACK);
145300829Sgrehan			break;
146300829Sgrehan		case PS2KC_SET_SCANCODE_SET:
147300829Sgrehan			fifo_put(sc, PS2KC_ACK);
148300829Sgrehan			break;
149300829Sgrehan		case PS2KC_SET_LEDS:
150300829Sgrehan			fifo_put(sc, PS2KC_ACK);
151300829Sgrehan			break;
152300829Sgrehan		default:
153300829Sgrehan			fprintf(stderr, "Unhandled ps2 keyboard current "
154300829Sgrehan			    "command byte 0x%02x\n", val);
155300829Sgrehan			break;
156300829Sgrehan		}
157300829Sgrehan		sc->curcmd = 0;
158300829Sgrehan	} else {
159300829Sgrehan		switch (val) {
160300829Sgrehan		case 0x00:
161300829Sgrehan			fifo_put(sc, PS2KC_ACK);
162300829Sgrehan			break;
163300829Sgrehan		case PS2KC_RESET_DEV:
164300829Sgrehan			fifo_reset(sc);
165300829Sgrehan			fifo_put(sc, PS2KC_ACK);
166300829Sgrehan			fifo_put(sc, PS2KC_BAT_SUCCESS);
167300829Sgrehan			break;
168300829Sgrehan		case PS2KC_DISABLE:
169300829Sgrehan			sc->enabled = false;
170300829Sgrehan			fifo_put(sc, PS2KC_ACK);
171300829Sgrehan			break;
172300829Sgrehan		case PS2KC_ENABLE:
173300829Sgrehan			sc->enabled = true;
174300829Sgrehan			fifo_reset(sc);
175300829Sgrehan			fifo_put(sc, PS2KC_ACK);
176300829Sgrehan			break;
177300829Sgrehan		case PS2KC_SET_TYPEMATIC:
178300829Sgrehan			sc->curcmd = val;
179300829Sgrehan			fifo_put(sc, PS2KC_ACK);
180300829Sgrehan			break;
181300829Sgrehan		case PS2KC_SEND_DEV_ID:
182300829Sgrehan			fifo_put(sc, PS2KC_ACK);
183300829Sgrehan			fifo_put(sc, 0xab);
184300829Sgrehan			fifo_put(sc, 0x83);
185300829Sgrehan			break;
186300829Sgrehan		case PS2KC_SET_SCANCODE_SET:
187300829Sgrehan			sc->curcmd = val;
188300829Sgrehan			fifo_put(sc, PS2KC_ACK);
189300829Sgrehan			break;
190300829Sgrehan		case PS2KC_ECHO:
191300829Sgrehan			fifo_put(sc, PS2KC_ECHO);
192300829Sgrehan			break;
193300829Sgrehan		case PS2KC_SET_LEDS:
194300829Sgrehan			sc->curcmd = val;
195300829Sgrehan			fifo_put(sc, PS2KC_ACK);
196300829Sgrehan			break;
197300829Sgrehan		default:
198300829Sgrehan			fprintf(stderr, "Unhandled ps2 keyboard command "
199300829Sgrehan			    "0x%02x\n", val);
200300829Sgrehan			break;
201300829Sgrehan		}
202300829Sgrehan	}
203300829Sgrehan	pthread_mutex_unlock(&sc->mtx);
204300829Sgrehan}
205300829Sgrehan
206300829Sgrehan/*
207300829Sgrehan * Translate keysym to type 2 scancode and insert into keyboard buffer.
208300829Sgrehan */
209300829Sgrehanstatic void
210300829Sgrehanps2kbd_keysym_queue(struct ps2kbd_softc *sc,
211300829Sgrehan    int down, uint32_t keysym)
212300829Sgrehan{
213300829Sgrehan	/* ASCII to type 2 scancode lookup table */
214300829Sgrehan	const uint8_t translation[128] = {
215300829Sgrehan		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216300829Sgrehan		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217300829Sgrehan		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218300829Sgrehan		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219300829Sgrehan		0x29, 0x16, 0x52, 0x26, 0x25, 0x2e, 0x3d, 0x52,
220300829Sgrehan		0x46, 0x45, 0x3e, 0x55, 0x41, 0x4e, 0x49, 0x4a,
221300829Sgrehan		0x45, 0x16, 0x1e, 0x26, 0x25, 0x2e, 0x36, 0x3d,
222300829Sgrehan		0x3e, 0x46, 0x4c, 0x4c, 0x41, 0x55, 0x49, 0x4a,
223300829Sgrehan		0x1e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
224300829Sgrehan		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
225300829Sgrehan		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
226300829Sgrehan		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x36, 0x4e,
227300829Sgrehan		0x0e, 0x1c, 0x32, 0x21, 0x23, 0x24, 0x2b, 0x34,
228300829Sgrehan		0x33, 0x43, 0x3b, 0x42, 0x4b, 0x3a, 0x31, 0x44,
229300829Sgrehan		0x4d, 0x15, 0x2d, 0x1b, 0x2c, 0x3c, 0x2a, 0x1d,
230300829Sgrehan		0x22, 0x35, 0x1a, 0x54, 0x5d, 0x5b, 0x0e, 0x00,
231300829Sgrehan	};
232300829Sgrehan
233300829Sgrehan	assert(pthread_mutex_isowned_np(&sc->mtx));
234300829Sgrehan
235300829Sgrehan	switch (keysym) {
236300829Sgrehan	case 0x0 ... 0x7f:
237300829Sgrehan		if (!down)
238300829Sgrehan			fifo_put(sc, 0xf0);
239300829Sgrehan		fifo_put(sc, translation[keysym]);
240300829Sgrehan		break;
241300829Sgrehan	case 0xff08:	/* Back space */
242300829Sgrehan		if (!down)
243300829Sgrehan			fifo_put(sc, 0xf0);
244300829Sgrehan		fifo_put(sc, 0x66);
245300829Sgrehan		break;
246300829Sgrehan	case 0xff09:	/* Tab */
247300829Sgrehan		if (!down)
248300829Sgrehan			fifo_put(sc, 0xf0);
249300829Sgrehan		fifo_put(sc, 0x0d);
250300829Sgrehan		break;
251300829Sgrehan	case 0xff0d:	/* Return  */
252300829Sgrehan		if (!down)
253300829Sgrehan			fifo_put(sc, 0xf0);
254300829Sgrehan		fifo_put(sc, 0x5a);
255300829Sgrehan		break;
256300829Sgrehan	case 0xff1b:	/* Escape */
257300829Sgrehan		if (!down)
258300829Sgrehan			fifo_put(sc, 0xf0);
259300829Sgrehan		fifo_put(sc, 0x76);
260300829Sgrehan		break;
261300829Sgrehan	case 0xff50:	/* Home */
262300829Sgrehan		fifo_put(sc, 0xe0);
263300829Sgrehan		if (!down)
264300829Sgrehan			fifo_put(sc, 0xf0);
265300829Sgrehan		fifo_put(sc, 0x6c);
266300829Sgrehan		break;
267300829Sgrehan	case 0xff51:	/* Left arrow */
268300829Sgrehan		fifo_put(sc, 0xe0);
269300829Sgrehan		if (!down)
270300829Sgrehan			fifo_put(sc, 0xf0);
271300829Sgrehan		fifo_put(sc, 0x6b);
272300829Sgrehan		break;
273300829Sgrehan	case 0xff52:	/* Up arrow */
274300829Sgrehan		fifo_put(sc, 0xe0);
275300829Sgrehan		if (!down)
276300829Sgrehan			fifo_put(sc, 0xf0);
277300829Sgrehan		fifo_put(sc, 0x75);
278300829Sgrehan		break;
279300829Sgrehan	case 0xff53:	/* Right arrow */
280300829Sgrehan		fifo_put(sc, 0xe0);
281300829Sgrehan		if (!down)
282300829Sgrehan			fifo_put(sc, 0xf0);
283300829Sgrehan		fifo_put(sc, 0x74);
284300829Sgrehan		break;
285300829Sgrehan	case 0xff54:	/* Down arrow */
286300829Sgrehan		fifo_put(sc, 0xe0);
287300829Sgrehan		if (!down)
288300829Sgrehan			fifo_put(sc, 0xf0);
289300829Sgrehan		fifo_put(sc, 0x72);
290300829Sgrehan		break;
291300829Sgrehan	case 0xff55:	/* PgUp */
292300829Sgrehan		fifo_put(sc, 0xe0);
293300829Sgrehan		if (!down)
294300829Sgrehan			fifo_put(sc, 0xf0);
295300829Sgrehan		fifo_put(sc, 0x7d);
296300829Sgrehan		break;
297300829Sgrehan	case 0xff56:	/* PgDwn */
298300829Sgrehan		fifo_put(sc, 0xe0);
299300829Sgrehan		if (!down)
300300829Sgrehan			fifo_put(sc, 0xf0);
301300829Sgrehan		fifo_put(sc, 0x7a);
302300829Sgrehan		break;
303300829Sgrehan	case 0xff57:	/* End */
304300829Sgrehan		fifo_put(sc, 0xe0);
305300829Sgrehan		if (!down)
306300829Sgrehan			fifo_put(sc, 0xf0);
307300829Sgrehan		fifo_put(sc, 0x69);
308300829Sgrehan		break;
309300829Sgrehan	case 0xff63:	/* Ins */
310300829Sgrehan		fifo_put(sc, 0xe0);
311300829Sgrehan		if (!down)
312300829Sgrehan			fifo_put(sc, 0xf0);
313300829Sgrehan		fifo_put(sc, 0x70);
314300829Sgrehan		break;
315300829Sgrehan	case 0xff8d:	/* Keypad Enter */
316300829Sgrehan		fifo_put(sc, 0xe0);
317300829Sgrehan		if (!down)
318300829Sgrehan			fifo_put(sc, 0xf0);
319300829Sgrehan		fifo_put(sc, 0x5a);
320300829Sgrehan		break;
321300829Sgrehan	case 0xffe1:	/* Left shift */
322300829Sgrehan		if (!down)
323300829Sgrehan			fifo_put(sc, 0xf0);
324300829Sgrehan		fifo_put(sc, 0x12);
325300829Sgrehan		break;
326300829Sgrehan	case 0xffe2:	/* Right shift */
327300829Sgrehan		/* XXX */
328300829Sgrehan		break;
329300829Sgrehan	case 0xffe3:	/* Left control */
330300829Sgrehan		if (!down)
331300829Sgrehan			fifo_put(sc, 0xf0);
332300829Sgrehan		fifo_put(sc, 0x14);
333300829Sgrehan		break;
334300829Sgrehan	case 0xffe4:	/* Right control */
335300829Sgrehan		/* XXX */
336300829Sgrehan		break;
337300829Sgrehan	case 0xffe7:	/* Left meta */
338300829Sgrehan		/* XXX */
339300829Sgrehan		break;
340300829Sgrehan	case 0xffe8:	/* Right meta */
341300829Sgrehan		/* XXX */
342300829Sgrehan		break;
343300829Sgrehan	case 0xffe9:	/* Left alt */
344300829Sgrehan		if (!down)
345300829Sgrehan			fifo_put(sc, 0xf0);
346300829Sgrehan		fifo_put(sc, 0x11);
347300829Sgrehan		break;
348300829Sgrehan	case 0xffea:	/* Right alt */
349300829Sgrehan		fifo_put(sc, 0xe0);
350300829Sgrehan		if (!down)
351300829Sgrehan			fifo_put(sc, 0xf0);
352300829Sgrehan		fifo_put(sc, 0x11);
353300829Sgrehan		break;
354300829Sgrehan	case 0xffeb:	/* Left Windows */
355300829Sgrehan		fifo_put(sc, 0xe0);
356300829Sgrehan		if (!down)
357300829Sgrehan			fifo_put(sc, 0xf0);
358300829Sgrehan		fifo_put(sc, 0x1f);
359300829Sgrehan		break;
360300829Sgrehan	case 0xffec:	/* Right Windows */
361300829Sgrehan		fifo_put(sc, 0xe0);
362300829Sgrehan		if (!down)
363300829Sgrehan			fifo_put(sc, 0xf0);
364300829Sgrehan		fifo_put(sc, 0x27);
365300829Sgrehan		break;
366300829Sgrehan	case 0xffbe:    /* F1 */
367300829Sgrehan		if (!down)
368300829Sgrehan			fifo_put(sc, 0xf0);
369300829Sgrehan		fifo_put(sc, 0x05);
370300829Sgrehan		break;
371300829Sgrehan	case 0xffbf:    /* F2 */
372300829Sgrehan		if (!down)
373300829Sgrehan			fifo_put(sc, 0xf0);
374300829Sgrehan		fifo_put(sc, 0x06);
375300829Sgrehan		break;
376300829Sgrehan	case 0xffc0:    /* F3 */
377300829Sgrehan		if (!down)
378300829Sgrehan			fifo_put(sc, 0xf0);
379300829Sgrehan		fifo_put(sc, 0x04);
380300829Sgrehan		break;
381300829Sgrehan	case 0xffc1:    /* F4 */
382300829Sgrehan		if (!down)
383300829Sgrehan			fifo_put(sc, 0xf0);
384300829Sgrehan		fifo_put(sc, 0x0C);
385300829Sgrehan		break;
386300829Sgrehan	case 0xffc2:    /* F5 */
387300829Sgrehan		if (!down)
388300829Sgrehan			fifo_put(sc, 0xf0);
389300829Sgrehan		fifo_put(sc, 0x03);
390300829Sgrehan		break;
391300829Sgrehan	case 0xffc3:    /* F6 */
392300829Sgrehan		if (!down)
393300829Sgrehan			fifo_put(sc, 0xf0);
394300829Sgrehan		fifo_put(sc, 0x0B);
395300829Sgrehan		break;
396300829Sgrehan	case 0xffc4:    /* F7 */
397300829Sgrehan		if (!down)
398300829Sgrehan			fifo_put(sc, 0xf0);
399300829Sgrehan		fifo_put(sc, 0x83);
400300829Sgrehan		break;
401300829Sgrehan	case 0xffc5:    /* F8 */
402300829Sgrehan		if (!down)
403300829Sgrehan			fifo_put(sc, 0xf0);
404300829Sgrehan		fifo_put(sc, 0x0A);
405300829Sgrehan		break;
406300829Sgrehan	case 0xffc6:    /* F9 */
407300829Sgrehan		if (!down)
408300829Sgrehan			fifo_put(sc, 0xf0);
409300829Sgrehan		fifo_put(sc, 0x01);
410300829Sgrehan		break;
411300829Sgrehan	case 0xffc7:    /* F10 */
412300829Sgrehan		if (!down)
413300829Sgrehan			fifo_put(sc, 0xf0);
414300829Sgrehan		fifo_put(sc, 0x09);
415300829Sgrehan		break;
416300829Sgrehan	case 0xffc8:    /* F11 */
417300829Sgrehan		if (!down)
418300829Sgrehan			fifo_put(sc, 0xf0);
419300829Sgrehan		fifo_put(sc, 0x78);
420300829Sgrehan		break;
421300829Sgrehan	case 0xffc9:    /* F12 */
422300829Sgrehan		if (!down)
423300829Sgrehan			fifo_put(sc, 0xf0);
424300829Sgrehan		fifo_put(sc, 0x07);
425300829Sgrehan		break;
426300829Sgrehan	case 0xffff:    /* Del */
427300829Sgrehan		fifo_put(sc, 0xe0);
428300829Sgrehan		if (!down)
429300829Sgrehan			fifo_put(sc, 0xf0);
430300829Sgrehan		fifo_put(sc, 0x71);
431300829Sgrehan		break;
432300829Sgrehan	default:
433300829Sgrehan		fprintf(stderr, "Unhandled ps2 keyboard keysym 0x%x\n",
434300829Sgrehan		     keysym);
435300829Sgrehan		break;
436300829Sgrehan	}
437300829Sgrehan}
438300829Sgrehan
439300829Sgrehanstatic void
440300829Sgrehanps2kbd_event(int down, uint32_t keysym, void *arg)
441300829Sgrehan{
442300829Sgrehan	struct ps2kbd_softc *sc = arg;
443300829Sgrehan	int fifo_full;
444300829Sgrehan
445300829Sgrehan	pthread_mutex_lock(&sc->mtx);
446300829Sgrehan	if (!sc->enabled) {
447300829Sgrehan		pthread_mutex_unlock(&sc->mtx);
448300829Sgrehan		return;
449300829Sgrehan	}
450300829Sgrehan	fifo_full = sc->fifo.num == PS2KBD_FIFOSZ;
451300829Sgrehan	ps2kbd_keysym_queue(sc, down, keysym);
452300829Sgrehan	pthread_mutex_unlock(&sc->mtx);
453300829Sgrehan
454300829Sgrehan	if (!fifo_full)
455300829Sgrehan		atkbdc_event(sc->atkbdc_sc, 1);
456300829Sgrehan}
457300829Sgrehan
458300829Sgrehanstruct ps2kbd_softc *
459300829Sgrehanps2kbd_init(struct atkbdc_softc *atkbdc_sc)
460300829Sgrehan{
461300829Sgrehan	struct ps2kbd_softc *sc;
462300829Sgrehan
463300829Sgrehan	sc = calloc(1, sizeof (struct ps2kbd_softc));
464300829Sgrehan	pthread_mutex_init(&sc->mtx, NULL);
465300829Sgrehan	fifo_init(sc);
466300829Sgrehan	sc->atkbdc_sc = atkbdc_sc;
467300829Sgrehan
468300829Sgrehan	console_kbd_register(ps2kbd_event, sc, 1);
469300829Sgrehan
470300829Sgrehan	return (sc);
471300829Sgrehan}
472300829Sgrehan
473