]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/atkbdc.c
THIS BRANCH IS OBSOLETE, PLEASE READ:
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / atkbdc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5  * Copyright (c) 2015 Nahanni Systems Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/types.h>
34
35 #include <machine/vmm.h>
36 #include <machine/vmm_snapshot.h>
37
38 #include <vmmapi.h>
39
40 #include <assert.h>
41 #include <errno.h>
42 #include <stdbool.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <pthread.h>
48 #include <pthread_np.h>
49
50 #include "acpi.h"
51 #include "atkbdc.h"
52 #include "inout.h"
53 #include "pci_emul.h"
54 #include "pci_irq.h"
55 #include "pci_lpc.h"
56 #include "ps2kbd.h"
57 #include "ps2mouse.h"
58
59 #define KBD_DATA_PORT           0x60
60
61 #define KBD_STS_CTL_PORT        0x64
62
63 #define KBDC_RESET              0xfe
64
65 #define KBD_DEV_IRQ             1
66 #define AUX_DEV_IRQ             12
67
68 /* controller commands */
69 #define KBDC_SET_COMMAND_BYTE   0x60
70 #define KBDC_GET_COMMAND_BYTE   0x20
71 #define KBDC_DISABLE_AUX_PORT   0xa7
72 #define KBDC_ENABLE_AUX_PORT    0xa8
73 #define KBDC_TEST_AUX_PORT      0xa9
74 #define KBDC_TEST_CTRL          0xaa
75 #define KBDC_TEST_KBD_PORT      0xab
76 #define KBDC_DISABLE_KBD_PORT   0xad
77 #define KBDC_ENABLE_KBD_PORT    0xae
78 #define KBDC_READ_INPORT        0xc0
79 #define KBDC_READ_OUTPORT       0xd0
80 #define KBDC_WRITE_OUTPORT      0xd1
81 #define KBDC_WRITE_KBD_OUTBUF   0xd2
82 #define KBDC_WRITE_AUX_OUTBUF   0xd3
83 #define KBDC_WRITE_TO_AUX       0xd4
84
85 /* controller command byte (set by KBDC_SET_COMMAND_BYTE) */
86 #define KBD_TRANSLATION         0x40
87 #define KBD_SYS_FLAG_BIT        0x04
88 #define KBD_DISABLE_KBD_PORT    0x10
89 #define KBD_DISABLE_AUX_PORT    0x20
90 #define KBD_ENABLE_AUX_INT      0x02
91 #define KBD_ENABLE_KBD_INT      0x01
92 #define KBD_KBD_CONTROL_BITS    (KBD_DISABLE_KBD_PORT | KBD_ENABLE_KBD_INT)
93 #define KBD_AUX_CONTROL_BITS    (KBD_DISABLE_AUX_PORT | KBD_ENABLE_AUX_INT)
94
95 /* controller status bits */
96 #define KBDS_KBD_BUFFER_FULL    0x01
97 #define KBDS_SYS_FLAG           0x04
98 #define KBDS_CTRL_FLAG          0x08
99 #define KBDS_AUX_BUFFER_FULL    0x20
100
101 /* controller output port */
102 #define KBDO_KBD_OUTFULL        0x10
103 #define KBDO_AUX_OUTFULL        0x20
104
105 #define RAMSZ                   32
106 #define FIFOSZ                  15
107 #define CTRL_CMD_FLAG           0x8000
108
109 struct kbd_dev {
110         bool    irq_active;
111         int     irq;
112
113         uint8_t buffer[FIFOSZ];
114         int     brd, bwr;
115         int     bcnt;
116 };
117
118 struct aux_dev {
119         bool    irq_active;
120         int     irq;
121 };
122
123 struct atkbdc_softc {
124         struct vmctx *ctx;
125         pthread_mutex_t mtx;
126
127         struct ps2kbd_softc     *ps2kbd_sc;
128         struct ps2mouse_softc   *ps2mouse_sc;
129
130         uint8_t status;         /* status register */
131         uint8_t outport;        /* controller output port */
132         uint8_t ram[RAMSZ];     /* byte0 = controller config */
133
134         uint32_t curcmd;        /* current command for next byte */
135         uint32_t  ctrlbyte;
136
137         struct kbd_dev kbd;
138         struct aux_dev aux;
139 };
140
141 #ifdef BHYVE_SNAPSHOT
142 static struct atkbdc_softc *atkbdc_sc = NULL;
143 #endif
144
145 static void
146 atkbdc_assert_kbd_intr(struct atkbdc_softc *sc)
147 {
148         if ((sc->ram[0] & KBD_ENABLE_KBD_INT) != 0) {
149                 sc->kbd.irq_active = true;
150                 vm_isa_pulse_irq(sc->ctx, sc->kbd.irq, sc->kbd.irq);
151         }
152 }
153
154 static void
155 atkbdc_assert_aux_intr(struct atkbdc_softc *sc)
156 {
157         if ((sc->ram[0] & KBD_ENABLE_AUX_INT) != 0) {
158                 sc->aux.irq_active = true;
159                 vm_isa_pulse_irq(sc->ctx, sc->aux.irq, sc->aux.irq);
160         }
161 }
162
163 static int
164 atkbdc_kbd_queue_data(struct atkbdc_softc *sc, uint8_t val)
165 {
166         assert(pthread_mutex_isowned_np(&sc->mtx));
167
168         if (sc->kbd.bcnt < FIFOSZ) {
169                 sc->kbd.buffer[sc->kbd.bwr] = val;
170                 sc->kbd.bwr = (sc->kbd.bwr + 1) % FIFOSZ;
171                 sc->kbd.bcnt++;
172                 sc->status |= KBDS_KBD_BUFFER_FULL;
173                 sc->outport |= KBDO_KBD_OUTFULL;
174         } else {
175                 printf("atkbd data buffer full\n");
176         }
177
178         return (sc->kbd.bcnt < FIFOSZ);
179 }
180
181 static void
182 atkbdc_kbd_read(struct atkbdc_softc *sc)
183 {
184         const uint8_t translation[256] = {
185                 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
186                 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
187                 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
188                 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
189                 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
190                 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
191                 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
192                 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
193                 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
194                 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
195                 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
196                 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
197                 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
198                 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
199                 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
200                 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
201                 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
202                 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
203                 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
204                 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
205                 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
206                 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
207                 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
208                 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
209                 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
210                 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
211                 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
212                 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
213                 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
214                 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
215                 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
216                 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
217         };
218         uint8_t val;
219         uint8_t release = 0;
220
221         assert(pthread_mutex_isowned_np(&sc->mtx));
222
223         if (sc->ram[0] & KBD_TRANSLATION) {
224                 while (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) {
225                         if (val == 0xf0) {
226                                 release = 0x80;
227                                 continue;
228                         } else {
229                                 val = translation[val] | release;
230                         }
231                         atkbdc_kbd_queue_data(sc, val);
232                         break;
233                 }
234         } else {
235                 while (sc->kbd.bcnt < FIFOSZ) {
236                         if (ps2kbd_read(sc->ps2kbd_sc, &val) != -1)
237                                 atkbdc_kbd_queue_data(sc, val);
238                         else
239                                 break;
240                 }
241         }
242
243         if (((sc->ram[0] & KBD_DISABLE_AUX_PORT) ||
244             ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) && sc->kbd.bcnt > 0)
245                 atkbdc_assert_kbd_intr(sc);
246 }
247
248 static void
249 atkbdc_aux_poll(struct atkbdc_softc *sc)
250 {
251         if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0) {
252                 sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
253                 sc->outport |= KBDO_AUX_OUTFULL;
254                 atkbdc_assert_aux_intr(sc);
255         }
256 }
257
258 static void
259 atkbdc_kbd_poll(struct atkbdc_softc *sc)
260 {
261         assert(pthread_mutex_isowned_np(&sc->mtx));
262
263         atkbdc_kbd_read(sc);
264 }
265
266 static void
267 atkbdc_poll(struct atkbdc_softc *sc)
268 {
269         atkbdc_aux_poll(sc);
270         atkbdc_kbd_poll(sc);
271 }
272
273 static void
274 atkbdc_dequeue_data(struct atkbdc_softc *sc, uint8_t *buf)
275 {
276         assert(pthread_mutex_isowned_np(&sc->mtx));
277
278         if (ps2mouse_read(sc->ps2mouse_sc, buf) == 0) {
279                 if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) {
280                         if (sc->kbd.bcnt == 0)
281                                 sc->status &= ~(KBDS_AUX_BUFFER_FULL |
282                                                 KBDS_KBD_BUFFER_FULL);
283                         else
284                                 sc->status &= ~(KBDS_AUX_BUFFER_FULL);
285                         sc->outport &= ~KBDO_AUX_OUTFULL;
286                 }
287
288                 atkbdc_poll(sc);
289                 return;
290         }
291
292         if (sc->kbd.bcnt > 0) {
293                 *buf = sc->kbd.buffer[sc->kbd.brd];
294                 sc->kbd.brd = (sc->kbd.brd + 1) % FIFOSZ;
295                 sc->kbd.bcnt--;
296                 if (sc->kbd.bcnt == 0) {
297                         sc->status &= ~KBDS_KBD_BUFFER_FULL;
298                         sc->outport &= ~KBDO_KBD_OUTFULL;
299                 }
300
301                 atkbdc_poll(sc);
302         }
303
304         if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0 && sc->kbd.bcnt == 0) {
305                 sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
306         }
307 }
308
309 static int
310 atkbdc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
311     uint32_t *eax, void *arg)
312 {
313         struct atkbdc_softc *sc;
314         uint8_t buf;
315         int retval;
316
317         if (bytes != 1)
318                 return (-1);
319         sc = arg;
320         retval = 0;
321
322         pthread_mutex_lock(&sc->mtx);
323         if (in) {
324                 sc->curcmd = 0;
325                 if (sc->ctrlbyte != 0) {
326                         *eax = sc->ctrlbyte & 0xff;
327                         sc->ctrlbyte = 0;
328                 } else {
329                         /* read device buffer; includes kbd cmd responses */
330                         atkbdc_dequeue_data(sc, &buf);
331                         *eax = buf;
332                 }
333
334                 sc->status &= ~KBDS_CTRL_FLAG;
335                 pthread_mutex_unlock(&sc->mtx);
336                 return (retval);
337         }
338
339         if (sc->status & KBDS_CTRL_FLAG) {
340                 /*
341                  * Command byte for the controller.
342                  */
343                 switch (sc->curcmd) {
344                 case KBDC_SET_COMMAND_BYTE:
345                         sc->ram[0] = *eax;
346                         if (sc->ram[0] & KBD_SYS_FLAG_BIT)
347                                 sc->status |= KBDS_SYS_FLAG;
348                         else
349                                 sc->status &= ~KBDS_SYS_FLAG;
350                         break;
351                 case KBDC_WRITE_OUTPORT:
352                         sc->outport = *eax;
353                         break;
354                 case KBDC_WRITE_TO_AUX:
355                         ps2mouse_write(sc->ps2mouse_sc, *eax, 0);
356                         atkbdc_poll(sc);
357                         break;
358                 case KBDC_WRITE_KBD_OUTBUF:
359                         atkbdc_kbd_queue_data(sc, *eax);
360                         break;
361                 case KBDC_WRITE_AUX_OUTBUF:
362                         ps2mouse_write(sc->ps2mouse_sc, *eax, 1);
363                         sc->status |= (KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
364                         atkbdc_aux_poll(sc);
365                         break;
366                 default:
367                         /* write to particular RAM byte */
368                         if (sc->curcmd >= 0x61 && sc->curcmd <= 0x7f) {
369                                 int byten;
370
371                                 byten = (sc->curcmd - 0x60) & 0x1f;
372                                 sc->ram[byten] = *eax & 0xff;
373                         }
374                         break;
375                 }
376
377                 sc->curcmd = 0;
378                 sc->status &= ~KBDS_CTRL_FLAG;
379
380                 pthread_mutex_unlock(&sc->mtx);
381                 return (retval);
382         }
383
384         /*
385          * Data byte for the device.
386          */
387         ps2kbd_write(sc->ps2kbd_sc, *eax);
388         atkbdc_poll(sc);
389
390         pthread_mutex_unlock(&sc->mtx);
391
392         return (retval);
393 }
394
395 static int
396 atkbdc_sts_ctl_handler(struct vmctx *ctx, int vcpu, int in, int port,
397     int bytes, uint32_t *eax, void *arg)
398 {
399         struct atkbdc_softc *sc;
400         int     error, retval;
401
402         if (bytes != 1)
403                 return (-1);
404
405         sc = arg;
406         retval = 0;
407
408         pthread_mutex_lock(&sc->mtx);
409
410         if (in) {
411                 /* read status register */
412                 *eax = sc->status;
413                 pthread_mutex_unlock(&sc->mtx);
414                 return (retval);
415         }
416
417
418         sc->curcmd = 0;
419         sc->status |= KBDS_CTRL_FLAG;
420         sc->ctrlbyte = 0;
421
422         switch (*eax) {
423         case KBDC_GET_COMMAND_BYTE:
424                 sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[0];
425                 break;
426         case KBDC_TEST_CTRL:
427                 sc->ctrlbyte = CTRL_CMD_FLAG | 0x55;
428                 break;
429         case KBDC_TEST_AUX_PORT:
430         case KBDC_TEST_KBD_PORT:
431                 sc->ctrlbyte = CTRL_CMD_FLAG | 0;
432                 break;
433         case KBDC_READ_INPORT:
434                 sc->ctrlbyte = CTRL_CMD_FLAG | 0;
435                 break;
436         case KBDC_READ_OUTPORT:
437                 sc->ctrlbyte = CTRL_CMD_FLAG | sc->outport;
438                 break;
439         case KBDC_SET_COMMAND_BYTE:
440         case KBDC_WRITE_OUTPORT:
441         case KBDC_WRITE_KBD_OUTBUF:
442         case KBDC_WRITE_AUX_OUTBUF:
443                 sc->curcmd = *eax;
444                 break;
445         case KBDC_DISABLE_KBD_PORT:
446                 sc->ram[0] |= KBD_DISABLE_KBD_PORT;
447                 break;
448         case KBDC_ENABLE_KBD_PORT:
449                 sc->ram[0] &= ~KBD_DISABLE_KBD_PORT;
450                 if (sc->kbd.bcnt > 0)
451                         sc->status |= KBDS_KBD_BUFFER_FULL;
452                 atkbdc_poll(sc);
453                 break;
454         case KBDC_WRITE_TO_AUX:
455                 sc->curcmd = *eax;
456                 break;
457         case KBDC_DISABLE_AUX_PORT:
458                 sc->ram[0] |= KBD_DISABLE_AUX_PORT;
459                 ps2mouse_toggle(sc->ps2mouse_sc, 0);
460                 sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
461                 sc->outport &= ~KBDS_AUX_BUFFER_FULL;
462                 break;
463         case KBDC_ENABLE_AUX_PORT:
464                 sc->ram[0] &= ~KBD_DISABLE_AUX_PORT;
465                 ps2mouse_toggle(sc->ps2mouse_sc, 1);
466                 if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0)
467                         sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
468                 break;
469         case KBDC_RESET:                /* Pulse "reset" line */
470                 error = vm_suspend(ctx, VM_SUSPEND_RESET);
471                 assert(error == 0 || errno == EALREADY);
472                 break;
473         default:
474                 if (*eax >= 0x21 && *eax <= 0x3f) {
475                         /* read "byte N" from RAM */
476                         int     byten;
477
478                         byten = (*eax - 0x20) & 0x1f;
479                         sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[byten];
480                 }
481                 break;
482         }
483
484         pthread_mutex_unlock(&sc->mtx);
485
486         if (sc->ctrlbyte != 0) {
487                 sc->status |= KBDS_KBD_BUFFER_FULL;
488                 sc->status &= ~KBDS_AUX_BUFFER_FULL;
489                 atkbdc_assert_kbd_intr(sc);
490         } else if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0 &&
491                    (sc->ram[0] & KBD_DISABLE_AUX_PORT) == 0) {
492                 sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
493                 atkbdc_assert_aux_intr(sc);
494         } else if (sc->kbd.bcnt > 0 && (sc->ram[0] & KBD_DISABLE_KBD_PORT) == 0) {
495                 sc->status |= KBDS_KBD_BUFFER_FULL;
496                 atkbdc_assert_kbd_intr(sc);
497         }
498
499         return (retval);
500 }
501
502 void
503 atkbdc_event(struct atkbdc_softc *sc, int iskbd)
504 {
505         pthread_mutex_lock(&sc->mtx);
506
507         if (iskbd)
508                 atkbdc_kbd_poll(sc);
509         else
510                 atkbdc_aux_poll(sc);
511         pthread_mutex_unlock(&sc->mtx);
512 }
513
514 void
515 atkbdc_init(struct vmctx *ctx)
516 {
517         struct inout_port iop;
518         struct atkbdc_softc *sc;
519         int error;
520
521         sc = calloc(1, sizeof(struct atkbdc_softc));
522         sc->ctx = ctx;
523
524         pthread_mutex_init(&sc->mtx, NULL);
525
526         bzero(&iop, sizeof(struct inout_port));
527         iop.name = "atkdbc";
528         iop.port = KBD_STS_CTL_PORT;
529         iop.size = 1;
530         iop.flags = IOPORT_F_INOUT;
531         iop.handler = atkbdc_sts_ctl_handler;
532         iop.arg = sc;
533
534         error = register_inout(&iop);
535         assert(error == 0);
536
537         bzero(&iop, sizeof(struct inout_port));
538         iop.name = "atkdbc";
539         iop.port = KBD_DATA_PORT;
540         iop.size = 1;
541         iop.flags = IOPORT_F_INOUT;
542         iop.handler = atkbdc_data_handler;
543         iop.arg = sc;
544
545         error = register_inout(&iop);
546         assert(error == 0);
547
548         pci_irq_reserve(KBD_DEV_IRQ);
549         sc->kbd.irq = KBD_DEV_IRQ;
550
551         pci_irq_reserve(AUX_DEV_IRQ);
552         sc->aux.irq = AUX_DEV_IRQ;
553
554         sc->ps2kbd_sc = ps2kbd_init(sc);
555         sc->ps2mouse_sc = ps2mouse_init(sc);
556
557 #ifdef BHYVE_SNAPSHOT
558         assert(atkbdc_sc == NULL);
559         atkbdc_sc = sc;
560 #endif
561 }
562
563 #ifdef BHYVE_SNAPSHOT
564 int
565 atkbdc_snapshot(struct vm_snapshot_meta *meta)
566 {
567         int ret;
568
569         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->status, meta, ret, done);
570         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->outport, meta, ret, done);
571         SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->ram,
572                               sizeof(atkbdc_sc->ram), meta, ret, done);
573         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->curcmd, meta, ret, done);
574         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->ctrlbyte, meta, ret, done);
575         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd, meta, ret, done);
576
577         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq_active, meta, ret, done);
578         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq, meta, ret, done);
579         SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->kbd.buffer,
580                               sizeof(atkbdc_sc->kbd.buffer), meta, ret, done);
581         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.brd, meta, ret, done);
582         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bwr, meta, ret, done);
583         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bcnt, meta, ret, done);
584
585         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq_active, meta, ret, done);
586         SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq, meta, ret, done);
587
588         ret = ps2kbd_snapshot(atkbdc_sc->ps2kbd_sc, meta);
589         if (ret != 0)
590                 goto done;
591
592         ret = ps2mouse_snapshot(atkbdc_sc->ps2mouse_sc, meta);
593
594 done:
595         return (ret);
596 }
597 #endif
598
599 static void
600 atkbdc_dsdt(void)
601 {
602
603         dsdt_line("");
604         dsdt_line("Device (KBD)");
605         dsdt_line("{");
606         dsdt_line("  Name (_HID, EisaId (\"PNP0303\"))");
607         dsdt_line("  Name (_CRS, ResourceTemplate ()");
608         dsdt_line("  {");
609         dsdt_indent(2);
610         dsdt_fixed_ioport(KBD_DATA_PORT, 1);
611         dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1);
612         dsdt_fixed_irq(1);
613         dsdt_unindent(2);
614         dsdt_line("  })");
615         dsdt_line("}");
616
617         dsdt_line("");
618         dsdt_line("Device (MOU)");
619         dsdt_line("{");
620         dsdt_line("  Name (_HID, EisaId (\"PNP0F13\"))");
621         dsdt_line("  Name (_CRS, ResourceTemplate ()");
622         dsdt_line("  {");
623         dsdt_indent(2);
624         dsdt_fixed_ioport(KBD_DATA_PORT, 1);
625         dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1);
626         dsdt_fixed_irq(12);
627         dsdt_unindent(2);
628         dsdt_line("  })");
629         dsdt_line("}");
630 }
631 LPC_DSDT(atkbdc_dsdt);
632