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