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