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