atkbdc.c revision 119418
142421Syokota/*-
242421Syokota * Copyright (c) 1996-1999
342421Syokota * Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
442421Syokota * All rights reserved.
542421Syokota *
642421Syokota * Redistribution and use in source and binary forms, with or without
742421Syokota * modification, are permitted provided that the following conditions
842421Syokota * are met:
942421Syokota * 1. Redistributions of source code must retain the above copyright
1042421Syokota *    notice, this list of conditions and the following disclaimer.
1142421Syokota * 2. Redistributions in binary form must reproduce the above copyright
1242421Syokota *    notice, this list of conditions and the following disclaimer in the
1342421Syokota *    documentation and/or other materials provided with the distribution.
1442421Syokota * 3. The name of the author may not be used to endorse or promote
1542421Syokota *    products derived from this software without specific prior written
1642421Syokota *    permission.
1742421Syokota *
1842421Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1942421Syokota * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2042421Syokota * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2142421Syokota * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2242421Syokota * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2342421Syokota * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2442421Syokota * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2542421Syokota * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2642421Syokota * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2742421Syokota * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2842421Syokota * SUCH DAMAGE.
2942421Syokota *
3042421Syokota * from kbdio.c,v 1.13 1998/09/25 11:55:46 yokota Exp
3142421Syokota */
3242421Syokota
33119418Sobrien#include <sys/cdefs.h>
34119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/atkbdc/atkbdc.c 119418 2003-08-24 17:55:58Z obrien $");
35119418Sobrien
3642421Syokota#include "opt_kbd.h"
3742421Syokota
3842421Syokota#include <sys/param.h>
3942421Syokota#include <sys/systm.h>
4058271Syokota#include <sys/bus.h>
4142421Syokota#include <sys/malloc.h>
4242421Syokota#include <sys/syslog.h>
4358271Syokota#include <machine/bus_pio.h>
4458271Syokota#include <machine/bus.h>
4558271Syokota#include <machine/resource.h>
4658271Syokota#include <sys/rman.h>
4742421Syokota
4842421Syokota
4942421Syokota#include <dev/kbd/atkbdcreg.h>
5042421Syokota
5142421Syokota#include <isa/isareg.h>
5242421Syokota
5342421Syokota/* constants */
5442421Syokota
55102149Speter#define MAXKBDC		1		/* XXX */
5642421Syokota
5742421Syokota/* macros */
5842421Syokota
5942421Syokota#ifndef MAX
6042421Syokota#define MAX(x, y)	((x) > (y) ? (x) : (y))
6142421Syokota#endif
6242421Syokota
6342421Syokota#define kbdcp(p)	((atkbdc_softc_t *)(p))
6442421Syokota#define nextq(i)	(((i) + 1) % KBDQ_BUFSIZE)
6542421Syokota#define availq(q)	((q)->head != (q)->tail)
6642421Syokota#if KBDIO_DEBUG >= 2
6742421Syokota#define emptyq(q)	((q)->tail = (q)->head = (q)->qcount = 0)
6842421Syokota#else
6942421Syokota#define emptyq(q)	((q)->tail = (q)->head = 0)
7042421Syokota#endif
7142421Syokota
7258271Syokota#define read_data(k)	(bus_space_read_1((k)->iot, (k)->ioh0, 0))
7358271Syokota#define read_status(k)	(bus_space_read_1((k)->iot, (k)->ioh1, 0))
7458271Syokota#define write_data(k, d)	\
7558271Syokota			(bus_space_write_1((k)->iot, (k)->ioh0, 0, (d)))
7658271Syokota#define write_command(k, d)	\
7758271Syokota			(bus_space_write_1((k)->iot, (k)->ioh1, 0, (d)))
7858271Syokota
7942421Syokota/* local variables */
8042421Syokota
8142421Syokota/*
8242421Syokota * We always need at least one copy of the kbdc_softc struct for the
8342421Syokota * low-level console.  As the low-level console accesses the keyboard
8442421Syokota * controller before kbdc, and all other devices, is probed, we
8542421Syokota * statically allocate one entry. XXX
8642421Syokota */
8742421Syokotastatic atkbdc_softc_t default_kbdc;
8842421Syokotastatic atkbdc_softc_t *atkbdc_softc[MAXKBDC] = { &default_kbdc };
8942421Syokota
9042421Syokotastatic int verbose = KBDIO_DEBUG;
9142421Syokota
9242421Syokota/* function prototypes */
9342421Syokota
9458271Syokotastatic int atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag,
9558271Syokota			bus_space_handle_t h0, bus_space_handle_t h1);
9642421Syokotastatic int addq(kqueue *q, int c);
9742421Syokotastatic int removeq(kqueue *q);
9842421Syokotastatic int wait_while_controller_busy(atkbdc_softc_t *kbdc);
9942421Syokotastatic int wait_for_data(atkbdc_softc_t *kbdc);
10042421Syokotastatic int wait_for_kbd_data(atkbdc_softc_t *kbdc);
10142421Syokotastatic int wait_for_kbd_ack(atkbdc_softc_t *kbdc);
10242421Syokotastatic int wait_for_aux_data(atkbdc_softc_t *kbdc);
10342421Syokotastatic int wait_for_aux_ack(atkbdc_softc_t *kbdc);
10442421Syokota
10542421Syokotaatkbdc_softc_t
10642421Syokota*atkbdc_get_softc(int unit)
10742421Syokota{
10842421Syokota	atkbdc_softc_t *sc;
10942421Syokota
11042421Syokota	if (unit >= sizeof(atkbdc_softc)/sizeof(atkbdc_softc[0]))
11142421Syokota		return NULL;
11242421Syokota	sc = atkbdc_softc[unit];
11342421Syokota	if (sc == NULL) {
11442421Syokota		sc = atkbdc_softc[unit]
11569781Sdwmalone		   = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO);
11642421Syokota		if (sc == NULL)
11742421Syokota			return NULL;
11842421Syokota	}
11942421Syokota	return sc;
12042421Syokota}
12142421Syokota
12242421Syokotaint
12358271Syokotaatkbdc_probe_unit(int unit, struct resource *port0, struct resource *port1)
12442421Syokota{
12558271Syokota	if (rman_get_start(port0) <= 0)
12647296Syokota		return ENXIO;
12758271Syokota	if (rman_get_start(port1) <= 0)
12858271Syokota		return ENXIO;
12947296Syokota	return 0;
13047296Syokota}
13147296Syokota
13247296Syokotaint
13358271Syokotaatkbdc_attach_unit(int unit, atkbdc_softc_t *sc, struct resource *port0,
13458271Syokota		   struct resource *port1)
13547296Syokota{
13658271Syokota	return atkbdc_setup(sc, rman_get_bustag(port0),
13758271Syokota			    rman_get_bushandle(port0),
13858271Syokota			    rman_get_bushandle(port1));
13942421Syokota}
14042421Syokota
14142421Syokota/* the backdoor to the keyboard controller! XXX */
14242421Syokotaint
14342421Syokotaatkbdc_configure(void)
14442421Syokota{
14558271Syokota	bus_space_tag_t tag;
14658271Syokota	bus_space_handle_t h0;
14758271Syokota	bus_space_handle_t h1;
14858271Syokota	int port0;
14958271Syokota	int port1;
15058271Syokota
15158271Syokota	port0 = IO_KBD;
15258271Syokota	resource_int_value("atkbdc", 0, "port", &port0);
15358271Syokota	port1 = IO_KBD + KBD_STATUS_PORT;
15458271Syokota#if 0
15558271Syokota	resource_int_value("atkbdc", 0, "port", &port0);
15658271Syokota#endif
15758271Syokota
15858271Syokota	/* XXX: tag should be passed from the caller */
159114930Speter#if defined(__i386__)
16058271Syokota	tag = I386_BUS_SPACE_IO;
161114930Speter#elif defined(__amd64__)
162114930Speter	tag = AMD64_BUS_SPACE_IO;
16358271Syokota#elif defined(__alpha__)
16465176Sdfr	tag = busspace_isa_io;
16592661Speter#elif defined(__ia64__)
16692661Speter	tag = IA64_BUS_SPACE_IO;
16792661Speter#else
16892661Speter#error "define tag!"
16958271Syokota#endif
17058271Syokota
17158271Syokota#if notyet
17258271Syokota	bus_space_map(tag, port0, IO_KBDSIZE, 0, &h0);
17358271Syokota	bus_space_map(tag, port1, IO_KBDSIZE, 0, &h1);
17458271Syokota#else
17558271Syokota	h0 = (bus_space_handle_t)port0;
17658271Syokota	h1 = (bus_space_handle_t)port1;
17758271Syokota#endif
17858271Syokota	return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
17942421Syokota}
18042421Syokota
18142421Syokotastatic int
18258271Syokotaatkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0,
18358271Syokota	     bus_space_handle_t h1)
18442421Syokota{
18558271Syokota	if (sc->ioh0 == 0) {	/* XXX */
18642421Syokota	    sc->command_byte = -1;
18742421Syokota	    sc->command_mask = 0;
18842421Syokota	    sc->lock = FALSE;
18942421Syokota	    sc->kbd.head = sc->kbd.tail = 0;
19042421Syokota	    sc->aux.head = sc->aux.tail = 0;
19142421Syokota#if KBDIO_DEBUG >= 2
19242421Syokota	    sc->kbd.call_count = 0;
19342421Syokota	    sc->kbd.qcount = sc->kbd.max_qcount = 0;
19442421Syokota	    sc->aux.call_count = 0;
19542421Syokota	    sc->aux.qcount = sc->aux.max_qcount = 0;
19642421Syokota#endif
19742421Syokota	}
19858271Syokota	sc->iot = tag;
19958271Syokota	sc->ioh0 = h0;
20058271Syokota	sc->ioh1 = h1;
20142421Syokota	return 0;
20242421Syokota}
20342421Syokota
20458271Syokota/* open a keyboard controller */
20542421SyokotaKBDC
20658271Syokotaatkbdc_open(int unit)
20742421Syokota{
20858271Syokota    if (unit <= 0)
20958271Syokota	unit = 0;
21058271Syokota    if (unit >= MAXKBDC)
21158271Syokota	return NULL;
21258271Syokota    if ((atkbdc_softc[unit]->port0 != NULL)
21358271Syokota	|| (atkbdc_softc[unit]->ioh0 != 0))		/* XXX */
21458271Syokota	return (KBDC)atkbdc_softc[unit];
21542421Syokota    return NULL;
21642421Syokota}
21742421Syokota
21842421Syokota/*
21942421Syokota * I/O access arbitration in `kbdio'
22042421Syokota *
22142421Syokota * The `kbdio' module uses a simplistic convention to arbitrate
22242421Syokota * I/O access to the controller/keyboard/mouse. The convention requires
22342421Syokota * close cooperation of the calling device driver.
22442421Syokota *
22593279Smurray * The device drivers which utilize the `kbdio' module are assumed to
22642421Syokota * have the following set of routines.
22742421Syokota *    a. An interrupt handler (the bottom half of the driver).
22893279Smurray *    b. Timeout routines which may briefly poll the keyboard controller.
22942421Syokota *    c. Routines outside interrupt context (the top half of the driver).
23042421Syokota * They should follow the rules below:
23142421Syokota *    1. The interrupt handler may assume that it always has full access
23242421Syokota *       to the controller/keyboard/mouse.
23342421Syokota *    2. The other routines must issue `spltty()' if they wish to
23442421Syokota *       prevent the interrupt handler from accessing
23542421Syokota *       the controller/keyboard/mouse.
23642421Syokota *    3. The timeout routines and the top half routines of the device driver
23742421Syokota *       arbitrate I/O access by observing the lock flag in `kbdio'.
23842421Syokota *       The flag is manipulated via `kbdc_lock()'; when one wants to
23942421Syokota *       perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if
24042421Syokota *       the call returns with TRUE. Otherwise the caller must back off.
24142421Syokota *       Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion
24242421Syokota *       is finished. This mechanism does not prevent the interrupt
24342421Syokota *       handler from being invoked at any time and carrying out I/O.
24442421Syokota *       Therefore, `spltty()' must be strategically placed in the device
24542421Syokota *       driver code. Also note that the timeout routine may interrupt
24642421Syokota *       `kbdc_lock()' called by the top half of the driver, but this
24793279Smurray *       interruption is OK so long as the timeout routine observes
24893279Smurray *       rule 4 below.
24942421Syokota *    4. The interrupt and timeout routines should not extend I/O operation
25093279Smurray *       across more than one interrupt or timeout; they must complete any
25193279Smurray *       necessary I/O operation within one invocation of the routine.
25293279Smurray *       This means that if the timeout routine acquires the lock flag,
25342421Syokota *       it must reset the flag to FALSE before it returns.
25442421Syokota */
25542421Syokota
25642421Syokota/* set/reset polling lock */
25742421Syokotaint
25842421Syokotakbdc_lock(KBDC p, int lock)
25942421Syokota{
26042421Syokota    int prevlock;
26142421Syokota
26242421Syokota    prevlock = kbdcp(p)->lock;
26342421Syokota    kbdcp(p)->lock = lock;
26442421Syokota
26542421Syokota    return (prevlock != lock);
26642421Syokota}
26742421Syokota
26842421Syokota/* check if any data is waiting to be processed */
26942421Syokotaint
27042421Syokotakbdc_data_ready(KBDC p)
27142421Syokota{
27242421Syokota    return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux)
27358271Syokota	|| (read_status(kbdcp(p)) & KBDS_ANY_BUFFER_FULL));
27442421Syokota}
27542421Syokota
27642421Syokota/* queuing functions */
27742421Syokota
27842421Syokotastatic int
27942421Syokotaaddq(kqueue *q, int c)
28042421Syokota{
28142421Syokota    if (nextq(q->tail) != q->head) {
28242421Syokota	q->q[q->tail] = c;
28342421Syokota	q->tail = nextq(q->tail);
28442421Syokota#if KBDIO_DEBUG >= 2
28542421Syokota        ++q->call_count;
28642421Syokota        ++q->qcount;
28742421Syokota	if (q->qcount > q->max_qcount)
28842421Syokota            q->max_qcount = q->qcount;
28942421Syokota#endif
29042421Syokota	return TRUE;
29142421Syokota    }
29242421Syokota    return FALSE;
29342421Syokota}
29442421Syokota
29542421Syokotastatic int
29642421Syokotaremoveq(kqueue *q)
29742421Syokota{
29842421Syokota    int c;
29942421Syokota
30042421Syokota    if (q->tail != q->head) {
30142421Syokota	c = q->q[q->head];
30242421Syokota	q->head = nextq(q->head);
30342421Syokota#if KBDIO_DEBUG >= 2
30442421Syokota        --q->qcount;
30542421Syokota#endif
30642421Syokota	return c;
30742421Syokota    }
30842421Syokota    return -1;
30942421Syokota}
31042421Syokota
31142421Syokota/*
31242421Syokota * device I/O routines
31342421Syokota */
31442421Syokotastatic int
31542421Syokotawait_while_controller_busy(struct atkbdc_softc *kbdc)
31642421Syokota{
31742421Syokota    /* CPU will stay inside the loop for 100msec at most */
31842421Syokota    int retry = 5000;
31942421Syokota    int f;
32042421Syokota
32158271Syokota    while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) {
32242421Syokota	if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
32342421Syokota	    DELAY(KBDD_DELAYTIME);
32458271Syokota	    addq(&kbdc->kbd, read_data(kbdc));
32542421Syokota	} else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
32642421Syokota	    DELAY(KBDD_DELAYTIME);
32758271Syokota	    addq(&kbdc->aux, read_data(kbdc));
32842421Syokota	}
32942421Syokota        DELAY(KBDC_DELAYTIME);
33042421Syokota        if (--retry < 0)
33142421Syokota    	    return FALSE;
33242421Syokota    }
33342421Syokota    return TRUE;
33442421Syokota}
33542421Syokota
33642421Syokota/*
33742421Syokota * wait for any data; whether it's from the controller,
33842421Syokota * the keyboard, or the aux device.
33942421Syokota */
34042421Syokotastatic int
34142421Syokotawait_for_data(struct atkbdc_softc *kbdc)
34242421Syokota{
34342421Syokota    /* CPU will stay inside the loop for 200msec at most */
34442421Syokota    int retry = 10000;
34542421Syokota    int f;
34642421Syokota
34758271Syokota    while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) {
34842421Syokota        DELAY(KBDC_DELAYTIME);
34942421Syokota        if (--retry < 0)
35042421Syokota    	    return 0;
35142421Syokota    }
35242421Syokota    DELAY(KBDD_DELAYTIME);
35342421Syokota    return f;
35442421Syokota}
35542421Syokota
35642421Syokota/* wait for data from the keyboard */
35742421Syokotastatic int
35842421Syokotawait_for_kbd_data(struct atkbdc_softc *kbdc)
35942421Syokota{
36042421Syokota    /* CPU will stay inside the loop for 200msec at most */
36142421Syokota    int retry = 10000;
36242421Syokota    int f;
36342421Syokota
36458271Syokota    while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
36542421Syokota	    != KBDS_KBD_BUFFER_FULL) {
36642421Syokota        if (f == KBDS_AUX_BUFFER_FULL) {
36742421Syokota	    DELAY(KBDD_DELAYTIME);
36858271Syokota	    addq(&kbdc->aux, read_data(kbdc));
36942421Syokota	}
37042421Syokota        DELAY(KBDC_DELAYTIME);
37142421Syokota        if (--retry < 0)
37242421Syokota    	    return 0;
37342421Syokota    }
37442421Syokota    DELAY(KBDD_DELAYTIME);
37542421Syokota    return f;
37642421Syokota}
37742421Syokota
37842421Syokota/*
37942421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard.
38042421Syokota * queue anything else.
38142421Syokota */
38242421Syokotastatic int
38342421Syokotawait_for_kbd_ack(struct atkbdc_softc *kbdc)
38442421Syokota{
38542421Syokota    /* CPU will stay inside the loop for 200msec at most */
38642421Syokota    int retry = 10000;
38742421Syokota    int f;
38842421Syokota    int b;
38942421Syokota
39042421Syokota    while (retry-- > 0) {
39158271Syokota        if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
39242421Syokota	    DELAY(KBDD_DELAYTIME);
39358271Syokota            b = read_data(kbdc);
39442421Syokota	    if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
39542421Syokota		if ((b == KBD_ACK) || (b == KBD_RESEND)
39642421Syokota		    || (b == KBD_RESET_FAIL))
39742421Syokota		    return b;
39842421Syokota		addq(&kbdc->kbd, b);
39942421Syokota	    } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
40042421Syokota		addq(&kbdc->aux, b);
40142421Syokota	    }
40242421Syokota	}
40342421Syokota        DELAY(KBDC_DELAYTIME);
40442421Syokota    }
40542421Syokota    return -1;
40642421Syokota}
40742421Syokota
40842421Syokota/* wait for data from the aux device */
40942421Syokotastatic int
41042421Syokotawait_for_aux_data(struct atkbdc_softc *kbdc)
41142421Syokota{
41242421Syokota    /* CPU will stay inside the loop for 200msec at most */
41342421Syokota    int retry = 10000;
41442421Syokota    int f;
41542421Syokota
41658271Syokota    while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
41742421Syokota	    != KBDS_AUX_BUFFER_FULL) {
41842421Syokota        if (f == KBDS_KBD_BUFFER_FULL) {
41942421Syokota	    DELAY(KBDD_DELAYTIME);
42058271Syokota	    addq(&kbdc->kbd, read_data(kbdc));
42142421Syokota	}
42242421Syokota        DELAY(KBDC_DELAYTIME);
42342421Syokota        if (--retry < 0)
42442421Syokota    	    return 0;
42542421Syokota    }
42642421Syokota    DELAY(KBDD_DELAYTIME);
42742421Syokota    return f;
42842421Syokota}
42942421Syokota
43042421Syokota/*
43142421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device.
43242421Syokota * queue anything else.
43342421Syokota */
43442421Syokotastatic int
43542421Syokotawait_for_aux_ack(struct atkbdc_softc *kbdc)
43642421Syokota{
43742421Syokota    /* CPU will stay inside the loop for 200msec at most */
43842421Syokota    int retry = 10000;
43942421Syokota    int f;
44042421Syokota    int b;
44142421Syokota
44242421Syokota    while (retry-- > 0) {
44358271Syokota        if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
44442421Syokota	    DELAY(KBDD_DELAYTIME);
44558271Syokota            b = read_data(kbdc);
44642421Syokota	    if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
44742421Syokota		if ((b == PSM_ACK) || (b == PSM_RESEND)
44842421Syokota		    || (b == PSM_RESET_FAIL))
44942421Syokota		    return b;
45042421Syokota		addq(&kbdc->aux, b);
45142421Syokota	    } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
45242421Syokota		addq(&kbdc->kbd, b);
45342421Syokota	    }
45442421Syokota	}
45542421Syokota        DELAY(KBDC_DELAYTIME);
45642421Syokota    }
45742421Syokota    return -1;
45842421Syokota}
45942421Syokota
46042421Syokota/* write a one byte command to the controller */
46142421Syokotaint
46242421Syokotawrite_controller_command(KBDC p, int c)
46342421Syokota{
46442421Syokota    if (!wait_while_controller_busy(kbdcp(p)))
46542421Syokota	return FALSE;
46658271Syokota    write_command(kbdcp(p), c);
46742421Syokota    return TRUE;
46842421Syokota}
46942421Syokota
47042421Syokota/* write a one byte data to the controller */
47142421Syokotaint
47242421Syokotawrite_controller_data(KBDC p, int c)
47342421Syokota{
47442421Syokota    if (!wait_while_controller_busy(kbdcp(p)))
47542421Syokota	return FALSE;
47658271Syokota    write_data(kbdcp(p), c);
47742421Syokota    return TRUE;
47842421Syokota}
47942421Syokota
48042421Syokota/* write a one byte keyboard command */
48142421Syokotaint
48242421Syokotawrite_kbd_command(KBDC p, int c)
48342421Syokota{
48442421Syokota    if (!wait_while_controller_busy(kbdcp(p)))
48542421Syokota	return FALSE;
48658271Syokota    write_data(kbdcp(p), c);
48742421Syokota    return TRUE;
48842421Syokota}
48942421Syokota
49042421Syokota/* write a one byte auxiliary device command */
49142421Syokotaint
49242421Syokotawrite_aux_command(KBDC p, int c)
49342421Syokota{
49442421Syokota    if (!write_controller_command(p, KBDC_WRITE_TO_AUX))
49542421Syokota	return FALSE;
49642421Syokota    return write_controller_data(p, c);
49742421Syokota}
49842421Syokota
49942421Syokota/* send a command to the keyboard and wait for ACK */
50042421Syokotaint
50142421Syokotasend_kbd_command(KBDC p, int c)
50242421Syokota{
50342421Syokota    int retry = KBD_MAXRETRY;
50442421Syokota    int res = -1;
50542421Syokota
50642421Syokota    while (retry-- > 0) {
50742421Syokota	if (!write_kbd_command(p, c))
50842421Syokota	    continue;
50942421Syokota        res = wait_for_kbd_ack(kbdcp(p));
51042421Syokota        if (res == KBD_ACK)
51142421Syokota    	    break;
51242421Syokota    }
51342421Syokota    return res;
51442421Syokota}
51542421Syokota
51642421Syokota/* send a command to the auxiliary device and wait for ACK */
51742421Syokotaint
51842421Syokotasend_aux_command(KBDC p, int c)
51942421Syokota{
52042421Syokota    int retry = KBD_MAXRETRY;
52142421Syokota    int res = -1;
52242421Syokota
52342421Syokota    while (retry-- > 0) {
52442421Syokota	if (!write_aux_command(p, c))
52542421Syokota	    continue;
52642421Syokota	/*
52742421Syokota	 * FIXME: XXX
52842421Syokota	 * The aux device may have already sent one or two bytes of
52942421Syokota	 * status data, when a command is received. It will immediately
53042421Syokota	 * stop data transmission, thus, leaving an incomplete data
53142421Syokota	 * packet in our buffer. We have to discard any unprocessed
53242421Syokota	 * data in order to remove such packets. Well, we may remove
53342421Syokota	 * unprocessed, but necessary data byte as well...
53442421Syokota	 */
53542421Syokota	emptyq(&kbdcp(p)->aux);
53642421Syokota        res = wait_for_aux_ack(kbdcp(p));
53742421Syokota        if (res == PSM_ACK)
53842421Syokota    	    break;
53942421Syokota    }
54042421Syokota    return res;
54142421Syokota}
54242421Syokota
54342421Syokota/* send a command and a data to the keyboard, wait for ACKs */
54442421Syokotaint
54542421Syokotasend_kbd_command_and_data(KBDC p, int c, int d)
54642421Syokota{
54742421Syokota    int retry;
54842421Syokota    int res = -1;
54942421Syokota
55042421Syokota    for (retry = KBD_MAXRETRY; retry > 0; --retry) {
55142421Syokota	if (!write_kbd_command(p, c))
55242421Syokota	    continue;
55342421Syokota        res = wait_for_kbd_ack(kbdcp(p));
55442421Syokota        if (res == KBD_ACK)
55542421Syokota    	    break;
55642421Syokota        else if (res != KBD_RESEND)
55742421Syokota    	    return res;
55842421Syokota    }
55942421Syokota    if (retry <= 0)
56042421Syokota	return res;
56142421Syokota
56242421Syokota    for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
56342421Syokota	if (!write_kbd_command(p, d))
56442421Syokota	    continue;
56542421Syokota        res = wait_for_kbd_ack(kbdcp(p));
56642421Syokota        if (res != KBD_RESEND)
56742421Syokota    	    break;
56842421Syokota    }
56942421Syokota    return res;
57042421Syokota}
57142421Syokota
57242421Syokota/* send a command and a data to the auxiliary device, wait for ACKs */
57342421Syokotaint
57442421Syokotasend_aux_command_and_data(KBDC p, int c, int d)
57542421Syokota{
57642421Syokota    int retry;
57742421Syokota    int res = -1;
57842421Syokota
57942421Syokota    for (retry = KBD_MAXRETRY; retry > 0; --retry) {
58042421Syokota	if (!write_aux_command(p, c))
58142421Syokota	    continue;
58242421Syokota	emptyq(&kbdcp(p)->aux);
58342421Syokota        res = wait_for_aux_ack(kbdcp(p));
58442421Syokota        if (res == PSM_ACK)
58542421Syokota    	    break;
58642421Syokota        else if (res != PSM_RESEND)
58742421Syokota    	    return res;
58842421Syokota    }
58942421Syokota    if (retry <= 0)
59042421Syokota	return res;
59142421Syokota
59242421Syokota    for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
59342421Syokota	if (!write_aux_command(p, d))
59442421Syokota	    continue;
59542421Syokota        res = wait_for_aux_ack(kbdcp(p));
59642421Syokota        if (res != PSM_RESEND)
59742421Syokota    	    break;
59842421Syokota    }
59942421Syokota    return res;
60042421Syokota}
60142421Syokota
60242421Syokota/*
60342421Syokota * read one byte from any source; whether from the controller,
60442421Syokota * the keyboard, or the aux device
60542421Syokota */
60642421Syokotaint
60742421Syokotaread_controller_data(KBDC p)
60842421Syokota{
60942421Syokota    if (availq(&kbdcp(p)->kbd))
61042421Syokota        return removeq(&kbdcp(p)->kbd);
61142421Syokota    if (availq(&kbdcp(p)->aux))
61242421Syokota        return removeq(&kbdcp(p)->aux);
61342421Syokota    if (!wait_for_data(kbdcp(p)))
61442421Syokota        return -1;		/* timeout */
61558271Syokota    return read_data(kbdcp(p));
61642421Syokota}
61742421Syokota
61842421Syokota#if KBDIO_DEBUG >= 2
61942421Syokotastatic int call = 0;
62042421Syokota#endif
62142421Syokota
62242421Syokota/* read one byte from the keyboard */
62342421Syokotaint
62442421Syokotaread_kbd_data(KBDC p)
62542421Syokota{
62642421Syokota#if KBDIO_DEBUG >= 2
62742421Syokota    if (++call > 2000) {
62842421Syokota	call = 0;
62942421Syokota	log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, "
63042421Syokota			     "aux q: %d calls, max %d chars\n",
63142421Syokota		       kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
63242421Syokota		       kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
63342421Syokota    }
63442421Syokota#endif
63542421Syokota
63642421Syokota    if (availq(&kbdcp(p)->kbd))
63742421Syokota        return removeq(&kbdcp(p)->kbd);
63842421Syokota    if (!wait_for_kbd_data(kbdcp(p)))
63942421Syokota        return -1;		/* timeout */
64058271Syokota    return read_data(kbdcp(p));
64142421Syokota}
64242421Syokota
64342421Syokota/* read one byte from the keyboard, but return immediately if
64442421Syokota * no data is waiting
64542421Syokota */
64642421Syokotaint
64742421Syokotaread_kbd_data_no_wait(KBDC p)
64842421Syokota{
64942421Syokota    int f;
65042421Syokota
65142421Syokota#if KBDIO_DEBUG >= 2
65242421Syokota    if (++call > 2000) {
65342421Syokota	call = 0;
65442421Syokota	log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, "
65542421Syokota			     "aux q: %d calls, max %d chars\n",
65642421Syokota		       kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
65742421Syokota		       kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
65842421Syokota    }
65942421Syokota#endif
66042421Syokota
66142421Syokota    if (availq(&kbdcp(p)->kbd))
66242421Syokota        return removeq(&kbdcp(p)->kbd);
66358271Syokota    f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
66442421Syokota    if (f == KBDS_AUX_BUFFER_FULL) {
66542421Syokota        DELAY(KBDD_DELAYTIME);
66658271Syokota        addq(&kbdcp(p)->aux, read_data(kbdcp(p)));
66758271Syokota        f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
66842421Syokota    }
66942421Syokota    if (f == KBDS_KBD_BUFFER_FULL) {
67042421Syokota        DELAY(KBDD_DELAYTIME);
67158271Syokota        return read_data(kbdcp(p));
67242421Syokota    }
67342421Syokota    return -1;		/* no data */
67442421Syokota}
67542421Syokota
67642421Syokota/* read one byte from the aux device */
67742421Syokotaint
67842421Syokotaread_aux_data(KBDC p)
67942421Syokota{
68042421Syokota    if (availq(&kbdcp(p)->aux))
68142421Syokota        return removeq(&kbdcp(p)->aux);
68242421Syokota    if (!wait_for_aux_data(kbdcp(p)))
68342421Syokota        return -1;		/* timeout */
68458271Syokota    return read_data(kbdcp(p));
68542421Syokota}
68642421Syokota
68742421Syokota/* read one byte from the aux device, but return immediately if
68842421Syokota * no data is waiting
68942421Syokota */
69042421Syokotaint
69142421Syokotaread_aux_data_no_wait(KBDC p)
69242421Syokota{
69342421Syokota    int f;
69442421Syokota
69542421Syokota    if (availq(&kbdcp(p)->aux))
69642421Syokota        return removeq(&kbdcp(p)->aux);
69758271Syokota    f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
69842421Syokota    if (f == KBDS_KBD_BUFFER_FULL) {
69942421Syokota        DELAY(KBDD_DELAYTIME);
70058271Syokota        addq(&kbdcp(p)->kbd, read_data(kbdcp(p)));
70158271Syokota        f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL;
70242421Syokota    }
70342421Syokota    if (f == KBDS_AUX_BUFFER_FULL) {
70442421Syokota        DELAY(KBDD_DELAYTIME);
70558271Syokota        return read_data(kbdcp(p));
70642421Syokota    }
70742421Syokota    return -1;		/* no data */
70842421Syokota}
70942421Syokota
71042421Syokota/* discard data from the keyboard */
71142421Syokotavoid
71242421Syokotaempty_kbd_buffer(KBDC p, int wait)
71342421Syokota{
71442421Syokota    int t;
71542421Syokota    int b;
71642421Syokota    int f;
71742421Syokota#if KBDIO_DEBUG >= 2
71842421Syokota    int c1 = 0;
71942421Syokota    int c2 = 0;
72042421Syokota#endif
72142421Syokota    int delta = 2;
72242421Syokota
72342421Syokota    for (t = wait; t > 0; ) {
72458271Syokota        if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
72542421Syokota	    DELAY(KBDD_DELAYTIME);
72658271Syokota            b = read_data(kbdcp(p));
72742421Syokota	    if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
72842421Syokota		addq(&kbdcp(p)->aux, b);
72942421Syokota#if KBDIO_DEBUG >= 2
73042421Syokota		++c2;
73142421Syokota            } else {
73242421Syokota		++c1;
73342421Syokota#endif
73442421Syokota	    }
73542421Syokota	    t = wait;
73642421Syokota	} else {
73742421Syokota	    t -= delta;
73842421Syokota	}
73942421Syokota        DELAY(delta*1000);
74042421Syokota    }
74142421Syokota#if KBDIO_DEBUG >= 2
74242421Syokota    if ((c1 > 0) || (c2 > 0))
74342421Syokota        log(LOG_DEBUG, "kbdc: %d:%d char read (empty_kbd_buffer)\n", c1, c2);
74442421Syokota#endif
74542421Syokota
74642421Syokota    emptyq(&kbdcp(p)->kbd);
74742421Syokota}
74842421Syokota
74942421Syokota/* discard data from the aux device */
75042421Syokotavoid
75142421Syokotaempty_aux_buffer(KBDC p, int wait)
75242421Syokota{
75342421Syokota    int t;
75442421Syokota    int b;
75542421Syokota    int f;
75642421Syokota#if KBDIO_DEBUG >= 2
75742421Syokota    int c1 = 0;
75842421Syokota    int c2 = 0;
75942421Syokota#endif
76042421Syokota    int delta = 2;
76142421Syokota
76242421Syokota    for (t = wait; t > 0; ) {
76358271Syokota        if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
76442421Syokota	    DELAY(KBDD_DELAYTIME);
76558271Syokota            b = read_data(kbdcp(p));
76642421Syokota	    if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
76742421Syokota		addq(&kbdcp(p)->kbd, b);
76842421Syokota#if KBDIO_DEBUG >= 2
76942421Syokota		++c1;
77042421Syokota            } else {
77142421Syokota		++c2;
77242421Syokota#endif
77342421Syokota	    }
77442421Syokota	    t = wait;
77542421Syokota	} else {
77642421Syokota	    t -= delta;
77742421Syokota	}
77842421Syokota	DELAY(delta*1000);
77942421Syokota    }
78042421Syokota#if KBDIO_DEBUG >= 2
78142421Syokota    if ((c1 > 0) || (c2 > 0))
78242421Syokota        log(LOG_DEBUG, "kbdc: %d:%d char read (empty_aux_buffer)\n", c1, c2);
78342421Syokota#endif
78442421Syokota
78542421Syokota    emptyq(&kbdcp(p)->aux);
78642421Syokota}
78742421Syokota
78842421Syokota/* discard any data from the keyboard or the aux device */
78942421Syokotavoid
79042421Syokotaempty_both_buffers(KBDC p, int wait)
79142421Syokota{
79242421Syokota    int t;
79342421Syokota    int f;
79442421Syokota#if KBDIO_DEBUG >= 2
79542421Syokota    int c1 = 0;
79642421Syokota    int c2 = 0;
79742421Syokota#endif
79842421Syokota    int delta = 2;
79942421Syokota
80042421Syokota    for (t = wait; t > 0; ) {
80158271Syokota        if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) {
80242421Syokota	    DELAY(KBDD_DELAYTIME);
80358271Syokota            (void)read_data(kbdcp(p));
80442421Syokota#if KBDIO_DEBUG >= 2
80542421Syokota	    if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL)
80642421Syokota		++c1;
80742421Syokota            else
80842421Syokota		++c2;
80942421Syokota#endif
81042421Syokota	    t = wait;
81142421Syokota	} else {
81242421Syokota	    t -= delta;
81342421Syokota	}
81442421Syokota	DELAY(delta*1000);
81542421Syokota    }
81642421Syokota#if KBDIO_DEBUG >= 2
81742421Syokota    if ((c1 > 0) || (c2 > 0))
81842421Syokota        log(LOG_DEBUG, "kbdc: %d:%d char read (empty_both_buffers)\n", c1, c2);
81942421Syokota#endif
82042421Syokota
82142421Syokota    emptyq(&kbdcp(p)->kbd);
82242421Syokota    emptyq(&kbdcp(p)->aux);
82342421Syokota}
82442421Syokota
82542421Syokota/* keyboard and mouse device control */
82642421Syokota
82742421Syokota/* NOTE: enable the keyboard port but disable the keyboard
82842421Syokota * interrupt before calling "reset_kbd()".
82942421Syokota */
83042421Syokotaint
83142421Syokotareset_kbd(KBDC p)
83242421Syokota{
83342421Syokota    int retry = KBD_MAXRETRY;
83442421Syokota    int again = KBD_MAXWAIT;
83542421Syokota    int c = KBD_RESEND;		/* keep the compiler happy */
83642421Syokota
83742421Syokota    while (retry-- > 0) {
83842421Syokota        empty_both_buffers(p, 10);
83942421Syokota        if (!write_kbd_command(p, KBDC_RESET_KBD))
84042421Syokota	    continue;
84142421Syokota	emptyq(&kbdcp(p)->kbd);
84242421Syokota        c = read_controller_data(p);
84342421Syokota	if (verbose || bootverbose)
84442421Syokota            log(LOG_DEBUG, "kbdc: RESET_KBD return code:%04x\n", c);
84542421Syokota        if (c == KBD_ACK)	/* keyboard has agreed to reset itself... */
84642421Syokota    	    break;
84742421Syokota    }
84842421Syokota    if (retry < 0)
84942421Syokota        return FALSE;
85042421Syokota
85142421Syokota    while (again-- > 0) {
85242421Syokota        /* wait awhile, well, in fact we must wait quite loooooooooooong */
85342421Syokota        DELAY(KBD_RESETDELAY*1000);
85442421Syokota        c = read_controller_data(p);	/* RESET_DONE/RESET_FAIL */
85542421Syokota        if (c != -1) 	/* wait again if the controller is not ready */
85642421Syokota    	    break;
85742421Syokota    }
85842421Syokota    if (verbose || bootverbose)
85942421Syokota        log(LOG_DEBUG, "kbdc: RESET_KBD status:%04x\n", c);
86042421Syokota    if (c != KBD_RESET_DONE)
86142421Syokota        return FALSE;
86242421Syokota    return TRUE;
86342421Syokota}
86442421Syokota
86542421Syokota/* NOTE: enable the aux port but disable the aux interrupt
86642421Syokota * before calling `reset_aux_dev()'.
86742421Syokota */
86842421Syokotaint
86942421Syokotareset_aux_dev(KBDC p)
87042421Syokota{
87142421Syokota    int retry = KBD_MAXRETRY;
87242421Syokota    int again = KBD_MAXWAIT;
87342421Syokota    int c = PSM_RESEND;		/* keep the compiler happy */
87442421Syokota
87542421Syokota    while (retry-- > 0) {
87642421Syokota        empty_both_buffers(p, 10);
87742421Syokota        if (!write_aux_command(p, PSMC_RESET_DEV))
87842421Syokota	    continue;
87942421Syokota	emptyq(&kbdcp(p)->aux);
88042421Syokota	/* NOTE: Compaq Armada laptops require extra delay here. XXX */
88142421Syokota	for (again = KBD_MAXWAIT; again > 0; --again) {
88242421Syokota            DELAY(KBD_RESETDELAY*1000);
88342421Syokota            c = read_aux_data_no_wait(p);
88442421Syokota	    if (c != -1)
88542421Syokota		break;
88642421Syokota	}
88742421Syokota        if (verbose || bootverbose)
88842421Syokota            log(LOG_DEBUG, "kbdc: RESET_AUX return code:%04x\n", c);
88942421Syokota        if (c == PSM_ACK)	/* aux dev is about to reset... */
89042421Syokota    	    break;
89142421Syokota    }
89242421Syokota    if (retry < 0)
89342421Syokota        return FALSE;
89442421Syokota
89542421Syokota    for (again = KBD_MAXWAIT; again > 0; --again) {
89642421Syokota        /* wait awhile, well, quite looooooooooooong */
89742421Syokota        DELAY(KBD_RESETDELAY*1000);
89842421Syokota        c = read_aux_data_no_wait(p);	/* RESET_DONE/RESET_FAIL */
89942421Syokota        if (c != -1) 	/* wait again if the controller is not ready */
90042421Syokota    	    break;
90142421Syokota    }
90242421Syokota    if (verbose || bootverbose)
90342421Syokota        log(LOG_DEBUG, "kbdc: RESET_AUX status:%04x\n", c);
90442421Syokota    if (c != PSM_RESET_DONE)	/* reset status */
90542421Syokota        return FALSE;
90642421Syokota
90742421Syokota    c = read_aux_data(p);	/* device ID */
90842421Syokota    if (verbose || bootverbose)
90942421Syokota        log(LOG_DEBUG, "kbdc: RESET_AUX ID:%04x\n", c);
91042421Syokota    /* NOTE: we could check the device ID now, but leave it later... */
91142421Syokota    return TRUE;
91242421Syokota}
91342421Syokota
91442421Syokota/* controller diagnostics and setup */
91542421Syokota
91642421Syokotaint
91742421Syokotatest_controller(KBDC p)
91842421Syokota{
91942421Syokota    int retry = KBD_MAXRETRY;
92042421Syokota    int again = KBD_MAXWAIT;
92142421Syokota    int c = KBD_DIAG_FAIL;
92242421Syokota
92342421Syokota    while (retry-- > 0) {
92442421Syokota        empty_both_buffers(p, 10);
92542421Syokota        if (write_controller_command(p, KBDC_DIAGNOSE))
92642421Syokota    	    break;
92742421Syokota    }
92842421Syokota    if (retry < 0)
92942421Syokota        return FALSE;
93042421Syokota
93142421Syokota    emptyq(&kbdcp(p)->kbd);
93242421Syokota    while (again-- > 0) {
93342421Syokota        /* wait awhile */
93442421Syokota        DELAY(KBD_RESETDELAY*1000);
93542421Syokota        c = read_controller_data(p);	/* DIAG_DONE/DIAG_FAIL */
93642421Syokota        if (c != -1) 	/* wait again if the controller is not ready */
93742421Syokota    	    break;
93842421Syokota    }
93942421Syokota    if (verbose || bootverbose)
94042421Syokota        log(LOG_DEBUG, "kbdc: DIAGNOSE status:%04x\n", c);
94142421Syokota    return (c == KBD_DIAG_DONE);
94242421Syokota}
94342421Syokota
94442421Syokotaint
94542421Syokotatest_kbd_port(KBDC p)
94642421Syokota{
94742421Syokota    int retry = KBD_MAXRETRY;
94842421Syokota    int again = KBD_MAXWAIT;
94942421Syokota    int c = -1;
95042421Syokota
95142421Syokota    while (retry-- > 0) {
95242421Syokota        empty_both_buffers(p, 10);
95342421Syokota        if (write_controller_command(p, KBDC_TEST_KBD_PORT))
95442421Syokota    	    break;
95542421Syokota    }
95642421Syokota    if (retry < 0)
95742421Syokota        return FALSE;
95842421Syokota
95942421Syokota    emptyq(&kbdcp(p)->kbd);
96042421Syokota    while (again-- > 0) {
96142421Syokota        c = read_controller_data(p);
96242421Syokota        if (c != -1) 	/* try again if the controller is not ready */
96342421Syokota    	    break;
96442421Syokota    }
96542421Syokota    if (verbose || bootverbose)
96642421Syokota        log(LOG_DEBUG, "kbdc: TEST_KBD_PORT status:%04x\n", c);
96742421Syokota    return c;
96842421Syokota}
96942421Syokota
97042421Syokotaint
97142421Syokotatest_aux_port(KBDC p)
97242421Syokota{
97342421Syokota    int retry = KBD_MAXRETRY;
97442421Syokota    int again = KBD_MAXWAIT;
97542421Syokota    int c = -1;
97642421Syokota
97742421Syokota    while (retry-- > 0) {
97842421Syokota        empty_both_buffers(p, 10);
97942421Syokota        if (write_controller_command(p, KBDC_TEST_AUX_PORT))
98042421Syokota    	    break;
98142421Syokota    }
98242421Syokota    if (retry < 0)
98342421Syokota        return FALSE;
98442421Syokota
98542421Syokota    emptyq(&kbdcp(p)->kbd);
98642421Syokota    while (again-- > 0) {
98742421Syokota        c = read_controller_data(p);
98842421Syokota        if (c != -1) 	/* try again if the controller is not ready */
98942421Syokota    	    break;
99042421Syokota    }
99142421Syokota    if (verbose || bootverbose)
99242421Syokota        log(LOG_DEBUG, "kbdc: TEST_AUX_PORT status:%04x\n", c);
99342421Syokota    return c;
99442421Syokota}
99542421Syokota
99642421Syokotaint
99742421Syokotakbdc_get_device_mask(KBDC p)
99842421Syokota{
99942421Syokota    return kbdcp(p)->command_mask;
100042421Syokota}
100142421Syokota
100242421Syokotavoid
100342421Syokotakbdc_set_device_mask(KBDC p, int mask)
100442421Syokota{
100542421Syokota    kbdcp(p)->command_mask =
100642421Syokota	mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS);
100742421Syokota}
100842421Syokota
100942421Syokotaint
101042421Syokotaget_controller_command_byte(KBDC p)
101142421Syokota{
101242421Syokota    if (kbdcp(p)->command_byte != -1)
101342421Syokota	return kbdcp(p)->command_byte;
101442421Syokota    if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE))
101542421Syokota	return -1;
101642421Syokota    emptyq(&kbdcp(p)->kbd);
101742421Syokota    kbdcp(p)->command_byte = read_controller_data(p);
101842421Syokota    return kbdcp(p)->command_byte;
101942421Syokota}
102042421Syokota
102142421Syokotaint
102242421Syokotaset_controller_command_byte(KBDC p, int mask, int command)
102342421Syokota{
102442421Syokota    if (get_controller_command_byte(p) == -1)
102542421Syokota	return FALSE;
102642421Syokota
102742421Syokota    command = (kbdcp(p)->command_byte & ~mask) | (command & mask);
102842421Syokota    if (command & KBD_DISABLE_KBD_PORT) {
102942421Syokota	if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT))
103042421Syokota	    return FALSE;
103142421Syokota    }
103242421Syokota    if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE))
103342421Syokota	return FALSE;
103442421Syokota    if (!write_controller_data(p, command))
103542421Syokota	return FALSE;
103642421Syokota    kbdcp(p)->command_byte = command;
103742421Syokota
103842421Syokota    if (verbose)
103942421Syokota        log(LOG_DEBUG, "kbdc: new command byte:%04x (set_controller...)\n",
104042421Syokota	    command);
104142421Syokota
104242421Syokota    return TRUE;
104342421Syokota}
1044