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