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