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