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