atkbdc.c revision 65176
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 * 3050477Speter * $FreeBSD: head/sys/dev/atkbdc/atkbdc.c 65176 2000-08-28 21:48:13Z dfr $ 3142421Syokota * from kbdio.c,v 1.13 1998/09/25 11:55:46 yokota Exp 3242421Syokota */ 3342421Syokota 3442421Syokota#include "atkbdc.h" 3542421Syokota#include "opt_kbd.h" 3642421Syokota 3742421Syokota#include <sys/param.h> 3842421Syokota#include <sys/systm.h> 3958271Syokota#include <sys/bus.h> 4042421Syokota#include <sys/malloc.h> 4142421Syokota#include <sys/syslog.h> 4258271Syokota#include <machine/bus_pio.h> 4358271Syokota#include <machine/bus.h> 4458271Syokota#include <machine/resource.h> 4558271Syokota#include <sys/rman.h> 4642421Syokota 4742421Syokota#include <machine/clock.h> 4842421Syokota 4942421Syokota#include <dev/kbd/atkbdcreg.h> 5042421Syokota 5142421Syokota#include <isa/isareg.h> 5242421Syokota 5342421Syokota/* constants */ 5442421Syokota 5556836Speter#define MAXKBDC MAX(NATKBDC, 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] 11542421Syokota = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); 11642421Syokota if (sc == NULL) 11742421Syokota return NULL; 11842421Syokota bzero(sc, sizeof(*sc)); 11942421Syokota } 12042421Syokota return sc; 12142421Syokota} 12242421Syokota 12342421Syokotaint 12458271Syokotaatkbdc_probe_unit(int unit, struct resource *port0, struct resource *port1) 12542421Syokota{ 12658271Syokota if (rman_get_start(port0) <= 0) 12747296Syokota return ENXIO; 12858271Syokota if (rman_get_start(port1) <= 0) 12958271Syokota return ENXIO; 13047296Syokota return 0; 13147296Syokota} 13247296Syokota 13347296Syokotaint 13458271Syokotaatkbdc_attach_unit(int unit, atkbdc_softc_t *sc, struct resource *port0, 13558271Syokota struct resource *port1) 13647296Syokota{ 13758271Syokota return atkbdc_setup(sc, rman_get_bustag(port0), 13858271Syokota rman_get_bushandle(port0), 13958271Syokota rman_get_bushandle(port1)); 14042421Syokota} 14142421Syokota 14242421Syokota/* the backdoor to the keyboard controller! XXX */ 14342421Syokotaint 14442421Syokotaatkbdc_configure(void) 14542421Syokota{ 14658271Syokota bus_space_tag_t tag; 14758271Syokota bus_space_handle_t h0; 14858271Syokota bus_space_handle_t h1; 14958271Syokota int port0; 15058271Syokota int port1; 15158271Syokota 15258271Syokota port0 = IO_KBD; 15358271Syokota resource_int_value("atkbdc", 0, "port", &port0); 15458271Syokota port1 = IO_KBD + KBD_STATUS_PORT; 15558271Syokota#if 0 15658271Syokota resource_int_value("atkbdc", 0, "port", &port0); 15758271Syokota#endif 15858271Syokota 15958271Syokota /* XXX: tag should be passed from the caller */ 16058271Syokota#if defined(__i386__) 16158271Syokota tag = I386_BUS_SPACE_IO; 16258271Syokota#elif defined(__alpha__) 16365176Sdfr tag = busspace_isa_io; 16458271Syokota#endif 16558271Syokota 16658271Syokota#if notyet 16758271Syokota bus_space_map(tag, port0, IO_KBDSIZE, 0, &h0); 16858271Syokota bus_space_map(tag, port1, IO_KBDSIZE, 0, &h1); 16958271Syokota#else 17058271Syokota h0 = (bus_space_handle_t)port0; 17158271Syokota h1 = (bus_space_handle_t)port1; 17258271Syokota#endif 17358271Syokota return atkbdc_setup(atkbdc_softc[0], tag, h0, h1); 17442421Syokota} 17542421Syokota 17642421Syokotastatic int 17758271Syokotaatkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0, 17858271Syokota bus_space_handle_t h1) 17942421Syokota{ 18058271Syokota if (sc->ioh0 == 0) { /* XXX */ 18142421Syokota sc->command_byte = -1; 18242421Syokota sc->command_mask = 0; 18342421Syokota sc->lock = FALSE; 18442421Syokota sc->kbd.head = sc->kbd.tail = 0; 18542421Syokota sc->aux.head = sc->aux.tail = 0; 18642421Syokota#if KBDIO_DEBUG >= 2 18742421Syokota sc->kbd.call_count = 0; 18842421Syokota sc->kbd.qcount = sc->kbd.max_qcount = 0; 18942421Syokota sc->aux.call_count = 0; 19042421Syokota sc->aux.qcount = sc->aux.max_qcount = 0; 19142421Syokota#endif 19242421Syokota } 19358271Syokota sc->iot = tag; 19458271Syokota sc->ioh0 = h0; 19558271Syokota sc->ioh1 = h1; 19642421Syokota return 0; 19742421Syokota} 19842421Syokota 19958271Syokota/* open a keyboard controller */ 20042421SyokotaKBDC 20158271Syokotaatkbdc_open(int unit) 20242421Syokota{ 20358271Syokota if (unit <= 0) 20458271Syokota unit = 0; 20558271Syokota if (unit >= MAXKBDC) 20658271Syokota return NULL; 20758271Syokota if ((atkbdc_softc[unit]->port0 != NULL) 20858271Syokota || (atkbdc_softc[unit]->ioh0 != 0)) /* XXX */ 20958271Syokota return (KBDC)atkbdc_softc[unit]; 21042421Syokota return NULL; 21142421Syokota} 21242421Syokota 21342421Syokota/* 21442421Syokota * I/O access arbitration in `kbdio' 21542421Syokota * 21642421Syokota * The `kbdio' module uses a simplistic convention to arbitrate 21742421Syokota * I/O access to the controller/keyboard/mouse. The convention requires 21842421Syokota * close cooperation of the calling device driver. 21942421Syokota * 22042421Syokota * The device driver which utilizes the `kbdio' module are assumed to 22142421Syokota * have the following set of routines. 22242421Syokota * a. An interrupt handler (the bottom half of the driver). 22342421Syokota * b. Timeout routines which may briefly polls the keyboard controller. 22442421Syokota * c. Routines outside interrupt context (the top half of the driver). 22542421Syokota * They should follow the rules below: 22642421Syokota * 1. The interrupt handler may assume that it always has full access 22742421Syokota * to the controller/keyboard/mouse. 22842421Syokota * 2. The other routines must issue `spltty()' if they wish to 22942421Syokota * prevent the interrupt handler from accessing 23042421Syokota * the controller/keyboard/mouse. 23142421Syokota * 3. The timeout routines and the top half routines of the device driver 23242421Syokota * arbitrate I/O access by observing the lock flag in `kbdio'. 23342421Syokota * The flag is manipulated via `kbdc_lock()'; when one wants to 23442421Syokota * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if 23542421Syokota * the call returns with TRUE. Otherwise the caller must back off. 23642421Syokota * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion 23742421Syokota * is finished. This mechanism does not prevent the interrupt 23842421Syokota * handler from being invoked at any time and carrying out I/O. 23942421Syokota * Therefore, `spltty()' must be strategically placed in the device 24042421Syokota * driver code. Also note that the timeout routine may interrupt 24142421Syokota * `kbdc_lock()' called by the top half of the driver, but this 24242421Syokota * interruption is OK so long as the timeout routine observes the 24342421Syokota * the rule 4 below. 24442421Syokota * 4. The interrupt and timeout routines should not extend I/O operation 24542421Syokota * across more than one interrupt or timeout; they must complete 24642421Syokota * necessary I/O operation within one invokation of the routine. 24742421Syokota * This measns that if the timeout routine acquires the lock flag, 24842421Syokota * it must reset the flag to FALSE before it returns. 24942421Syokota */ 25042421Syokota 25142421Syokota/* set/reset polling lock */ 25242421Syokotaint 25342421Syokotakbdc_lock(KBDC p, int lock) 25442421Syokota{ 25542421Syokota int prevlock; 25642421Syokota 25742421Syokota prevlock = kbdcp(p)->lock; 25842421Syokota kbdcp(p)->lock = lock; 25942421Syokota 26042421Syokota return (prevlock != lock); 26142421Syokota} 26242421Syokota 26342421Syokota/* check if any data is waiting to be processed */ 26442421Syokotaint 26542421Syokotakbdc_data_ready(KBDC p) 26642421Syokota{ 26742421Syokota return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux) 26858271Syokota || (read_status(kbdcp(p)) & KBDS_ANY_BUFFER_FULL)); 26942421Syokota} 27042421Syokota 27142421Syokota/* queuing functions */ 27242421Syokota 27342421Syokotastatic int 27442421Syokotaaddq(kqueue *q, int c) 27542421Syokota{ 27642421Syokota if (nextq(q->tail) != q->head) { 27742421Syokota q->q[q->tail] = c; 27842421Syokota q->tail = nextq(q->tail); 27942421Syokota#if KBDIO_DEBUG >= 2 28042421Syokota ++q->call_count; 28142421Syokota ++q->qcount; 28242421Syokota if (q->qcount > q->max_qcount) 28342421Syokota q->max_qcount = q->qcount; 28442421Syokota#endif 28542421Syokota return TRUE; 28642421Syokota } 28742421Syokota return FALSE; 28842421Syokota} 28942421Syokota 29042421Syokotastatic int 29142421Syokotaremoveq(kqueue *q) 29242421Syokota{ 29342421Syokota int c; 29442421Syokota 29542421Syokota if (q->tail != q->head) { 29642421Syokota c = q->q[q->head]; 29742421Syokota q->head = nextq(q->head); 29842421Syokota#if KBDIO_DEBUG >= 2 29942421Syokota --q->qcount; 30042421Syokota#endif 30142421Syokota return c; 30242421Syokota } 30342421Syokota return -1; 30442421Syokota} 30542421Syokota 30642421Syokota/* 30742421Syokota * device I/O routines 30842421Syokota */ 30942421Syokotastatic int 31042421Syokotawait_while_controller_busy(struct atkbdc_softc *kbdc) 31142421Syokota{ 31242421Syokota /* CPU will stay inside the loop for 100msec at most */ 31342421Syokota int retry = 5000; 31442421Syokota int f; 31542421Syokota 31658271Syokota while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) { 31742421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 31842421Syokota DELAY(KBDD_DELAYTIME); 31958271Syokota addq(&kbdc->kbd, read_data(kbdc)); 32042421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 32142421Syokota DELAY(KBDD_DELAYTIME); 32258271Syokota addq(&kbdc->aux, read_data(kbdc)); 32342421Syokota } 32442421Syokota DELAY(KBDC_DELAYTIME); 32542421Syokota if (--retry < 0) 32642421Syokota return FALSE; 32742421Syokota } 32842421Syokota return TRUE; 32942421Syokota} 33042421Syokota 33142421Syokota/* 33242421Syokota * wait for any data; whether it's from the controller, 33342421Syokota * the keyboard, or the aux device. 33442421Syokota */ 33542421Syokotastatic int 33642421Syokotawait_for_data(struct atkbdc_softc *kbdc) 33742421Syokota{ 33842421Syokota /* CPU will stay inside the loop for 200msec at most */ 33942421Syokota int retry = 10000; 34042421Syokota int f; 34142421Syokota 34258271Syokota while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) { 34342421Syokota DELAY(KBDC_DELAYTIME); 34442421Syokota if (--retry < 0) 34542421Syokota return 0; 34642421Syokota } 34742421Syokota DELAY(KBDD_DELAYTIME); 34842421Syokota return f; 34942421Syokota} 35042421Syokota 35142421Syokota/* wait for data from the keyboard */ 35242421Syokotastatic int 35342421Syokotawait_for_kbd_data(struct atkbdc_softc *kbdc) 35442421Syokota{ 35542421Syokota /* CPU will stay inside the loop for 200msec at most */ 35642421Syokota int retry = 10000; 35742421Syokota int f; 35842421Syokota 35958271Syokota while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) 36042421Syokota != KBDS_KBD_BUFFER_FULL) { 36142421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 36242421Syokota DELAY(KBDD_DELAYTIME); 36358271Syokota addq(&kbdc->aux, read_data(kbdc)); 36442421Syokota } 36542421Syokota DELAY(KBDC_DELAYTIME); 36642421Syokota if (--retry < 0) 36742421Syokota return 0; 36842421Syokota } 36942421Syokota DELAY(KBDD_DELAYTIME); 37042421Syokota return f; 37142421Syokota} 37242421Syokota 37342421Syokota/* 37442421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard. 37542421Syokota * queue anything else. 37642421Syokota */ 37742421Syokotastatic int 37842421Syokotawait_for_kbd_ack(struct atkbdc_softc *kbdc) 37942421Syokota{ 38042421Syokota /* CPU will stay inside the loop for 200msec at most */ 38142421Syokota int retry = 10000; 38242421Syokota int f; 38342421Syokota int b; 38442421Syokota 38542421Syokota while (retry-- > 0) { 38658271Syokota if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { 38742421Syokota DELAY(KBDD_DELAYTIME); 38858271Syokota b = read_data(kbdc); 38942421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 39042421Syokota if ((b == KBD_ACK) || (b == KBD_RESEND) 39142421Syokota || (b == KBD_RESET_FAIL)) 39242421Syokota return b; 39342421Syokota addq(&kbdc->kbd, b); 39442421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 39542421Syokota addq(&kbdc->aux, b); 39642421Syokota } 39742421Syokota } 39842421Syokota DELAY(KBDC_DELAYTIME); 39942421Syokota } 40042421Syokota return -1; 40142421Syokota} 40242421Syokota 40342421Syokota/* wait for data from the aux device */ 40442421Syokotastatic int 40542421Syokotawait_for_aux_data(struct atkbdc_softc *kbdc) 40642421Syokota{ 40742421Syokota /* CPU will stay inside the loop for 200msec at most */ 40842421Syokota int retry = 10000; 40942421Syokota int f; 41042421Syokota 41158271Syokota while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) 41242421Syokota != KBDS_AUX_BUFFER_FULL) { 41342421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 41442421Syokota DELAY(KBDD_DELAYTIME); 41558271Syokota addq(&kbdc->kbd, read_data(kbdc)); 41642421Syokota } 41742421Syokota DELAY(KBDC_DELAYTIME); 41842421Syokota if (--retry < 0) 41942421Syokota return 0; 42042421Syokota } 42142421Syokota DELAY(KBDD_DELAYTIME); 42242421Syokota return f; 42342421Syokota} 42442421Syokota 42542421Syokota/* 42642421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device. 42742421Syokota * queue anything else. 42842421Syokota */ 42942421Syokotastatic int 43042421Syokotawait_for_aux_ack(struct atkbdc_softc *kbdc) 43142421Syokota{ 43242421Syokota /* CPU will stay inside the loop for 200msec at most */ 43342421Syokota int retry = 10000; 43442421Syokota int f; 43542421Syokota int b; 43642421Syokota 43742421Syokota while (retry-- > 0) { 43858271Syokota if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { 43942421Syokota DELAY(KBDD_DELAYTIME); 44058271Syokota b = read_data(kbdc); 44142421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 44242421Syokota if ((b == PSM_ACK) || (b == PSM_RESEND) 44342421Syokota || (b == PSM_RESET_FAIL)) 44442421Syokota return b; 44542421Syokota addq(&kbdc->aux, b); 44642421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 44742421Syokota addq(&kbdc->kbd, b); 44842421Syokota } 44942421Syokota } 45042421Syokota DELAY(KBDC_DELAYTIME); 45142421Syokota } 45242421Syokota return -1; 45342421Syokota} 45442421Syokota 45542421Syokota/* write a one byte command to the controller */ 45642421Syokotaint 45742421Syokotawrite_controller_command(KBDC p, int c) 45842421Syokota{ 45942421Syokota if (!wait_while_controller_busy(kbdcp(p))) 46042421Syokota return FALSE; 46158271Syokota write_command(kbdcp(p), c); 46242421Syokota return TRUE; 46342421Syokota} 46442421Syokota 46542421Syokota/* write a one byte data to the controller */ 46642421Syokotaint 46742421Syokotawrite_controller_data(KBDC p, int c) 46842421Syokota{ 46942421Syokota if (!wait_while_controller_busy(kbdcp(p))) 47042421Syokota return FALSE; 47158271Syokota write_data(kbdcp(p), c); 47242421Syokota return TRUE; 47342421Syokota} 47442421Syokota 47542421Syokota/* write a one byte keyboard command */ 47642421Syokotaint 47742421Syokotawrite_kbd_command(KBDC p, int c) 47842421Syokota{ 47942421Syokota if (!wait_while_controller_busy(kbdcp(p))) 48042421Syokota return FALSE; 48158271Syokota write_data(kbdcp(p), c); 48242421Syokota return TRUE; 48342421Syokota} 48442421Syokota 48542421Syokota/* write a one byte auxiliary device command */ 48642421Syokotaint 48742421Syokotawrite_aux_command(KBDC p, int c) 48842421Syokota{ 48942421Syokota if (!write_controller_command(p, KBDC_WRITE_TO_AUX)) 49042421Syokota return FALSE; 49142421Syokota return write_controller_data(p, c); 49242421Syokota} 49342421Syokota 49442421Syokota/* send a command to the keyboard and wait for ACK */ 49542421Syokotaint 49642421Syokotasend_kbd_command(KBDC p, int c) 49742421Syokota{ 49842421Syokota int retry = KBD_MAXRETRY; 49942421Syokota int res = -1; 50042421Syokota 50142421Syokota while (retry-- > 0) { 50242421Syokota if (!write_kbd_command(p, c)) 50342421Syokota continue; 50442421Syokota res = wait_for_kbd_ack(kbdcp(p)); 50542421Syokota if (res == KBD_ACK) 50642421Syokota break; 50742421Syokota } 50842421Syokota return res; 50942421Syokota} 51042421Syokota 51142421Syokota/* send a command to the auxiliary device and wait for ACK */ 51242421Syokotaint 51342421Syokotasend_aux_command(KBDC p, int c) 51442421Syokota{ 51542421Syokota int retry = KBD_MAXRETRY; 51642421Syokota int res = -1; 51742421Syokota 51842421Syokota while (retry-- > 0) { 51942421Syokota if (!write_aux_command(p, c)) 52042421Syokota continue; 52142421Syokota /* 52242421Syokota * FIXME: XXX 52342421Syokota * The aux device may have already sent one or two bytes of 52442421Syokota * status data, when a command is received. It will immediately 52542421Syokota * stop data transmission, thus, leaving an incomplete data 52642421Syokota * packet in our buffer. We have to discard any unprocessed 52742421Syokota * data in order to remove such packets. Well, we may remove 52842421Syokota * unprocessed, but necessary data byte as well... 52942421Syokota */ 53042421Syokota emptyq(&kbdcp(p)->aux); 53142421Syokota res = wait_for_aux_ack(kbdcp(p)); 53242421Syokota if (res == PSM_ACK) 53342421Syokota break; 53442421Syokota } 53542421Syokota return res; 53642421Syokota} 53742421Syokota 53842421Syokota/* send a command and a data to the keyboard, wait for ACKs */ 53942421Syokotaint 54042421Syokotasend_kbd_command_and_data(KBDC p, int c, int d) 54142421Syokota{ 54242421Syokota int retry; 54342421Syokota int res = -1; 54442421Syokota 54542421Syokota for (retry = KBD_MAXRETRY; retry > 0; --retry) { 54642421Syokota if (!write_kbd_command(p, c)) 54742421Syokota continue; 54842421Syokota res = wait_for_kbd_ack(kbdcp(p)); 54942421Syokota if (res == KBD_ACK) 55042421Syokota break; 55142421Syokota else if (res != KBD_RESEND) 55242421Syokota return res; 55342421Syokota } 55442421Syokota if (retry <= 0) 55542421Syokota return res; 55642421Syokota 55742421Syokota for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { 55842421Syokota if (!write_kbd_command(p, d)) 55942421Syokota continue; 56042421Syokota res = wait_for_kbd_ack(kbdcp(p)); 56142421Syokota if (res != KBD_RESEND) 56242421Syokota break; 56342421Syokota } 56442421Syokota return res; 56542421Syokota} 56642421Syokota 56742421Syokota/* send a command and a data to the auxiliary device, wait for ACKs */ 56842421Syokotaint 56942421Syokotasend_aux_command_and_data(KBDC p, int c, int d) 57042421Syokota{ 57142421Syokota int retry; 57242421Syokota int res = -1; 57342421Syokota 57442421Syokota for (retry = KBD_MAXRETRY; retry > 0; --retry) { 57542421Syokota if (!write_aux_command(p, c)) 57642421Syokota continue; 57742421Syokota emptyq(&kbdcp(p)->aux); 57842421Syokota res = wait_for_aux_ack(kbdcp(p)); 57942421Syokota if (res == PSM_ACK) 58042421Syokota break; 58142421Syokota else if (res != PSM_RESEND) 58242421Syokota return res; 58342421Syokota } 58442421Syokota if (retry <= 0) 58542421Syokota return res; 58642421Syokota 58742421Syokota for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { 58842421Syokota if (!write_aux_command(p, d)) 58942421Syokota continue; 59042421Syokota res = wait_for_aux_ack(kbdcp(p)); 59142421Syokota if (res != PSM_RESEND) 59242421Syokota break; 59342421Syokota } 59442421Syokota return res; 59542421Syokota} 59642421Syokota 59742421Syokota/* 59842421Syokota * read one byte from any source; whether from the controller, 59942421Syokota * the keyboard, or the aux device 60042421Syokota */ 60142421Syokotaint 60242421Syokotaread_controller_data(KBDC p) 60342421Syokota{ 60442421Syokota if (availq(&kbdcp(p)->kbd)) 60542421Syokota return removeq(&kbdcp(p)->kbd); 60642421Syokota if (availq(&kbdcp(p)->aux)) 60742421Syokota return removeq(&kbdcp(p)->aux); 60842421Syokota if (!wait_for_data(kbdcp(p))) 60942421Syokota return -1; /* timeout */ 61058271Syokota return read_data(kbdcp(p)); 61142421Syokota} 61242421Syokota 61342421Syokota#if KBDIO_DEBUG >= 2 61442421Syokotastatic int call = 0; 61542421Syokota#endif 61642421Syokota 61742421Syokota/* read one byte from the keyboard */ 61842421Syokotaint 61942421Syokotaread_kbd_data(KBDC p) 62042421Syokota{ 62142421Syokota#if KBDIO_DEBUG >= 2 62242421Syokota if (++call > 2000) { 62342421Syokota call = 0; 62442421Syokota log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, " 62542421Syokota "aux q: %d calls, max %d chars\n", 62642421Syokota kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, 62742421Syokota kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); 62842421Syokota } 62942421Syokota#endif 63042421Syokota 63142421Syokota if (availq(&kbdcp(p)->kbd)) 63242421Syokota return removeq(&kbdcp(p)->kbd); 63342421Syokota if (!wait_for_kbd_data(kbdcp(p))) 63442421Syokota return -1; /* timeout */ 63558271Syokota return read_data(kbdcp(p)); 63642421Syokota} 63742421Syokota 63842421Syokota/* read one byte from the keyboard, but return immediately if 63942421Syokota * no data is waiting 64042421Syokota */ 64142421Syokotaint 64242421Syokotaread_kbd_data_no_wait(KBDC p) 64342421Syokota{ 64442421Syokota int f; 64542421Syokota 64642421Syokota#if KBDIO_DEBUG >= 2 64742421Syokota if (++call > 2000) { 64842421Syokota call = 0; 64942421Syokota log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, " 65042421Syokota "aux q: %d calls, max %d chars\n", 65142421Syokota kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, 65242421Syokota kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); 65342421Syokota } 65442421Syokota#endif 65542421Syokota 65642421Syokota if (availq(&kbdcp(p)->kbd)) 65742421Syokota return removeq(&kbdcp(p)->kbd); 65858271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 65942421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 66042421Syokota DELAY(KBDD_DELAYTIME); 66158271Syokota addq(&kbdcp(p)->aux, read_data(kbdcp(p))); 66258271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 66342421Syokota } 66442421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 66542421Syokota DELAY(KBDD_DELAYTIME); 66658271Syokota return read_data(kbdcp(p)); 66742421Syokota } 66842421Syokota return -1; /* no data */ 66942421Syokota} 67042421Syokota 67142421Syokota/* read one byte from the aux device */ 67242421Syokotaint 67342421Syokotaread_aux_data(KBDC p) 67442421Syokota{ 67542421Syokota if (availq(&kbdcp(p)->aux)) 67642421Syokota return removeq(&kbdcp(p)->aux); 67742421Syokota if (!wait_for_aux_data(kbdcp(p))) 67842421Syokota return -1; /* timeout */ 67958271Syokota return read_data(kbdcp(p)); 68042421Syokota} 68142421Syokota 68242421Syokota/* read one byte from the aux device, but return immediately if 68342421Syokota * no data is waiting 68442421Syokota */ 68542421Syokotaint 68642421Syokotaread_aux_data_no_wait(KBDC p) 68742421Syokota{ 68842421Syokota int f; 68942421Syokota 69042421Syokota if (availq(&kbdcp(p)->aux)) 69142421Syokota return removeq(&kbdcp(p)->aux); 69258271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 69342421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 69442421Syokota DELAY(KBDD_DELAYTIME); 69558271Syokota addq(&kbdcp(p)->kbd, read_data(kbdcp(p))); 69658271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 69742421Syokota } 69842421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 69942421Syokota DELAY(KBDD_DELAYTIME); 70058271Syokota return read_data(kbdcp(p)); 70142421Syokota } 70242421Syokota return -1; /* no data */ 70342421Syokota} 70442421Syokota 70542421Syokota/* discard data from the keyboard */ 70642421Syokotavoid 70742421Syokotaempty_kbd_buffer(KBDC p, int wait) 70842421Syokota{ 70942421Syokota int t; 71042421Syokota int b; 71142421Syokota int f; 71242421Syokota#if KBDIO_DEBUG >= 2 71342421Syokota int c1 = 0; 71442421Syokota int c2 = 0; 71542421Syokota#endif 71642421Syokota int delta = 2; 71742421Syokota 71842421Syokota for (t = wait; t > 0; ) { 71958271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 72042421Syokota DELAY(KBDD_DELAYTIME); 72158271Syokota b = read_data(kbdcp(p)); 72242421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 72342421Syokota addq(&kbdcp(p)->aux, b); 72442421Syokota#if KBDIO_DEBUG >= 2 72542421Syokota ++c2; 72642421Syokota } else { 72742421Syokota ++c1; 72842421Syokota#endif 72942421Syokota } 73042421Syokota t = wait; 73142421Syokota } else { 73242421Syokota t -= delta; 73342421Syokota } 73442421Syokota DELAY(delta*1000); 73542421Syokota } 73642421Syokota#if KBDIO_DEBUG >= 2 73742421Syokota if ((c1 > 0) || (c2 > 0)) 73842421Syokota log(LOG_DEBUG, "kbdc: %d:%d char read (empty_kbd_buffer)\n", c1, c2); 73942421Syokota#endif 74042421Syokota 74142421Syokota emptyq(&kbdcp(p)->kbd); 74242421Syokota} 74342421Syokota 74442421Syokota/* discard data from the aux device */ 74542421Syokotavoid 74642421Syokotaempty_aux_buffer(KBDC p, int wait) 74742421Syokota{ 74842421Syokota int t; 74942421Syokota int b; 75042421Syokota int f; 75142421Syokota#if KBDIO_DEBUG >= 2 75242421Syokota int c1 = 0; 75342421Syokota int c2 = 0; 75442421Syokota#endif 75542421Syokota int delta = 2; 75642421Syokota 75742421Syokota for (t = wait; t > 0; ) { 75858271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 75942421Syokota DELAY(KBDD_DELAYTIME); 76058271Syokota b = read_data(kbdcp(p)); 76142421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 76242421Syokota addq(&kbdcp(p)->kbd, b); 76342421Syokota#if KBDIO_DEBUG >= 2 76442421Syokota ++c1; 76542421Syokota } else { 76642421Syokota ++c2; 76742421Syokota#endif 76842421Syokota } 76942421Syokota t = wait; 77042421Syokota } else { 77142421Syokota t -= delta; 77242421Syokota } 77342421Syokota DELAY(delta*1000); 77442421Syokota } 77542421Syokota#if KBDIO_DEBUG >= 2 77642421Syokota if ((c1 > 0) || (c2 > 0)) 77742421Syokota log(LOG_DEBUG, "kbdc: %d:%d char read (empty_aux_buffer)\n", c1, c2); 77842421Syokota#endif 77942421Syokota 78042421Syokota emptyq(&kbdcp(p)->aux); 78142421Syokota} 78242421Syokota 78342421Syokota/* discard any data from the keyboard or the aux device */ 78442421Syokotavoid 78542421Syokotaempty_both_buffers(KBDC p, int wait) 78642421Syokota{ 78742421Syokota int t; 78842421Syokota int f; 78942421Syokota#if KBDIO_DEBUG >= 2 79042421Syokota int c1 = 0; 79142421Syokota int c2 = 0; 79242421Syokota#endif 79342421Syokota int delta = 2; 79442421Syokota 79542421Syokota for (t = wait; t > 0; ) { 79658271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 79742421Syokota DELAY(KBDD_DELAYTIME); 79858271Syokota (void)read_data(kbdcp(p)); 79942421Syokota#if KBDIO_DEBUG >= 2 80042421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) 80142421Syokota ++c1; 80242421Syokota else 80342421Syokota ++c2; 80442421Syokota#endif 80542421Syokota t = wait; 80642421Syokota } else { 80742421Syokota t -= delta; 80842421Syokota } 80942421Syokota DELAY(delta*1000); 81042421Syokota } 81142421Syokota#if KBDIO_DEBUG >= 2 81242421Syokota if ((c1 > 0) || (c2 > 0)) 81342421Syokota log(LOG_DEBUG, "kbdc: %d:%d char read (empty_both_buffers)\n", c1, c2); 81442421Syokota#endif 81542421Syokota 81642421Syokota emptyq(&kbdcp(p)->kbd); 81742421Syokota emptyq(&kbdcp(p)->aux); 81842421Syokota} 81942421Syokota 82042421Syokota/* keyboard and mouse device control */ 82142421Syokota 82242421Syokota/* NOTE: enable the keyboard port but disable the keyboard 82342421Syokota * interrupt before calling "reset_kbd()". 82442421Syokota */ 82542421Syokotaint 82642421Syokotareset_kbd(KBDC p) 82742421Syokota{ 82842421Syokota int retry = KBD_MAXRETRY; 82942421Syokota int again = KBD_MAXWAIT; 83042421Syokota int c = KBD_RESEND; /* keep the compiler happy */ 83142421Syokota 83242421Syokota while (retry-- > 0) { 83342421Syokota empty_both_buffers(p, 10); 83442421Syokota if (!write_kbd_command(p, KBDC_RESET_KBD)) 83542421Syokota continue; 83642421Syokota emptyq(&kbdcp(p)->kbd); 83742421Syokota c = read_controller_data(p); 83842421Syokota if (verbose || bootverbose) 83942421Syokota log(LOG_DEBUG, "kbdc: RESET_KBD return code:%04x\n", c); 84042421Syokota if (c == KBD_ACK) /* keyboard has agreed to reset itself... */ 84142421Syokota break; 84242421Syokota } 84342421Syokota if (retry < 0) 84442421Syokota return FALSE; 84542421Syokota 84642421Syokota while (again-- > 0) { 84742421Syokota /* wait awhile, well, in fact we must wait quite loooooooooooong */ 84842421Syokota DELAY(KBD_RESETDELAY*1000); 84942421Syokota c = read_controller_data(p); /* RESET_DONE/RESET_FAIL */ 85042421Syokota if (c != -1) /* wait again if the controller is not ready */ 85142421Syokota break; 85242421Syokota } 85342421Syokota if (verbose || bootverbose) 85442421Syokota log(LOG_DEBUG, "kbdc: RESET_KBD status:%04x\n", c); 85542421Syokota if (c != KBD_RESET_DONE) 85642421Syokota return FALSE; 85742421Syokota return TRUE; 85842421Syokota} 85942421Syokota 86042421Syokota/* NOTE: enable the aux port but disable the aux interrupt 86142421Syokota * before calling `reset_aux_dev()'. 86242421Syokota */ 86342421Syokotaint 86442421Syokotareset_aux_dev(KBDC p) 86542421Syokota{ 86642421Syokota int retry = KBD_MAXRETRY; 86742421Syokota int again = KBD_MAXWAIT; 86842421Syokota int c = PSM_RESEND; /* keep the compiler happy */ 86942421Syokota 87042421Syokota while (retry-- > 0) { 87142421Syokota empty_both_buffers(p, 10); 87242421Syokota if (!write_aux_command(p, PSMC_RESET_DEV)) 87342421Syokota continue; 87442421Syokota emptyq(&kbdcp(p)->aux); 87542421Syokota /* NOTE: Compaq Armada laptops require extra delay here. XXX */ 87642421Syokota for (again = KBD_MAXWAIT; again > 0; --again) { 87742421Syokota DELAY(KBD_RESETDELAY*1000); 87842421Syokota c = read_aux_data_no_wait(p); 87942421Syokota if (c != -1) 88042421Syokota break; 88142421Syokota } 88242421Syokota if (verbose || bootverbose) 88342421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX return code:%04x\n", c); 88442421Syokota if (c == PSM_ACK) /* aux dev is about to reset... */ 88542421Syokota break; 88642421Syokota } 88742421Syokota if (retry < 0) 88842421Syokota return FALSE; 88942421Syokota 89042421Syokota for (again = KBD_MAXWAIT; again > 0; --again) { 89142421Syokota /* wait awhile, well, quite looooooooooooong */ 89242421Syokota DELAY(KBD_RESETDELAY*1000); 89342421Syokota c = read_aux_data_no_wait(p); /* RESET_DONE/RESET_FAIL */ 89442421Syokota if (c != -1) /* wait again if the controller is not ready */ 89542421Syokota break; 89642421Syokota } 89742421Syokota if (verbose || bootverbose) 89842421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX status:%04x\n", c); 89942421Syokota if (c != PSM_RESET_DONE) /* reset status */ 90042421Syokota return FALSE; 90142421Syokota 90242421Syokota c = read_aux_data(p); /* device ID */ 90342421Syokota if (verbose || bootverbose) 90442421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX ID:%04x\n", c); 90542421Syokota /* NOTE: we could check the device ID now, but leave it later... */ 90642421Syokota return TRUE; 90742421Syokota} 90842421Syokota 90942421Syokota/* controller diagnostics and setup */ 91042421Syokota 91142421Syokotaint 91242421Syokotatest_controller(KBDC p) 91342421Syokota{ 91442421Syokota int retry = KBD_MAXRETRY; 91542421Syokota int again = KBD_MAXWAIT; 91642421Syokota int c = KBD_DIAG_FAIL; 91742421Syokota 91842421Syokota while (retry-- > 0) { 91942421Syokota empty_both_buffers(p, 10); 92042421Syokota if (write_controller_command(p, KBDC_DIAGNOSE)) 92142421Syokota break; 92242421Syokota } 92342421Syokota if (retry < 0) 92442421Syokota return FALSE; 92542421Syokota 92642421Syokota emptyq(&kbdcp(p)->kbd); 92742421Syokota while (again-- > 0) { 92842421Syokota /* wait awhile */ 92942421Syokota DELAY(KBD_RESETDELAY*1000); 93042421Syokota c = read_controller_data(p); /* DIAG_DONE/DIAG_FAIL */ 93142421Syokota if (c != -1) /* wait again if the controller is not ready */ 93242421Syokota break; 93342421Syokota } 93442421Syokota if (verbose || bootverbose) 93542421Syokota log(LOG_DEBUG, "kbdc: DIAGNOSE status:%04x\n", c); 93642421Syokota return (c == KBD_DIAG_DONE); 93742421Syokota} 93842421Syokota 93942421Syokotaint 94042421Syokotatest_kbd_port(KBDC p) 94142421Syokota{ 94242421Syokota int retry = KBD_MAXRETRY; 94342421Syokota int again = KBD_MAXWAIT; 94442421Syokota int c = -1; 94542421Syokota 94642421Syokota while (retry-- > 0) { 94742421Syokota empty_both_buffers(p, 10); 94842421Syokota if (write_controller_command(p, KBDC_TEST_KBD_PORT)) 94942421Syokota break; 95042421Syokota } 95142421Syokota if (retry < 0) 95242421Syokota return FALSE; 95342421Syokota 95442421Syokota emptyq(&kbdcp(p)->kbd); 95542421Syokota while (again-- > 0) { 95642421Syokota c = read_controller_data(p); 95742421Syokota if (c != -1) /* try again if the controller is not ready */ 95842421Syokota break; 95942421Syokota } 96042421Syokota if (verbose || bootverbose) 96142421Syokota log(LOG_DEBUG, "kbdc: TEST_KBD_PORT status:%04x\n", c); 96242421Syokota return c; 96342421Syokota} 96442421Syokota 96542421Syokotaint 96642421Syokotatest_aux_port(KBDC p) 96742421Syokota{ 96842421Syokota int retry = KBD_MAXRETRY; 96942421Syokota int again = KBD_MAXWAIT; 97042421Syokota int c = -1; 97142421Syokota 97242421Syokota while (retry-- > 0) { 97342421Syokota empty_both_buffers(p, 10); 97442421Syokota if (write_controller_command(p, KBDC_TEST_AUX_PORT)) 97542421Syokota break; 97642421Syokota } 97742421Syokota if (retry < 0) 97842421Syokota return FALSE; 97942421Syokota 98042421Syokota emptyq(&kbdcp(p)->kbd); 98142421Syokota while (again-- > 0) { 98242421Syokota c = read_controller_data(p); 98342421Syokota if (c != -1) /* try again if the controller is not ready */ 98442421Syokota break; 98542421Syokota } 98642421Syokota if (verbose || bootverbose) 98742421Syokota log(LOG_DEBUG, "kbdc: TEST_AUX_PORT status:%04x\n", c); 98842421Syokota return c; 98942421Syokota} 99042421Syokota 99142421Syokotaint 99242421Syokotakbdc_get_device_mask(KBDC p) 99342421Syokota{ 99442421Syokota return kbdcp(p)->command_mask; 99542421Syokota} 99642421Syokota 99742421Syokotavoid 99842421Syokotakbdc_set_device_mask(KBDC p, int mask) 99942421Syokota{ 100042421Syokota kbdcp(p)->command_mask = 100142421Syokota mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS); 100242421Syokota} 100342421Syokota 100442421Syokotaint 100542421Syokotaget_controller_command_byte(KBDC p) 100642421Syokota{ 100742421Syokota if (kbdcp(p)->command_byte != -1) 100842421Syokota return kbdcp(p)->command_byte; 100942421Syokota if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE)) 101042421Syokota return -1; 101142421Syokota emptyq(&kbdcp(p)->kbd); 101242421Syokota kbdcp(p)->command_byte = read_controller_data(p); 101342421Syokota return kbdcp(p)->command_byte; 101442421Syokota} 101542421Syokota 101642421Syokotaint 101742421Syokotaset_controller_command_byte(KBDC p, int mask, int command) 101842421Syokota{ 101942421Syokota if (get_controller_command_byte(p) == -1) 102042421Syokota return FALSE; 102142421Syokota 102242421Syokota command = (kbdcp(p)->command_byte & ~mask) | (command & mask); 102342421Syokota if (command & KBD_DISABLE_KBD_PORT) { 102442421Syokota if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT)) 102542421Syokota return FALSE; 102642421Syokota } 102742421Syokota if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE)) 102842421Syokota return FALSE; 102942421Syokota if (!write_controller_data(p, command)) 103042421Syokota return FALSE; 103142421Syokota kbdcp(p)->command_byte = command; 103242421Syokota 103342421Syokota if (verbose) 103442421Syokota log(LOG_DEBUG, "kbdc: new command byte:%04x (set_controller...)\n", 103542421Syokota command); 103642421Syokota 103742421Syokota return TRUE; 103842421Syokota} 1039