xref: /openbsd/sys/dev/ic/pckbc.c (revision 771fbea0)
1 /* $OpenBSD: pckbc.c,v 1.53 2019/11/30 18:18:34 cheloha Exp $ */
2 /* $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */
3 
4 /*
5  * Copyright (c) 1998
6  *	Matthias Drochner.  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 ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/timeout.h>
32 #include <sys/kernel.h>
33 #include <sys/device.h>
34 #include <sys/malloc.h>
35 #include <sys/errno.h>
36 #include <sys/queue.h>
37 
38 #include <machine/bus.h>
39 #include <machine/cpu.h>
40 
41 #include <dev/ic/i8042reg.h>
42 #include <dev/ic/pckbcvar.h>
43 
44 #include "pckbd.h"
45 
46 #if NPCKBD > 0
47 #include <dev/pckbc/pckbdvar.h>
48 #endif
49 
50 #ifdef PCKBCDEBUG
51 #define DPRINTF(x...)	do { printf(x); } while (0);
52 #else
53 #define DPRINTF(x...)
54 #endif
55 
56 /* descriptor for one device command */
57 struct pckbc_devcmd {
58 	TAILQ_ENTRY(pckbc_devcmd) next;
59 	int flags;
60 #define KBC_CMDFLAG_SYNC 1 /* give descriptor back to caller */
61 #define KBC_CMDFLAG_SLOW 2
62 #define KBC_CMDFLAG_QUEUED 4 /* descriptor on cmdqueue */
63 	u_char cmd[4];
64 	int cmdlen, cmdidx, retries;
65 	u_char response[4];
66 	int status, responselen, responseidx;
67 };
68 
69 /* data per slave device */
70 struct pckbc_slotdata {
71 	int polling; /* don't read data port in interrupt handler */
72 	TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* active commands */
73 	TAILQ_HEAD(, pckbc_devcmd) freequeue; /* free commands */
74 #define NCMD 5
75 	struct pckbc_devcmd cmds[NCMD];
76 };
77 
78 #define CMD_IN_QUEUE(q) (!TAILQ_EMPTY(&(q)->cmdqueue))
79 
80 void pckbc_init_slotdata(struct pckbc_slotdata *);
81 int pckbc_attach_slot(struct pckbc_softc *, pckbc_slot_t, int);
82 int pckbc_submatch_locators(struct device *, void *, void *);
83 int pckbc_submatch(struct device *, void *, void *);
84 int pckbcprint(void *, const char *);
85 
86 struct pckbc_internal pckbc_consdata;
87 int pckbc_console_attached;
88 
89 int pckbc_console;
90 static struct pckbc_slotdata pckbc_cons_slotdata;
91 
92 static int pckbc_wait_output(bus_space_tag_t, bus_space_handle_t);
93 
94 static int pckbc_get8042cmd(struct pckbc_internal *);
95 static int pckbc_put8042cmd(struct pckbc_internal *);
96 static int pckbc_send_devcmd(struct pckbc_internal *, pckbc_slot_t,
97 				  u_char);
98 static void pckbc_poll_cmd1(struct pckbc_internal *, pckbc_slot_t,
99 				 struct pckbc_devcmd *);
100 
101 void pckbc_cleanqueues(struct pckbc_internal *);
102 void pckbc_cleanqueue(struct pckbc_slotdata *);
103 void pckbc_cleanup(void *);
104 void pckbc_poll(void *);
105 int pckbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char);
106 void pckbc_start(struct pckbc_internal *, pckbc_slot_t);
107 int pckbcintr_internal(struct pckbc_internal *, struct pckbc_softc *);
108 
109 const char *pckbc_slot_names[] = { "kbd", "aux" };
110 
111 #define KBC_DEVCMD_ACK		0xfa
112 #define KBC_DEVCMD_RESEND	0xfe
113 #define KBC_DEVCMD_BAT_DONE	0xaa
114 #define KBC_DEVCMD_BAT_FAIL	0xfc
115 
116 #define	KBD_DELAY	DELAY(8)
117 
118 static inline int
119 pckbc_wait_output(bus_space_tag_t iot, bus_space_handle_t ioh_c)
120 {
121 	u_int i;
122 
123 	for (i = 100000; i; i--)
124 		if (!(bus_space_read_1(iot, ioh_c, 0) & KBS_IBF)) {
125 			KBD_DELAY;
126 			return (1);
127 		}
128 	return (0);
129 }
130 
131 int
132 pckbc_send_cmd(bus_space_tag_t iot, bus_space_handle_t ioh_c, u_char val)
133 {
134 	if (!pckbc_wait_output(iot, ioh_c))
135 		return (0);
136 	bus_space_write_1(iot, ioh_c, 0, val);
137 	return (1);
138 }
139 
140 int
141 pckbc_poll_data1(bus_space_tag_t iot, bus_space_handle_t ioh_d,
142     bus_space_handle_t ioh_c, pckbc_slot_t slot, int checkaux)
143 {
144 	int i;
145 	u_char stat;
146 
147 	/* polls for ~100ms */
148 	for (i = 100; i; i--, delay(1000)) {
149 		stat = bus_space_read_1(iot, ioh_c, 0);
150 		if (stat & KBS_DIB) {
151 			register u_char c;
152 
153 			KBD_DELAY;
154 			CPU_BUSY_CYCLE();
155 			c = bus_space_read_1(iot, ioh_d, 0);
156 			if (checkaux && (stat & KBS_AUXDATA)) {
157 				if (slot != PCKBC_AUX_SLOT) {
158 					DPRINTF("lost aux 0x%x\n", c);
159 					continue;
160 				}
161 			} else {
162 				if (slot == PCKBC_AUX_SLOT) {
163 					DPRINTF("lost kbd 0x%x\n", c);
164 					continue;
165 				} else if (stat & KBS_AUXDATA) {
166 					DPRINTF("discard aux data 0x%x\n", c);
167 					continue;
168 				}
169 			}
170 			return (c);
171 		}
172 	}
173 	return (-1);
174 }
175 
176 /*
177  * Get the current command byte.
178  */
179 static int
180 pckbc_get8042cmd(struct pckbc_internal *t)
181 {
182 	bus_space_tag_t iot = t->t_iot;
183 	bus_space_handle_t ioh_d = t->t_ioh_d;
184 	bus_space_handle_t ioh_c = t->t_ioh_c;
185 	int data;
186 
187 	if (!pckbc_send_cmd(iot, ioh_c, K_RDCMDBYTE))
188 		return (0);
189 	data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT,
190 				t->t_haveaux);
191 	if (data == -1)
192 		return (0);
193 	t->t_cmdbyte = data;
194 	return (1);
195 }
196 
197 /*
198  * Pass command byte to keyboard controller (8042).
199  */
200 static int
201 pckbc_put8042cmd(struct pckbc_internal *t)
202 {
203 	bus_space_tag_t iot = t->t_iot;
204 	bus_space_handle_t ioh_d = t->t_ioh_d;
205 	bus_space_handle_t ioh_c = t->t_ioh_c;
206 
207 	if (!pckbc_send_cmd(iot, ioh_c, K_LDCMDBYTE))
208 		return (0);
209 	if (!pckbc_wait_output(iot, ioh_c))
210 		return (0);
211 	bus_space_write_1(iot, ioh_d, 0, t->t_cmdbyte);
212 	return (1);
213 }
214 
215 static int
216 pckbc_send_devcmd(struct pckbc_internal *t, pckbc_slot_t slot, u_char val)
217 {
218 	bus_space_tag_t iot = t->t_iot;
219 	bus_space_handle_t ioh_d = t->t_ioh_d;
220 	bus_space_handle_t ioh_c = t->t_ioh_c;
221 
222 	if (slot == PCKBC_AUX_SLOT) {
223 		if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE))
224 			return (0);
225 	}
226 	if (!pckbc_wait_output(iot, ioh_c))
227 		return (0);
228 	bus_space_write_1(iot, ioh_d, 0, val);
229 	return (1);
230 }
231 
232 int
233 pckbc_is_console(bus_space_tag_t iot, bus_addr_t addr)
234 {
235 	if (pckbc_console && !pckbc_console_attached &&
236 	    pckbc_consdata.t_iot == iot &&
237 	    pckbc_consdata.t_addr == addr)
238 		return (1);
239 	return (0);
240 }
241 
242 int
243 pckbc_submatch_locators(struct device *parent, void *match, void *aux)
244 {
245 	struct cfdata *cf = match;
246 	struct pckbc_attach_args *pa = aux;
247 
248 	if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT &&
249 	    cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot)
250 		return (0);
251 	return (1);
252 }
253 
254 int
255 pckbc_submatch(struct device *parent, void *match, void *aux)
256 {
257 	struct cfdata *cf = match;
258 
259 	if (pckbc_submatch_locators(parent, match, aux) == 0)
260 		return (0);
261 	return ((*cf->cf_attach->ca_match)(parent, cf, aux));
262 }
263 
264 int
265 pckbc_attach_slot(struct pckbc_softc *sc, pckbc_slot_t slot, int force)
266 {
267 	struct pckbc_internal *t = sc->id;
268 	struct pckbc_attach_args pa;
269 	int found;
270 
271 	pa.pa_tag = t;
272 	pa.pa_slot = slot;
273 	found = (config_found_sm((struct device *)sc, &pa, pckbcprint,
274 	    force ? pckbc_submatch_locators : pckbc_submatch) != NULL);
275 
276 	if ((found || slot == PCKBC_AUX_SLOT) && !t->t_slotdata[slot]) {
277 		t->t_slotdata[slot] = malloc(sizeof(struct pckbc_slotdata),
278 					     M_DEVBUF, M_NOWAIT);
279 		if (t->t_slotdata[slot] == NULL)
280 			return 0;
281 		pckbc_init_slotdata(t->t_slotdata[slot]);
282 
283 		if (!found && slot == PCKBC_AUX_SLOT) {
284 			/*
285 			 * Some machines don't handle disabling the aux slot
286 			 * completely and still generate data when the mouse is
287 			 * moved, so setup a dummy interrupt handler to discard
288 			 * this slot's data.
289 			 */
290 			pckbc_set_inputhandler(t, PCKBC_AUX_SLOT, NULL, sc,
291 			    NULL);
292 			found = 1;
293 		}
294 	}
295 	return (found);
296 }
297 
298 void
299 pckbc_attach(struct pckbc_softc *sc, int flags)
300 {
301 	struct pckbc_internal *t;
302 	bus_space_tag_t iot;
303 	bus_space_handle_t ioh_d, ioh_c;
304 	int haskbd = 0, res;
305 	u_char cmdbits = 0;
306 
307 	t = sc->id;
308 	iot = t->t_iot;
309 	ioh_d = t->t_ioh_d;
310 	ioh_c = t->t_ioh_c;
311 
312 	if (pckbc_console == 0) {
313 		timeout_set(&t->t_cleanup, pckbc_cleanup, t);
314 		timeout_set(&t->t_poll, pckbc_poll, t);
315 	}
316 
317 	/* flush */
318 	(void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0);
319 
320 	/* set initial cmd byte */
321 	if (!pckbc_put8042cmd(t)) {
322 #if defined(__i386__) || defined(__amd64__)
323 		if (!ISSET(flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) {
324 			pckbc_release_console();
325 			return;
326 		}
327 #endif
328 		printf("kbc: cmd word write error\n");
329 		return;
330 	}
331 
332 /*
333  * XXX Don't check the keyboard port. There are broken keyboard controllers
334  * which don't pass the test but work normally otherwise.
335  */
336 #if 0
337 	/*
338 	 * check kbd port ok
339 	 */
340 	if (!pckbc_send_cmd(iot, ioh_c, KBC_KBDTEST))
341 		return;
342 	res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0);
343 
344 	/*
345 	 * Normally, we should get a "0" here.
346 	 * But there are keyboard controllers behaving differently.
347 	 */
348 	if (res == 0 || res == 0xfa || res == 0x01 || res == 0xab) {
349 #ifdef PCKBCDEBUG
350 		if (res != 0)
351 			printf("kbc: returned %x on kbd slot test\n", res);
352 #endif
353 		if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) {
354 			cmdbits |= KC8_KENABLE;
355 			haskbd = 1;
356 		}
357 	} else {
358 		printf("kbc: kbd port test: %x\n", res);
359 		return;
360 	}
361 #else
362 	if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) {
363 		cmdbits |= KC8_KENABLE;
364 		haskbd = 1;
365 	}
366 #endif /* 0 */
367 
368 	/*
369 	 * Check aux port ok.
370 	 * Avoid KBC_AUXTEST because it hangs some older controllers
371 	 * (eg UMC880?).
372 	 */
373 	if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO)) {
374 		printf("kbc: aux echo error 1\n");
375 		goto nomouse;
376 	}
377 	if (!pckbc_wait_output(iot, ioh_c)) {
378 		printf("kbc: aux echo error 2\n");
379 		goto nomouse;
380 	}
381 	bus_space_write_1(iot, ioh_d, 0, 0x5a);	/* a random value */
382 	res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, 1);
383 
384 	if (ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) {
385 		/*
386 		 * The following code is necessary to find the aux port on the
387 		 * oqo-1 machine, among others.  However if confuses old
388 		 * (non-ps/2) keyboard controllers (at least UMC880x again).
389 		 */
390 		if (res == -1) {
391 			/* Read of aux echo timed out, try again */
392 			if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE))
393 				goto nomouse;
394 			if (!pckbc_wait_output(iot, ioh_c))
395 				goto nomouse;
396 			bus_space_write_1(iot, ioh_d, 0, 0x5a);
397 			res = pckbc_poll_data1(iot, ioh_d, ioh_c,
398 			    PCKBC_AUX_SLOT, 1);
399 			DPRINTF("kbc: aux echo: %x\n", res);
400 		}
401 	}
402 
403 	if (res != -1) {
404 		/*
405 		 * In most cases, the 0x5a gets echoed.
406 		 * Some old controllers (Gateway 2000 circa 1993)
407 		 * return 0xfe here.
408 		 * We are satisfied if there is anything in the
409 		 * aux output buffer.
410 		 */
411 		DPRINTF("kbc: aux echo: %x\n", res);
412 		t->t_haveaux = 1;
413 		if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT, 0))
414 			cmdbits |= KC8_MENABLE;
415 	}
416 #ifdef PCKBCDEBUG
417 	else
418 		printf("kbc: aux echo test failed\n");
419 #endif
420 
421 #if defined(__i386__) || defined(__amd64__)
422 	if (haskbd == 0 && !ISSET(flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) {
423 		if (t->t_haveaux) {
424 			if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 1))
425 				cmdbits |= KC8_KENABLE;
426 		} else {
427 			pckbc_release_console();
428 		}
429 	}
430 #endif
431 
432 nomouse:
433 	/* enable needed interrupts */
434 	t->t_cmdbyte |= cmdbits;
435 	if (!pckbc_put8042cmd(t))
436 		printf("kbc: cmd word write error\n");
437 }
438 
439 int
440 pckbcprint(void *aux, const char *pnp)
441 {
442 	struct pckbc_attach_args *pa = aux;
443 
444 	if (!pnp)
445 		printf(" (%s slot)", pckbc_slot_names[pa->pa_slot]);
446 	return (QUIET);
447 }
448 
449 void
450 pckbc_release_console(void)
451 {
452 #if defined(__i386__) || defined(__amd64__)
453 	/*
454 	 * If there is no keyboard present, yet we are the console,
455 	 * we might be on a legacy-free PC where the PS/2 emulated
456 	 * keyboard was elected as console, but went away as soon
457 	 * as the USB controller drivers attached.
458 	 *
459 	 * In that case, we want to release ourselves from console
460 	 * duties, unless we have been able to attach a mouse,
461 	 * which would mean this is a real PS/2 controller
462 	 * afterwards.
463 	 */
464 	if (pckbc_console != 0) {
465 		extern void wscn_input_init(int);
466 
467 		pckbc_console = 0;
468 		wscn_input_init(1);
469 	}
470 #endif
471 }
472 
473 void
474 pckbc_init_slotdata(struct pckbc_slotdata *q)
475 {
476 	int i;
477 	TAILQ_INIT(&q->cmdqueue);
478 	TAILQ_INIT(&q->freequeue);
479 
480 	for (i = 0; i < NCMD; i++) {
481 		TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next);
482 	}
483 	q->polling = 0;
484 }
485 
486 void
487 pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot)
488 {
489 	struct pckbc_internal *t = self;
490 
491 	(void) pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c,
492 	    slot, t->t_haveaux);
493 }
494 
495 int
496 pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot)
497 {
498 	struct pckbc_internal *t = self;
499 	struct pckbc_slotdata *q = t->t_slotdata[slot];
500 	int c;
501 
502 	c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c,
503 			     slot, t->t_haveaux);
504 	if (c != -1 && q && CMD_IN_QUEUE(q)) {
505 		/* we jumped into a running command - try to
506 		 deliver the response */
507 		if (pckbc_cmdresponse(t, slot, c))
508 			return (-1);
509 	}
510 	return (c);
511 }
512 
513 /*
514  * set scancode translation on
515  */
516 int
517 pckbc_xt_translation(pckbc_tag_t self)
518 {
519 	struct pckbc_internal *t = self;
520 
521 	if (ISSET(t->t_flags, PCKBC_CANT_TRANSLATE))
522 		return (-1);
523 
524 	if (t->t_cmdbyte & KC8_TRANS)
525 		return (0);
526 
527 	t->t_cmdbyte |= KC8_TRANS;
528 	if (!pckbc_put8042cmd(t))
529 		return (-1);
530 
531 	/* read back to be sure */
532 	if (!pckbc_get8042cmd(t))
533 		return (-1);
534 
535 	return (t->t_cmdbyte & KC8_TRANS) ? (0) : (-1);
536 }
537 
538 static struct pckbc_portcmd {
539 	u_char cmd_en, cmd_dis;
540 } pckbc_portcmd[2] = {
541 	{
542 		KBC_KBDENABLE, KBC_KBDDISABLE,
543 	}, {
544 		KBC_AUXENABLE, KBC_AUXDISABLE,
545 	}
546 };
547 
548 void
549 pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on)
550 {
551 	struct pckbc_internal *t = (struct pckbc_internal *)self;
552 	struct pckbc_portcmd *cmd;
553 
554 	cmd = &pckbc_portcmd[slot];
555 
556 	if (!pckbc_send_cmd(t->t_iot, t->t_ioh_c,
557 			    on ? cmd->cmd_en : cmd->cmd_dis))
558 		printf("pckbc_slot_enable(%d) failed\n", on);
559 
560 	if (slot == PCKBC_KBD_SLOT) {
561 		if (on)
562 			timeout_add_sec(&t->t_poll, 1);
563 		else
564 			timeout_del(&t->t_poll);
565 	}
566 }
567 
568 void
569 pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on)
570 {
571 	struct pckbc_internal *t = (struct pckbc_internal *)self;
572 
573 	t->t_slotdata[slot]->polling = on;
574 
575 	if (!on) {
576                 int s;
577 
578                 /*
579                  * If disabling polling on a device that's been configured,
580                  * make sure there are no bytes left in the FIFO, holding up
581                  * the interrupt line.  Otherwise we won't get any further
582                  * interrupts.
583                  */
584 		if (t->t_sc) {
585 			s = spltty();
586 			pckbcintr_internal(t, t->t_sc);
587 			splx(s);
588 		}
589 	}
590 }
591 
592 /*
593  * Pass command to device, poll for ACK and data.
594  * to be called at spltty()
595  */
596 static void
597 pckbc_poll_cmd1(struct pckbc_internal *t, pckbc_slot_t slot,
598     struct pckbc_devcmd *cmd)
599 {
600 	bus_space_tag_t iot = t->t_iot;
601 	bus_space_handle_t ioh_d = t->t_ioh_d;
602 	bus_space_handle_t ioh_c = t->t_ioh_c;
603 	int i, c = 0;
604 
605 	while (cmd->cmdidx < cmd->cmdlen) {
606 		if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) {
607 			printf("pckbc_cmd: send error\n");
608 			cmd->status = EIO;
609 			return;
610 		}
611 		for (i = 10; i; i--) { /* 1s ??? */
612 			c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot,
613 					     t->t_haveaux);
614 			if (c != -1)
615 				break;
616 		}
617 
618 		switch (c) {
619 		case KBC_DEVCMD_ACK:
620 			cmd->cmdidx++;
621 			continue;
622 		/*
623 		 * Some legacy free PCs keep returning Basic Assurance Test
624 		 * (BAT) instead of something usable, so fail gracefully.
625 		 */
626 		case KBC_DEVCMD_RESEND:
627 		case KBC_DEVCMD_BAT_DONE:
628 		case KBC_DEVCMD_BAT_FAIL:
629 			DPRINTF("pckbc_cmd: %s\n",
630 			    c == KBC_DEVCMD_RESEND ? "RESEND": "BAT");
631 			if (cmd->retries++ < 5)
632 				continue;
633 
634 			DPRINTF("pckbc_cmd: cmd failed\n");
635 			cmd->status = ENXIO;
636 			return;
637 		case -1:
638 			DPRINTF("pckbc_cmd: timeout\n");
639 			cmd->status = EIO;
640 			return;
641 		default:
642 			DPRINTF("pckbc_cmd: lost 0x%x\n", c);
643 		}
644 	}
645 
646 	while (cmd->responseidx < cmd->responselen) {
647 		if (cmd->flags & KBC_CMDFLAG_SLOW)
648 			i = 100; /* 10s ??? */
649 		else
650 			i = 10; /* 1s ??? */
651 		while (i--) {
652 			c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot,
653 					     t->t_haveaux);
654 			if (c != -1)
655 				break;
656 		}
657 		if (c == -1) {
658 			DPRINTF("pckbc_cmd: no data\n");
659 			cmd->status = ETIMEDOUT;
660 			return;
661 		} else
662 			cmd->response[cmd->responseidx++] = c;
663 	}
664 }
665 
666 /* for use in autoconfiguration */
667 int
668 pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len,
669     int responselen, u_char *respbuf, int slow)
670 {
671 	struct pckbc_devcmd nc;
672 
673 	if ((len > 4) || (responselen > 4))
674 		return (EINVAL);
675 
676 	bzero(&nc, sizeof(nc));
677 	memcpy(nc.cmd, cmd, len);
678 	nc.cmdlen = len;
679 	nc.responselen = responselen;
680 	nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0);
681 
682 	pckbc_poll_cmd1(self, slot, &nc);
683 
684 	if (nc.status == 0 && respbuf)
685 		memcpy(respbuf, nc.response, responselen);
686 
687 	return (nc.status);
688 }
689 
690 /*
691  * Clean up a command queue, throw away everything.
692  */
693 void
694 pckbc_cleanqueue(struct pckbc_slotdata *q)
695 {
696 	struct pckbc_devcmd *cmd;
697 #ifdef PCKBCDEBUG
698 	int i;
699 #endif
700 
701 	while ((cmd = TAILQ_FIRST(&q->cmdqueue))) {
702 		TAILQ_REMOVE(&q->cmdqueue, cmd, next);
703 		cmd->flags &= ~KBC_CMDFLAG_QUEUED;
704 #ifdef PCKBCDEBUG
705 		printf("pckbc_cleanqueue: removing");
706 		for (i = 0; i < cmd->cmdlen; i++)
707 			printf(" %02x", cmd->cmd[i]);
708 		printf("\n");
709 #endif
710 		/*
711 		 * A synchronous command on the cmdqueue is currently owned by a
712 		 * sleeping proc. The same proc is responsible for putting it
713 		 * back on the freequeue once awake.
714 		 */
715 		if (cmd->flags & KBC_CMDFLAG_SYNC)
716 			continue;
717 
718 		TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
719 	}
720 }
721 
722 void
723 pckbc_cleanqueues(struct pckbc_internal *t)
724 {
725 	if (t->t_slotdata[PCKBC_KBD_SLOT])
726 		pckbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]);
727 	if (t->t_slotdata[PCKBC_AUX_SLOT])
728 		pckbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]);
729 }
730 
731 /*
732  * Timeout error handler: clean queues and data port.
733  * XXX could be less invasive.
734  */
735 void
736 pckbc_cleanup(void *self)
737 {
738 	struct pckbc_internal *t = self;
739 	int s;
740 
741 	printf("pckbc: command timeout\n");
742 
743 	s = spltty();
744 
745 	pckbc_cleanqueues(t);
746 
747 	while (bus_space_read_1(t->t_iot, t->t_ioh_c, 0) & KBS_DIB) {
748 		KBD_DELAY;
749 		(void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
750 	}
751 
752 	/* reset KBC? */
753 
754 	splx(s);
755 }
756 
757 /*
758  * Stop the keyboard controller when we are going to suspend
759  */
760 void
761 pckbc_stop(struct pckbc_softc *sc)
762 {
763 	struct pckbc_internal *t = sc->id;
764 
765 	timeout_del(&t->t_poll);
766 	pckbc_cleanqueues(t);
767 	timeout_del(&t->t_cleanup);
768 }
769 
770 /*
771  * Reset the keyboard controller in a violent fashion; normally done
772  * after suspend/resume when we do not trust the machine.
773  */
774 void
775 pckbc_reset(struct pckbc_softc *sc)
776 {
777 	struct pckbc_internal *t = sc->id;
778 	bus_space_tag_t iot = t->t_iot;
779 	bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c;
780 
781 	pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0);
782 	/* KBC selftest */
783 	if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0)
784 		return;
785 	pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0);
786 	(void)pckbc_put8042cmd(t);
787 	pckbcintr_internal(t->t_sc->id, t->t_sc);
788 }
789 
790 /*
791  * Pass command to device during normal operation.
792  * to be called at spltty()
793  */
794 void
795 pckbc_start(struct pckbc_internal *t, pckbc_slot_t slot)
796 {
797 	struct pckbc_slotdata *q = t->t_slotdata[slot];
798 	struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
799 
800 	if (q->polling) {
801 		do {
802 			pckbc_poll_cmd1(t, slot, cmd);
803 			if (cmd->status)
804 				printf("pckbc_start: command error\n");
805 
806 			TAILQ_REMOVE(&q->cmdqueue, cmd, next);
807 			cmd->flags &= ~KBC_CMDFLAG_QUEUED;
808 			if (cmd->flags & KBC_CMDFLAG_SYNC) {
809 				wakeup(cmd);
810 			} else {
811 				timeout_del(&t->t_cleanup);
812 				TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
813 			}
814 			cmd = TAILQ_FIRST(&q->cmdqueue);
815 		} while (cmd);
816 		return;
817 	}
818 
819 	if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) {
820 		printf("pckbc_start: send error\n");
821 		/* XXX what now? */
822 		return;
823 	}
824 }
825 
826 /*
827  * Handle command responses coming in asynchronously,
828  * return nonzero if valid response.
829  * to be called at spltty()
830  */
831 int
832 pckbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data)
833 {
834 	struct pckbc_slotdata *q = t->t_slotdata[slot];
835 	struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
836 #ifdef DIAGNOSTIC
837 	if (!cmd)
838 		panic("pckbc_cmdresponse: no active command");
839 #endif
840 	if (cmd->cmdidx < cmd->cmdlen) {
841 		if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND)
842 			return (0);
843 
844 		if (data == KBC_DEVCMD_RESEND) {
845 			if (cmd->retries++ < 5) {
846 				/* try again last command */
847 				goto restart;
848 			} else {
849 				DPRINTF("pckbc: cmd failed\n");
850 				cmd->status = ENXIO;
851 				/* dequeue */
852 			}
853 		} else {
854 			if (++cmd->cmdidx < cmd->cmdlen)
855 				goto restart;
856 			if (cmd->responselen)
857 				return (1);
858 			/* else dequeue */
859 		}
860 	} else if (cmd->responseidx < cmd->responselen) {
861 		cmd->response[cmd->responseidx++] = data;
862 		if (cmd->responseidx < cmd->responselen)
863 			return (1);
864 		/* else dequeue */
865 	} else
866 		return (0);
867 
868 	/* dequeue: */
869 	TAILQ_REMOVE(&q->cmdqueue, cmd, next);
870 	cmd->flags &= ~KBC_CMDFLAG_QUEUED;
871 	if (cmd->flags & KBC_CMDFLAG_SYNC) {
872 		wakeup(cmd);
873 	} else {
874 		timeout_del(&t->t_cleanup);
875 		TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
876 	}
877 	cmd = TAILQ_FIRST(&q->cmdqueue);
878 	if (cmd == NULL)
879 		return (1);
880 restart:
881 	pckbc_start(t, slot);
882 	return (1);
883 }
884 
885 /*
886  * Put command into the device's command queue, return zero or errno.
887  */
888 int
889 pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len,
890     int responselen, int sync, u_char *respbuf)
891 {
892 	struct pckbc_internal *t = self;
893 	struct pckbc_slotdata *q = t->t_slotdata[slot];
894 	struct pckbc_devcmd *nc;
895 	int s, isactive, res = 0;
896 
897 	if ((len > 4) || (responselen > 4))
898 		return (EINVAL);
899 	s = spltty();
900 	nc = TAILQ_FIRST(&q->freequeue);
901 	if (nc) {
902 		TAILQ_REMOVE(&q->freequeue, nc, next);
903 	}
904 	splx(s);
905 	if (!nc)
906 		return (ENOMEM);
907 
908 	bzero(nc, sizeof(*nc));
909 	memcpy(nc->cmd, cmd, len);
910 	nc->cmdlen = len;
911 	nc->responselen = responselen;
912 	nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0);
913 
914 	s = spltty();
915 
916 	if (q->polling && sync) {
917 		/*
918 		 * XXX We should poll until the queue is empty.
919 		 * But we don't come here normally, so make
920 		 * it simple and throw away everything.
921 		 */
922 		pckbc_cleanqueue(q);
923 	}
924 
925 	isactive = CMD_IN_QUEUE(q);
926 	nc->flags |= KBC_CMDFLAG_QUEUED;
927 	TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next);
928 	if (!isactive)
929 		pckbc_start(t, slot);
930 
931 	if (q->polling)
932 		res = (sync ? nc->status : 0);
933 	else if (sync) {
934 		if ((res = tsleep_nsec(nc, 0, "kbccmd", SEC_TO_NSEC(1)))) {
935 			pckbc_cleanup(t);
936 		} else {
937 			/*
938 			 * Under certain circumstances, such as during suspend,
939 			 * tsleep() becomes a no-op and the command is left on
940 			 * the cmdqueue.
941 			 */
942 			if (nc->flags & KBC_CMDFLAG_QUEUED) {
943 				TAILQ_REMOVE(&q->cmdqueue, nc, next);
944 				nc->flags &= ~KBC_CMDFLAG_QUEUED;
945 			}
946 			res = nc->status;
947 		}
948 	} else
949 		timeout_add_sec(&t->t_cleanup, 1);
950 
951 	if (sync) {
952 		if (respbuf)
953 			memcpy(respbuf, nc->response, responselen);
954 		TAILQ_INSERT_TAIL(&q->freequeue, nc, next);
955 	}
956 
957 	splx(s);
958 
959 	return (res);
960 }
961 
962 void
963 pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func,
964     void *arg, char *name)
965 {
966 	struct pckbc_internal *t = (struct pckbc_internal *)self;
967 	struct pckbc_softc *sc = t->t_sc;
968 
969 	if (slot >= PCKBC_NSLOTS)
970 		panic("pckbc_set_inputhandler: bad slot %d", slot);
971 
972 	sc->inputhandler[slot] = func;
973 	sc->inputarg[slot] = arg;
974 	sc->subname[slot] = name;
975 
976 	if (pckbc_console && slot == PCKBC_KBD_SLOT)
977 		timeout_add_sec(&t->t_poll, 1);
978 }
979 
980 void
981 pckbc_poll(void *v)
982 {
983 	struct pckbc_internal *t = v;
984 	int s;
985 
986 	s = spltty();
987 	(void)pckbcintr_internal(t, t->t_sc);
988 	timeout_add_sec(&t->t_poll, 1);
989 	splx(s);
990 }
991 
992 int
993 pckbcintr(void *vsc)
994 {
995 	struct pckbc_softc *sc = (struct pckbc_softc *)vsc;
996 
997 	return (pckbcintr_internal(sc->id, sc));
998 }
999 
1000 int
1001 pckbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc)
1002 {
1003 	u_char stat;
1004 	pckbc_slot_t slot;
1005 	struct pckbc_slotdata *q;
1006 	int served = 0, data;
1007 
1008 	/* reschedule timeout further into the idle times */
1009 	if (timeout_pending(&t->t_poll))
1010 		timeout_add_sec(&t->t_poll, 1);
1011 
1012 	for(;;) {
1013 		stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0);
1014 		if (!(stat & KBS_DIB))
1015 			break;
1016 
1017 		served = 1;
1018 
1019 		slot = (t->t_haveaux && (stat & KBS_AUXDATA)) ?
1020 		    PCKBC_AUX_SLOT : PCKBC_KBD_SLOT;
1021 		q = t->t_slotdata[slot];
1022 
1023 		if (!q) {
1024 			/* XXX do something for live insertion? */
1025 #ifdef PCKBCDEBUG
1026 			printf("pckbcintr: no dev for slot %d\n", slot);
1027 #endif
1028 			KBD_DELAY;
1029 			(void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
1030 			continue;
1031 		}
1032 
1033 		if (q->polling)
1034 			break; /* pckbc_poll_data() will get it */
1035 
1036 		KBD_DELAY;
1037 		data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0);
1038 
1039 		if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data))
1040 			continue;
1041 
1042 		if (sc != NULL) {
1043 			if (sc->inputhandler[slot])
1044 				(*sc->inputhandler[slot])(sc->inputarg[slot],
1045 				    data);
1046 #ifdef PCKBCDEBUG
1047 			else
1048 				printf("pckbcintr: slot %d lost %d\n",
1049 				    slot, data);
1050 #endif
1051 		}
1052 	}
1053 
1054 	return (served);
1055 }
1056 
1057 int
1058 pckbc_cnattach(bus_space_tag_t iot, bus_addr_t addr, bus_size_t cmd_offset,
1059     int flags)
1060 {
1061 	bus_space_handle_t ioh_d, ioh_c;
1062 	int res = 0;
1063 
1064 	if (bus_space_map(iot, addr + KBDATAP, 1, 0, &ioh_d))
1065                 return (ENXIO);
1066 	if (bus_space_map(iot, addr + cmd_offset, 1, 0, &ioh_c)) {
1067 		bus_space_unmap(iot, ioh_d, 1);
1068                 return (ENXIO);
1069 	}
1070 
1071 	pckbc_consdata.t_iot = iot;
1072 	pckbc_consdata.t_ioh_d = ioh_d;
1073 	pckbc_consdata.t_ioh_c = ioh_c;
1074 	pckbc_consdata.t_addr = addr;
1075 	pckbc_consdata.t_flags = flags;
1076 	timeout_set(&pckbc_consdata.t_cleanup, pckbc_cleanup, &pckbc_consdata);
1077 	timeout_set(&pckbc_consdata.t_poll, pckbc_poll, &pckbc_consdata);
1078 
1079 	/* flush */
1080 	(void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0);
1081 
1082 	/* selftest? */
1083 
1084 	/* init cmd byte, enable ports */
1085 	pckbc_consdata.t_cmdbyte = KC8_CPU;
1086 	if (!pckbc_put8042cmd(&pckbc_consdata)) {
1087 		printf("kbc: cmd word write error\n");
1088 		res = EIO;
1089 	}
1090 
1091 	if (!res) {
1092 #if (NPCKBD > 0)
1093 		res = pckbd_cnattach(&pckbc_consdata);
1094 #else
1095 		res = ENXIO;
1096 #endif /* NPCKBD > 0 */
1097 	}
1098 
1099 	if (res) {
1100 		bus_space_unmap(iot, pckbc_consdata.t_ioh_d, 1);
1101 		bus_space_unmap(iot, pckbc_consdata.t_ioh_c, 1);
1102 	} else {
1103 		pckbc_consdata.t_slotdata[PCKBC_KBD_SLOT] = &pckbc_cons_slotdata;
1104 		pckbc_init_slotdata(&pckbc_cons_slotdata);
1105 		pckbc_console = 1;
1106 	}
1107 
1108 	return (res);
1109 }
1110 
1111 struct cfdriver pckbc_cd = {
1112 	NULL, "pckbc", DV_DULL
1113 };
1114