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