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