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