kernel - Fix keyboard probe for chromebooks
[dragonfly.git] / sys / dev / misc / kbd / atkbdc.c
CommitLineData
d4e80d19
MD
1/*
2 * (MPSAFE)
3 *
984263bc
MD
4 * Copyright (c) 1996-1999
5 * Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
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 * 3. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: src/sys/dev/kbd/atkbdc.c,v 1.5.2.2 2002/03/31 11:02:02 murray Exp $
33 * from kbdio.c,v 1.13 1998/09/25 11:55:46 yokota Exp
34 */
35
984263bc 36#include "opt_kbd.h"
1f2de5d4 37#include "use_atkbdc.h"
984263bc
MD
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/bus.h>
42#include <sys/malloc.h>
43#include <sys/syslog.h>
984263bc
MD
44#include <sys/rman.h>
45
46#include <machine/clock.h>
47
1f2de5d4 48#include "atkbdcreg.h"
984263bc 49
1f2de5d4 50#include <bus/isa/isareg.h>
984263bc 51
22ff886e
AH
52#if 0
53#define lwkt_gettoken(x)
54#define lwkt_reltoken(x)
55#endif
56
984263bc
MD
57/* constants */
58
59#define MAXKBDC MAX(NATKBDC, 1) /* XXX */
60
61/* macros */
62
63#ifndef MAX
64#define MAX(x, y) ((x) > (y) ? (x) : (y))
65#endif
66
67#define kbdcp(p) ((atkbdc_softc_t *)(p))
68#define nextq(i) (((i) + 1) % KBDQ_BUFSIZE)
69#define availq(q) ((q)->head != (q)->tail)
70#if KBDIO_DEBUG >= 2
71#define emptyq(q) ((q)->tail = (q)->head = (q)->qcount = 0)
72#else
73#define emptyq(q) ((q)->tail = (q)->head = 0)
74#endif
75
76#define read_data(k) (bus_space_read_1((k)->iot, (k)->ioh0, 0))
77#define read_status(k) (bus_space_read_1((k)->iot, (k)->ioh1, 0))
78#define write_data(k, d) \
79 (bus_space_write_1((k)->iot, (k)->ioh0, 0, (d)))
80#define write_command(k, d) \
81 (bus_space_write_1((k)->iot, (k)->ioh1, 0, (d)))
82
83/* local variables */
84
85/*
86 * We always need at least one copy of the kbdc_softc struct for the
87 * low-level console. As the low-level console accesses the keyboard
88 * controller before kbdc, and all other devices, is probed, we
89 * statically allocate one entry. XXX
90 */
91static atkbdc_softc_t default_kbdc;
92static atkbdc_softc_t *atkbdc_softc[MAXKBDC] = { &default_kbdc };
93
94static int verbose = KBDIO_DEBUG;
95
96/* function prototypes */
97
98static int atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag,
99 bus_space_handle_t h0, bus_space_handle_t h1);
5c4d4c9d
MD
100static int addq(kbdkqueue *q, int c);
101static int removeq(kbdkqueue *q);
984263bc
MD
102static int wait_while_controller_busy(atkbdc_softc_t *kbdc);
103static int wait_for_data(atkbdc_softc_t *kbdc);
104static int wait_for_kbd_data(atkbdc_softc_t *kbdc);
105static int wait_for_kbd_ack(atkbdc_softc_t *kbdc);
106static int wait_for_aux_data(atkbdc_softc_t *kbdc);
107static int wait_for_aux_ack(atkbdc_softc_t *kbdc);
108
3d8ba483
SW
109atkbdc_softc_t *
110atkbdc_get_softc(int unit)
984263bc
MD
111{
112 atkbdc_softc_t *sc;
113
c157ff7a 114 if (unit >= NELEM(atkbdc_softc))
984263bc
MD
115 return NULL;
116 sc = atkbdc_softc[unit];
117 if (sc == NULL) {
efda3bd0 118 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
bf22d4c1 119 atkbdc_softc[unit] = sc;
984263bc
MD
120 }
121 return sc;
122}
123
124int
125atkbdc_probe_unit(int unit, struct resource *port0, struct resource *port1)
126{
127 if (rman_get_start(port0) <= 0)
128 return ENXIO;
129 if (rman_get_start(port1) <= 0)
130 return ENXIO;
131 return 0;
132}
133
134int
135atkbdc_attach_unit(int unit, atkbdc_softc_t *sc, struct resource *port0,
136 struct resource *port1)
137{
138 return atkbdc_setup(sc, rman_get_bustag(port0),
139 rman_get_bushandle(port0),
140 rman_get_bushandle(port1));
141}
142
143/* the backdoor to the keyboard controller! XXX */
144int
145atkbdc_configure(void)
146{
147 bus_space_tag_t tag;
148 bus_space_handle_t h0;
149 bus_space_handle_t h1;
150 int port0;
151 int port1;
d8129ed3
MD
152#if defined(__i386__) || defined(__x86_64__)
153 int i;
269ffd40 154#endif
984263bc
MD
155
156 port0 = IO_KBD;
157 resource_int_value("atkbdc", 0, "port", &port0);
158 port1 = IO_KBD + KBD_STATUS_PORT;
159#if 0
160 resource_int_value("atkbdc", 0, "port", &port0);
161#endif
162
163 /* XXX: tag should be passed from the caller */
164#if defined(__i386__)
165 tag = I386_BUS_SPACE_IO;
bfc09ba0
MD
166#else
167 tag = 0; /* XXX */
984263bc
MD
168#endif
169
122df98f 170#if 0 /* notyet */
984263bc
MD
171 bus_space_map(tag, port0, IO_KBDSIZE, 0, &h0);
172 bus_space_map(tag, port1, IO_KBDSIZE, 0, &h1);
173#else
174 h0 = (bus_space_handle_t)port0;
175 h1 = (bus_space_handle_t)port1;
176#endif
269ffd40 177
d8129ed3 178#if defined(__i386__) || defined(__x86_64__)
269ffd40
YT
179 /*
180 * Check if we really have AT keyboard controller. Poll status
181 * register until we get "all clear" indication. If no such
182 * indication comes, it probably means that there is no AT
183 * keyboard controller present. Give up in such case. Check relies
184 * on the fact that reading from non-existing in/out port returns
185 * 0xff on i386. May or may not be true on other platforms.
186 */
187 for (i = 65536; i != 0; --i) {
188 if ((bus_space_read_1(tag, h1, 0) & 0x2) == 0)
189 break;
a200774b 190 DELAY(16);
269ffd40
YT
191 }
192 if (i == 0)
193 return ENXIO;
194#endif
195
984263bc
MD
196 return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
197}
198
199static int
200atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0,
201 bus_space_handle_t h1)
202{
203 if (sc->ioh0 == 0) { /* XXX */
204 sc->command_byte = -1;
205 sc->command_mask = 0;
206 sc->lock = FALSE;
207 sc->kbd.head = sc->kbd.tail = 0;
208 sc->aux.head = sc->aux.tail = 0;
209#if KBDIO_DEBUG >= 2
210 sc->kbd.call_count = 0;
211 sc->kbd.qcount = sc->kbd.max_qcount = 0;
212 sc->aux.call_count = 0;
213 sc->aux.qcount = sc->aux.max_qcount = 0;
214#endif
215 }
216 sc->iot = tag;
217 sc->ioh0 = h0;
218 sc->ioh1 = h1;
219 return 0;
220}
221
222/* open a keyboard controller */
223KBDC
224atkbdc_open(int unit)
225{
226 if (unit <= 0)
227 unit = 0;
228 if (unit >= MAXKBDC)
229 return NULL;
230 if ((atkbdc_softc[unit]->port0 != NULL)
231 || (atkbdc_softc[unit]->ioh0 != 0)) /* XXX */
232 return (KBDC)atkbdc_softc[unit];
233 return NULL;
234}
235
236/*
237 * I/O access arbitration in `kbdio'
238 *
239 * The `kbdio' module uses a simplistic convention to arbitrate
240 * I/O access to the controller/keyboard/mouse. The convention requires
241 * close cooperation of the calling device driver.
242 *
243 * The device drivers which utilize the `kbdio' module are assumed to
244 * have the following set of routines.
245 * a. An interrupt handler (the bottom half of the driver).
246 * b. Timeout routines which may briefly poll the keyboard controller.
247 * c. Routines outside interrupt context (the top half of the driver).
248 * They should follow the rules below:
249 * 1. The interrupt handler may assume that it always has full access
250 * to the controller/keyboard/mouse.
251 * 2. The other routines must issue `spltty()' if they wish to
252 * prevent the interrupt handler from accessing
253 * the controller/keyboard/mouse.
254 * 3. The timeout routines and the top half routines of the device driver
255 * arbitrate I/O access by observing the lock flag in `kbdio'.
256 * The flag is manipulated via `kbdc_lock()'; when one wants to
257 * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if
258 * the call returns with TRUE. Otherwise the caller must back off.
259 * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion
260 * is finished. This mechanism does not prevent the interrupt
261 * handler from being invoked at any time and carrying out I/O.
262 * Therefore, `spltty()' must be strategically placed in the device
263 * driver code. Also note that the timeout routine may interrupt
264 * `kbdc_lock()' called by the top half of the driver, but this
265 * interruption is OK so long as the timeout routine observes
266 * rule 4 below.
267 * 4. The interrupt and timeout routines should not extend I/O operation
268 * across more than one interrupt or timeout; they must complete any
269 * necessary I/O operation within one invocation of the routine.
270 * This means that if the timeout routine acquires the lock flag,
271 * it must reset the flag to FALSE before it returns.
272 */
273
274/* set/reset polling lock */
275int
276kbdc_lock(KBDC p, int lock)
277{
278 int prevlock;
279
280 prevlock = kbdcp(p)->lock;
281 kbdcp(p)->lock = lock;
282
283 return (prevlock != lock);
284}
285
286/* check if any data is waiting to be processed */
287int
288kbdc_data_ready(KBDC p)
289{
290 return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux)
291 || (read_status(kbdcp(p)) & KBDS_ANY_BUFFER_FULL));
292}
293
294/* queuing functions */
295
296static int
5c4d4c9d 297addq(kbdkqueue *q, int c)
984263bc
MD
298{
299 if (nextq(q->tail) != q->head) {
300 q->q[q->tail] = c;
301 q->tail = nextq(q->tail);
302#if KBDIO_DEBUG >= 2
303 ++q->call_count;
304 ++q->qcount;
305 if (q->qcount > q->max_qcount)
306 q->max_qcount = q->qcount;
307#endif
308 return TRUE;
309 }
310 return FALSE;
311}
312
313static int
5c4d4c9d 314removeq(kbdkqueue *q)
984263bc
MD
315{
316 int c;
317
318 if (q->tail != q->head) {
319 c = q->q[q->head];
320 q->head = nextq(q->head);
321#if KBDIO_DEBUG >= 2
322 --q->qcount;
323#endif
324 return c;
325 }
326 return -1;
327}
328
329/*
330 * device I/O routines
331 */
332static int
333wait_while_controller_busy(struct atkbdc_softc *kbdc)
334{
335 /* CPU will stay inside the loop for 100msec at most */
d8129ed3 336 TOTALDELAY retry = { .us = 70000, .last_clock =0 }; /* 70ms */
984263bc 337 int f;
ad8b9749 338 unsigned char c;
984263bc
MD
339
340 while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) {
341 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
342 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
343 c = read_data(kbdc);
344 addq(&kbdc->kbd, c);
984263bc
MD
345 } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
346 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
347 c = read_data(kbdc);
348 addq(&kbdc->aux, c);
984263bc
MD
349 }
350 DELAY(KBDC_DELAYTIME);
d8129ed3 351 if (CHECKTIMEOUT(&retry))
984263bc
MD
352 return FALSE;
353 }
354 return TRUE;
355}
356
357/*
358 * wait for any data; whether it's from the controller,
359 * the keyboard, or the aux device.
360 */
361static int
362wait_for_data(struct atkbdc_softc *kbdc)
363{
364 /* CPU will stay inside the loop for 200msec at most */
d8129ed3 365 TOTALDELAY retry = { 200000, 0 }; /* 200ms */
984263bc
MD
366 int f;
367
368 while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) {
369 DELAY(KBDC_DELAYTIME);
d8129ed3 370 if (CHECKTIMEOUT(&retry))
984263bc
MD
371 return 0;
372 }
373 DELAY(KBDD_DELAYTIME);
374 return f;
375}
376
377/* wait for data from the keyboard */
378static int
379wait_for_kbd_data(struct atkbdc_softc *kbdc)
380{
381 /* CPU will stay inside the loop for 200msec at most */
d8129ed3 382 TOTALDELAY retry = { 200000, 0 }; /* 200ms */
984263bc 383 int f;
ad8b9749 384 unsigned char c;
984263bc
MD
385
386 while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
387 != KBDS_KBD_BUFFER_FULL) {
388 if (f == KBDS_AUX_BUFFER_FULL) {
389 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
390 c = read_data(kbdc);
391 addq(&kbdc->aux, c);
984263bc
MD
392 }
393 DELAY(KBDC_DELAYTIME);
d8129ed3 394 if (CHECKTIMEOUT(&retry))
984263bc
MD
395 return 0;
396 }
397 DELAY(KBDD_DELAYTIME);
398 return f;
399}
400
401/*
402 * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard.
403 * queue anything else.
404 */
405static int
406wait_for_kbd_ack(struct atkbdc_softc *kbdc)
407{
408 /* CPU will stay inside the loop for 200msec at most */
d8129ed3 409 TOTALDELAY retry = { 200000, 0 }; /* 200ms */
984263bc
MD
410 int f;
411 int b;
412
d8129ed3 413 while (CHECKTIMEOUT(&retry) == 0) {
984263bc
MD
414 if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
415 DELAY(KBDD_DELAYTIME);
416 b = read_data(kbdc);
417 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
418 if ((b == KBD_ACK) || (b == KBD_RESEND)
419 || (b == KBD_RESET_FAIL))
420 return b;
421 addq(&kbdc->kbd, b);
422 } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
423 addq(&kbdc->aux, b);
424 }
425 }
426 DELAY(KBDC_DELAYTIME);
427 }
428 return -1;
429}
430
431/* wait for data from the aux device */
432static int
433wait_for_aux_data(struct atkbdc_softc *kbdc)
434{
435 /* CPU will stay inside the loop for 200msec at most */
d8129ed3 436 TOTALDELAY retry = { 200000, 0 }; /* 200ms */
984263bc 437 int f;
ad8b9749 438 unsigned char b;
984263bc
MD
439
440 while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
441 != KBDS_AUX_BUFFER_FULL) {
442 if (f == KBDS_KBD_BUFFER_FULL) {
443 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
444 b = read_data(kbdc);
445 addq(&kbdc->kbd, b);
984263bc
MD
446 }
447 DELAY(KBDC_DELAYTIME);
d8129ed3 448 if (CHECKTIMEOUT(&retry))
984263bc
MD
449 return 0;
450 }
451 DELAY(KBDD_DELAYTIME);
452 return f;
453}
454
455/*
456 * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device.
457 * queue anything else.
458 */
459static int
460wait_for_aux_ack(struct atkbdc_softc *kbdc)
461{
462 /* CPU will stay inside the loop for 200msec at most */
d8129ed3 463 TOTALDELAY retry = { 200000, 0 }; /* 200ms */
984263bc
MD
464 int f;
465 int b;
466
d8129ed3 467 while (CHECKTIMEOUT(&retry) == 0) {
984263bc
MD
468 if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
469 DELAY(KBDD_DELAYTIME);
470 b = read_data(kbdc);
471 if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
472 if ((b == PSM_ACK) || (b == PSM_RESEND)
473 || (b == PSM_RESET_FAIL))
474 return b;
475 addq(&kbdc->aux, b);
476 } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
477 addq(&kbdc->kbd, b);
478 }
479 }
480 DELAY(KBDC_DELAYTIME);
481 }
482 return -1;
483}
484
ad8b9749
MD
485/*
486 * Returns read-back data or -1 on failure
487 */
488int
489write_controller_w1r1(KBDC p, int c, int d)
490{
491 if (!write_controller_command(p, c))
492 return(-1);
493 if (!write_controller_data(p, d))
494 return(-1);
495 return (read_controller_data(p));
496}
497
984263bc
MD
498/* write a one byte command to the controller */
499int
500write_controller_command(KBDC p, int c)
501{
502 if (!wait_while_controller_busy(kbdcp(p)))
503 return FALSE;
504 write_command(kbdcp(p), c);
505 return TRUE;
506}
507
508/* write a one byte data to the controller */
509int
510write_controller_data(KBDC p, int c)
511{
512 if (!wait_while_controller_busy(kbdcp(p)))
513 return FALSE;
514 write_data(kbdcp(p), c);
515 return TRUE;
516}
517
518/* write a one byte keyboard command */
519int
520write_kbd_command(KBDC p, int c)
521{
522 if (!wait_while_controller_busy(kbdcp(p)))
523 return FALSE;
524 write_data(kbdcp(p), c);
525 return TRUE;
526}
527
528/* write a one byte auxiliary device command */
529int
530write_aux_command(KBDC p, int c)
531{
532 if (!write_controller_command(p, KBDC_WRITE_TO_AUX))
533 return FALSE;
534 return write_controller_data(p, c);
535}
536
537/* send a command to the keyboard and wait for ACK */
538int
539send_kbd_command(KBDC p, int c)
540{
541 int retry = KBD_MAXRETRY;
542 int res = -1;
543
544 while (retry-- > 0) {
545 if (!write_kbd_command(p, c))
546 continue;
547 res = wait_for_kbd_ack(kbdcp(p));
548 if (res == KBD_ACK)
549 break;
550 }
551 return res;
552}
553
554/* send a command to the auxiliary device and wait for ACK */
555int
556send_aux_command(KBDC p, int c)
557{
558 int retry = KBD_MAXRETRY;
559 int res = -1;
560
561 while (retry-- > 0) {
562 if (!write_aux_command(p, c))
563 continue;
564 /*
565 * FIXME: XXX
566 * The aux device may have already sent one or two bytes of
567 * status data, when a command is received. It will immediately
568 * stop data transmission, thus, leaving an incomplete data
569 * packet in our buffer. We have to discard any unprocessed
570 * data in order to remove such packets. Well, we may remove
571 * unprocessed, but necessary data byte as well...
572 */
573 emptyq(&kbdcp(p)->aux);
574 res = wait_for_aux_ack(kbdcp(p));
575 if (res == PSM_ACK)
576 break;
577 }
578 return res;
579}
580
581/* send a command and a data to the keyboard, wait for ACKs */
582int
583send_kbd_command_and_data(KBDC p, int c, int d)
584{
585 int retry;
586 int res = -1;
587
588 for (retry = KBD_MAXRETRY; retry > 0; --retry) {
589 if (!write_kbd_command(p, c))
590 continue;
591 res = wait_for_kbd_ack(kbdcp(p));
592 if (res == KBD_ACK)
593 break;
594 else if (res != KBD_RESEND)
595 return res;
596 }
597 if (retry <= 0)
598 return res;
599
600 for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
601 if (!write_kbd_command(p, d))
602 continue;
603 res = wait_for_kbd_ack(kbdcp(p));
604 if (res != KBD_RESEND)
605 break;
606 }
607 return res;
608}
609
610/* send a command and a data to the auxiliary device, wait for ACKs */
611int
612send_aux_command_and_data(KBDC p, int c, int d)
613{
614 int retry;
615 int res = -1;
616
617 for (retry = KBD_MAXRETRY; retry > 0; --retry) {
618 if (!write_aux_command(p, c))
619 continue;
620 emptyq(&kbdcp(p)->aux);
621 res = wait_for_aux_ack(kbdcp(p));
622 if (res == PSM_ACK)
623 break;
624 else if (res != PSM_RESEND)
625 return res;
626 }
627 if (retry <= 0)
628 return res;
629
630 for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
631 if (!write_aux_command(p, d))
632 continue;
633 res = wait_for_aux_ack(kbdcp(p));
634 if (res != PSM_RESEND)
635 break;
636 }
637 return res;
638}
639
640/*
641 * read one byte from any source; whether from the controller,
642 * the keyboard, or the aux device
643 */
644int
645read_controller_data(KBDC p)
646{
647 if (availq(&kbdcp(p)->kbd))
648 return removeq(&kbdcp(p)->kbd);
649 if (availq(&kbdcp(p)->aux))
650 return removeq(&kbdcp(p)->aux);
651 if (!wait_for_data(kbdcp(p)))
652 return -1; /* timeout */
653 return read_data(kbdcp(p));
654}
655
656#if KBDIO_DEBUG >= 2
657static int call = 0;
658#endif
659
660/* read one byte from the keyboard */
661int
662read_kbd_data(KBDC p)
663{
ad8b9749
MD
664 unsigned char b;
665
984263bc
MD
666#if KBDIO_DEBUG >= 2
667 if (++call > 2000) {
668 call = 0;
669 log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, "
670 "aux q: %d calls, max %d chars\n",
671 kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
672 kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
673 }
674#endif
675
676 if (availq(&kbdcp(p)->kbd))
677 return removeq(&kbdcp(p)->kbd);
678 if (!wait_for_kbd_data(kbdcp(p)))
679 return -1; /* timeout */
ad8b9749
MD
680 b = read_data(kbdcp(p));
681 return b;
984263bc
MD
682}
683
684/* read one byte from the keyboard, but return immediately if
685 * no data is waiting
686 */
687int
688read_kbd_data_no_wait(KBDC p)
689{
690 int f;
ad8b9749 691 unsigned char b;
984263bc
MD
692
693#if KBDIO_DEBUG >= 2
694 if (++call > 2000) {
695 call = 0;
696 log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, "
697 "aux q: %d calls, max %d chars\n",
698 kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
699 kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
700 }
701#endif
702
703 if (availq(&kbdcp(p)->kbd))
704 return removeq(&kbdcp(p)->kbd);
705 f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
ad8b9749 706 while (f == KBDS_AUX_BUFFER_FULL) {
984263bc 707 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
708 b = read_data(kbdcp(p));
709 addq(&kbdcp(p)->aux, b);
984263bc
MD
710 f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
711 }
712 if (f == KBDS_KBD_BUFFER_FULL) {
713 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
714 b = read_data(kbdcp(p));
715 return (int)b;
984263bc
MD
716 }
717 return -1; /* no data */
718}
719
720/* read one byte from the aux device */
721int
722read_aux_data(KBDC p)
723{
ad8b9749 724 unsigned char b;
984263bc
MD
725 if (availq(&kbdcp(p)->aux))
726 return removeq(&kbdcp(p)->aux);
727 if (!wait_for_aux_data(kbdcp(p)))
728 return -1; /* timeout */
ad8b9749
MD
729 b = read_data(kbdcp(p));
730 return b;
984263bc
MD
731}
732
733/* read one byte from the aux device, but return immediately if
734 * no data is waiting
735 */
736int
737read_aux_data_no_wait(KBDC p)
738{
ad8b9749 739 unsigned char b;
984263bc
MD
740 int f;
741
742 if (availq(&kbdcp(p)->aux))
743 return removeq(&kbdcp(p)->aux);
744 f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
ad8b9749 745 while (f == KBDS_KBD_BUFFER_FULL) {
984263bc 746 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
747 b = read_data(kbdcp(p));
748 addq(&kbdcp(p)->kbd, b);
984263bc
MD
749 f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
750 }
751 if (f == KBDS_AUX_BUFFER_FULL) {
752 DELAY(KBDD_DELAYTIME);
ad8b9749
MD
753 b = read_data(kbdcp(p));
754 return b;
984263bc
MD
755 }
756 return -1; /* no data */
757}
758
759/* discard data from the keyboard */
760void
761empty_kbd_buffer(KBDC p, int wait)
762{
763 int t;
764 int b;
765 int f;
766#if KBDIO_DEBUG >= 2
767 int c1 = 0;
768 int c2 = 0;
769#endif
770 int delta = 2;
771
772 for (t = wait; t > 0; ) {
773 if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
774 DELAY(KBDD_DELAYTIME);
775 b = read_data(kbdcp(p));
776 if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
777 addq(&kbdcp(p)->aux, b);
778#if KBDIO_DEBUG >= 2
779 ++c2;
780 } else {
781 ++c1;
782#endif
783 }
784 t = wait;
785 } else {
786 t -= delta;
787 }
788 DELAY(delta*1000);
789 }
790#if KBDIO_DEBUG >= 2
791 if ((c1 > 0) || (c2 > 0))
792 log(LOG_DEBUG, "kbdc: %d:%d char read (empty_kbd_buffer)\n", c1, c2);
793#endif
794
795 emptyq(&kbdcp(p)->kbd);
796}
797
798/* discard data from the aux device */
799void
800empty_aux_buffer(KBDC p, int wait)
801{
802 int t;
803 int b;
804 int f;
805#if KBDIO_DEBUG >= 2
806 int c1 = 0;
807 int c2 = 0;
808#endif
809 int delta = 2;
810
811 for (t = wait; t > 0; ) {
812 if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
813 DELAY(KBDD_DELAYTIME);
814 b = read_data(kbdcp(p));
815 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
816 addq(&kbdcp(p)->kbd, b);
817#if KBDIO_DEBUG >= 2
818 ++c1;
819 } else {
820 ++c2;
821#endif
822 }
823 t = wait;
824 } else {
825 t -= delta;
826 }
827 DELAY(delta*1000);
828 }
829#if KBDIO_DEBUG >= 2
830 if ((c1 > 0) || (c2 > 0))
831 log(LOG_DEBUG, "kbdc: %d:%d char read (empty_aux_buffer)\n", c1, c2);
832#endif
833
834 emptyq(&kbdcp(p)->aux);
835}
836
837/* discard any data from the keyboard or the aux device */
838void
839empty_both_buffers(KBDC p, int wait)
840{
841 int t;
842 int f;
843#if KBDIO_DEBUG >= 2
844 int c1 = 0;
845 int c2 = 0;
846#endif
847 int delta = 2;
848
849 for (t = wait; t > 0; ) {
850 if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
851 DELAY(KBDD_DELAYTIME);
852 (void)read_data(kbdcp(p));
853#if KBDIO_DEBUG >= 2
854 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL)
855 ++c1;
856 else
857 ++c2;
858#endif
859 t = wait;
860 } else {
861 t -= delta;
862 }
863 DELAY(delta*1000);
864 }
865#if KBDIO_DEBUG >= 2
866 if ((c1 > 0) || (c2 > 0))
867 log(LOG_DEBUG, "kbdc: %d:%d char read (empty_both_buffers)\n", c1, c2);
868#endif
869
870 emptyq(&kbdcp(p)->kbd);
871 emptyq(&kbdcp(p)->aux);
872}
873
874/* keyboard and mouse device control */
875
876/* NOTE: enable the keyboard port but disable the keyboard
877 * interrupt before calling "reset_kbd()".
878 */
879int
880reset_kbd(KBDC p)
881{
882 int retry = KBD_MAXRETRY;
883 int again = KBD_MAXWAIT;
884 int c = KBD_RESEND; /* keep the compiler happy */
885
886 while (retry-- > 0) {
887 empty_both_buffers(p, 10);
888 if (!write_kbd_command(p, KBDC_RESET_KBD))
889 continue;
890 emptyq(&kbdcp(p)->kbd);
891 c = read_controller_data(p);
892 if (verbose || bootverbose)
893 log(LOG_DEBUG, "kbdc: RESET_KBD return code:%04x\n", c);
894 if (c == KBD_ACK) /* keyboard has agreed to reset itself... */
895 break;
896 }
897 if (retry < 0)
898 return FALSE;
899
900 while (again-- > 0) {
901 /* wait awhile, well, in fact we must wait quite loooooooooooong */
902 DELAY(KBD_RESETDELAY*1000);
903 c = read_controller_data(p); /* RESET_DONE/RESET_FAIL */
904 if (c != -1) /* wait again if the controller is not ready */
905 break;
906 }
907 if (verbose || bootverbose)
908 log(LOG_DEBUG, "kbdc: RESET_KBD status:%04x\n", c);
909 if (c != KBD_RESET_DONE)
910 return FALSE;
911 return TRUE;
912}
913
914/* NOTE: enable the aux port but disable the aux interrupt
915 * before calling `reset_aux_dev()'.
916 */
917int
918reset_aux_dev(KBDC p)
919{
920 int retry = KBD_MAXRETRY;
921 int again = KBD_MAXWAIT;
922 int c = PSM_RESEND; /* keep the compiler happy */
923
924 while (retry-- > 0) {
925 empty_both_buffers(p, 10);
926 if (!write_aux_command(p, PSMC_RESET_DEV))
927 continue;
928 emptyq(&kbdcp(p)->aux);
929 /* NOTE: Compaq Armada laptops require extra delay here. XXX */
930 for (again = KBD_MAXWAIT; again > 0; --again) {
931 DELAY(KBD_RESETDELAY*1000);
932 c = read_aux_data_no_wait(p);
933 if (c != -1)
934 break;
935 }
936 if (verbose || bootverbose)
937 log(LOG_DEBUG, "kbdc: RESET_AUX return code:%04x\n", c);
938 if (c == PSM_ACK) /* aux dev is about to reset... */
939 break;
940 }
941 if (retry < 0)
942 return FALSE;
943
944 for (again = KBD_MAXWAIT; again > 0; --again) {
945 /* wait awhile, well, quite looooooooooooong */
946 DELAY(KBD_RESETDELAY*1000);
947 c = read_aux_data_no_wait(p); /* RESET_DONE/RESET_FAIL */
948 if (c != -1) /* wait again if the controller is not ready */
949 break;
950 }
951 if (verbose || bootverbose)
952 log(LOG_DEBUG, "kbdc: RESET_AUX status:%04x\n", c);
953 if (c != PSM_RESET_DONE) /* reset status */
954 return FALSE;
955
956 c = read_aux_data(p); /* device ID */
957 if (verbose || bootverbose)
958 log(LOG_DEBUG, "kbdc: RESET_AUX ID:%04x\n", c);
959 /* NOTE: we could check the device ID now, but leave it later... */
960 return TRUE;
961}
962
963/* controller diagnostics and setup */
964
965int
966test_controller(KBDC p)
967{
968 int retry = KBD_MAXRETRY;
969 int again = KBD_MAXWAIT;
970 int c = KBD_DIAG_FAIL;
971
972 while (retry-- > 0) {
973 empty_both_buffers(p, 10);
974 if (write_controller_command(p, KBDC_DIAGNOSE))
975 break;
976 }
977 if (retry < 0)
978 return FALSE;
979
980 emptyq(&kbdcp(p)->kbd);
981 while (again-- > 0) {
982 /* wait awhile */
983 DELAY(KBD_RESETDELAY*1000);
984 c = read_controller_data(p); /* DIAG_DONE/DIAG_FAIL */
985 if (c != -1) /* wait again if the controller is not ready */
986 break;
987 }
988 if (verbose || bootverbose)
989 log(LOG_DEBUG, "kbdc: DIAGNOSE status:%04x\n", c);
990 return (c == KBD_DIAG_DONE);
991}
992
993int
994test_kbd_port(KBDC p)
995{
996 int retry = KBD_MAXRETRY;
997 int again = KBD_MAXWAIT;
998 int c = -1;
999
1000 while (retry-- > 0) {
1001 empty_both_buffers(p, 10);
1002 if (write_controller_command(p, KBDC_TEST_KBD_PORT))
1003 break;
1004 }
1005 if (retry < 0)
1006 return FALSE;
1007
1008 emptyq(&kbdcp(p)->kbd);
1009 while (again-- > 0) {
1010 c = read_controller_data(p);
1011 if (c != -1) /* try again if the controller is not ready */
1012 break;
1013 }
1014 if (verbose || bootverbose)
1015 log(LOG_DEBUG, "kbdc: TEST_KBD_PORT status:%04x\n", c);
1016 return c;
1017}
1018
1019int
1020test_aux_port(KBDC p)
1021{
1022 int retry = KBD_MAXRETRY;
1023 int again = KBD_MAXWAIT;
1024 int c = -1;
1025
1026 while (retry-- > 0) {
1027 empty_both_buffers(p, 10);
1028 if (write_controller_command(p, KBDC_TEST_AUX_PORT))
1029 break;
1030 }
1031 if (retry < 0)
1032 return FALSE;
1033
1034 emptyq(&kbdcp(p)->kbd);
1035 while (again-- > 0) {
1036 c = read_controller_data(p);
1037 if (c != -1) /* try again if the controller is not ready */
1038 break;
1039 }
1040 if (verbose || bootverbose)
1041 log(LOG_DEBUG, "kbdc: TEST_AUX_PORT status:%04x\n", c);
1042 return c;
1043}
1044
1045int
1046kbdc_get_device_mask(KBDC p)
1047{
1048 return kbdcp(p)->command_mask;
1049}
1050
1051void
1052kbdc_set_device_mask(KBDC p, int mask)
1053{
1054 kbdcp(p)->command_mask =
1055 mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS);
1056}
1057
1058int
1059get_controller_command_byte(KBDC p)
1060{
1061 if (kbdcp(p)->command_byte != -1)
1062 return kbdcp(p)->command_byte;
1063 if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE))
1064 return -1;
1065 emptyq(&kbdcp(p)->kbd);
1066 kbdcp(p)->command_byte = read_controller_data(p);
1067 return kbdcp(p)->command_byte;
1068}
1069
1070int
1071set_controller_command_byte(KBDC p, int mask, int command)
1072{
1073 if (get_controller_command_byte(p) == -1)
1074 return FALSE;
1075
1076 command = (kbdcp(p)->command_byte & ~mask) | (command & mask);
ad8b9749
MD
1077#if 1
1078 if (mask & KBD_DISABLE_KBD_PORT) {
1079 if (command & KBD_DISABLE_KBD_PORT) {
1080 if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT))
1081 return FALSE;
1082 }
984263bc 1083 }
ad8b9749 1084#endif
984263bc
MD
1085 if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE))
1086 return FALSE;
1087 if (!write_controller_data(p, command))
1088 return FALSE;
ad8b9749
MD
1089#if 0
1090 if (mask & KBD_DISABLE_KBD_PORT) {
1091 if ((command & KBD_DISABLE_KBD_PORT) == 0) {
1092 if (!write_controller_command(p, KBDC_ENABLE_KBD_PORT))
1093 return FALSE;
1094 }
1095 }
1096#endif
984263bc
MD
1097 kbdcp(p)->command_byte = command;
1098
1099 if (verbose)
1100 log(LOG_DEBUG, "kbdc: new command byte:%04x (set_controller...)\n",
1101 command);
1102
1103 return TRUE;
1104}