xref: /illumos-gate/usr/src/cmd/bhyve/atkbdc.c (revision 32640292)
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