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