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