atkbdc.c revision 158041
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 158041 2006-04-26 06:05:16Z sobomax $"); 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.h> 4458271Syokota#include <machine/resource.h> 4558271Syokota#include <sys/rman.h> 4642421Syokota 47147271Smarius#include <dev/atkbdc/atkbdcreg.h> 4842421Syokota 49147271Smarius#ifdef __sparc64__ 50147271Smarius#include <dev/ofw/openfirm.h> 51147271Smarius#include <machine/bus_private.h> 52147271Smarius#include <machine/ofw_machdep.h> 53147271Smarius#else 5442421Syokota#include <isa/isareg.h> 55147271Smarius#endif 5642421Syokota 5742421Syokota/* constants */ 5842421Syokota 59102149Speter#define MAXKBDC 1 /* XXX */ 6042421Syokota 6142421Syokota/* macros */ 6242421Syokota 6342421Syokota#ifndef MAX 6442421Syokota#define MAX(x, y) ((x) > (y) ? (x) : (y)) 6542421Syokota#endif 6642421Syokota 6742421Syokota#define kbdcp(p) ((atkbdc_softc_t *)(p)) 6842421Syokota#define nextq(i) (((i) + 1) % KBDQ_BUFSIZE) 6942421Syokota#define availq(q) ((q)->head != (q)->tail) 7042421Syokota#if KBDIO_DEBUG >= 2 7142421Syokota#define emptyq(q) ((q)->tail = (q)->head = (q)->qcount = 0) 7242421Syokota#else 7342421Syokota#define emptyq(q) ((q)->tail = (q)->head = 0) 7442421Syokota#endif 7542421Syokota 7658271Syokota#define read_data(k) (bus_space_read_1((k)->iot, (k)->ioh0, 0)) 7758271Syokota#define read_status(k) (bus_space_read_1((k)->iot, (k)->ioh1, 0)) 7858271Syokota#define write_data(k, d) \ 7958271Syokota (bus_space_write_1((k)->iot, (k)->ioh0, 0, (d))) 8058271Syokota#define write_command(k, d) \ 8158271Syokota (bus_space_write_1((k)->iot, (k)->ioh1, 0, (d))) 8258271Syokota 8342421Syokota/* local variables */ 8442421Syokota 8542421Syokota/* 8642421Syokota * We always need at least one copy of the kbdc_softc struct for the 8742421Syokota * low-level console. As the low-level console accesses the keyboard 8842421Syokota * controller before kbdc, and all other devices, is probed, we 8942421Syokota * statically allocate one entry. XXX 9042421Syokota */ 9142421Syokotastatic atkbdc_softc_t default_kbdc; 9242421Syokotastatic atkbdc_softc_t *atkbdc_softc[MAXKBDC] = { &default_kbdc }; 9342421Syokota 9442421Syokotastatic int verbose = KBDIO_DEBUG; 9542421Syokota 96147271Smarius#ifdef __sparc64__ 97147271Smariusstatic struct bus_space_tag atkbdc_bst_store[MAXKBDC]; 98147271Smarius#endif 99147271Smarius 10042421Syokota/* function prototypes */ 10142421Syokota 10258271Syokotastatic int atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, 10358271Syokota bus_space_handle_t h0, bus_space_handle_t h1); 10442421Syokotastatic int addq(kqueue *q, int c); 10542421Syokotastatic int removeq(kqueue *q); 10642421Syokotastatic int wait_while_controller_busy(atkbdc_softc_t *kbdc); 10742421Syokotastatic int wait_for_data(atkbdc_softc_t *kbdc); 10842421Syokotastatic int wait_for_kbd_data(atkbdc_softc_t *kbdc); 10942421Syokotastatic int wait_for_kbd_ack(atkbdc_softc_t *kbdc); 11042421Syokotastatic int wait_for_aux_data(atkbdc_softc_t *kbdc); 11142421Syokotastatic int wait_for_aux_ack(atkbdc_softc_t *kbdc); 11242421Syokota 11342421Syokotaatkbdc_softc_t 11442421Syokota*atkbdc_get_softc(int unit) 11542421Syokota{ 11642421Syokota atkbdc_softc_t *sc; 11742421Syokota 11842421Syokota if (unit >= sizeof(atkbdc_softc)/sizeof(atkbdc_softc[0])) 11942421Syokota return NULL; 12042421Syokota sc = atkbdc_softc[unit]; 12142421Syokota if (sc == NULL) { 12242421Syokota sc = atkbdc_softc[unit] 12369781Sdwmalone = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO); 12442421Syokota if (sc == NULL) 12542421Syokota return NULL; 12642421Syokota } 12742421Syokota return sc; 12842421Syokota} 12942421Syokota 13042421Syokotaint 13158271Syokotaatkbdc_probe_unit(int unit, struct resource *port0, struct resource *port1) 13242421Syokota{ 13358271Syokota if (rman_get_start(port0) <= 0) 13447296Syokota return ENXIO; 13558271Syokota if (rman_get_start(port1) <= 0) 13658271Syokota return ENXIO; 13747296Syokota return 0; 13847296Syokota} 13947296Syokota 14047296Syokotaint 14158271Syokotaatkbdc_attach_unit(int unit, atkbdc_softc_t *sc, struct resource *port0, 14258271Syokota struct resource *port1) 14347296Syokota{ 14458271Syokota return atkbdc_setup(sc, rman_get_bustag(port0), 14558271Syokota rman_get_bushandle(port0), 14658271Syokota rman_get_bushandle(port1)); 14742421Syokota} 14842421Syokota 14942421Syokota/* the backdoor to the keyboard controller! XXX */ 15042421Syokotaint 15142421Syokotaatkbdc_configure(void) 15242421Syokota{ 15358271Syokota bus_space_tag_t tag; 15458271Syokota bus_space_handle_t h0; 15558271Syokota bus_space_handle_t h1; 156158041Ssobomax#if defined(__i386__) 157158041Ssobomax volatile int i; 158158041Ssobomax register_t flags; 159158041Ssobomax#endif 160147271Smarius#ifdef __sparc64__ 161147271Smarius char name[32]; 162147271Smarius phandle_t chosen, node; 163147271Smarius ihandle_t stdin; 164147271Smarius bus_addr_t port0; 165147271Smarius bus_addr_t port1; 166147271Smarius int space; 167147271Smarius#else 16858271Syokota int port0; 16958271Syokota int port1; 17058271Syokota#endif 17158271Syokota 17258271Syokota /* XXX: tag should be passed from the caller */ 173114930Speter#if defined(__i386__) 17458271Syokota tag = I386_BUS_SPACE_IO; 175114930Speter#elif defined(__amd64__) 176114930Speter tag = AMD64_BUS_SPACE_IO; 17758271Syokota#elif defined(__alpha__) 17865176Sdfr tag = busspace_isa_io; 17992661Speter#elif defined(__ia64__) 18092661Speter tag = IA64_BUS_SPACE_IO; 181147271Smarius#elif defined(__sparc64__) 182147271Smarius tag = &atkbdc_bst_store[0]; 18392661Speter#else 18492661Speter#error "define tag!" 18558271Syokota#endif 18658271Syokota 187147271Smarius#ifdef __sparc64__ 188147271Smarius if ((chosen = OF_finddevice("/chosen")) == -1) 189147271Smarius return 0; 190147271Smarius if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) 191147271Smarius return 0; 192147271Smarius if ((node = OF_instance_to_package(stdin)) == -1) 193147271Smarius return 0; 194147271Smarius if (OF_getprop(node, "name", name, sizeof(name)) == -1) 195147271Smarius return 0; 196147271Smarius name[sizeof(name) - 1] = '\0'; 197147271Smarius if (strcmp(name, "kb_ps2") != 0) 198147271Smarius return 0; 199147271Smarius /* 200147271Smarius * The stdin handle points to an instance of a PS/2 keyboard 201147271Smarius * package but we want the 8042 controller, which is the parent 202147271Smarius * of that keyboard node. 203147271Smarius */ 204147271Smarius if ((node = OF_parent(node)) == 0) 205147271Smarius return 0; 206147271Smarius if (OF_decode_addr(node, 0, &space, &port0) != 0) 207147271Smarius return 0; 208147271Smarius h0 = sparc64_fake_bustag(space, port0, tag); 209147271Smarius bus_space_subregion(tag, h0, KBD_DATA_PORT, 1, &h0); 210147271Smarius if (OF_decode_addr(node, 1, &space, &port1) != 0) 211147271Smarius return 0; 212147271Smarius h1 = sparc64_fake_bustag(space, port1, tag); 213147271Smarius bus_space_subregion(tag, h1, KBD_STATUS_PORT, 1, &h1); 214147271Smarius#else 215147271Smarius port0 = IO_KBD; 216147271Smarius resource_int_value("atkbdc", 0, "port", &port0); 217147271Smarius port1 = IO_KBD + KBD_STATUS_PORT; 218153072Sru#ifdef notyet 21958271Syokota bus_space_map(tag, port0, IO_KBDSIZE, 0, &h0); 22058271Syokota bus_space_map(tag, port1, IO_KBDSIZE, 0, &h1); 22158271Syokota#else 22258271Syokota h0 = (bus_space_handle_t)port0; 22358271Syokota h1 = (bus_space_handle_t)port1; 22458271Syokota#endif 225147271Smarius#endif 226158041Ssobomax 227158041Ssobomax#if defined(__i386__) 228158041Ssobomax /* 229158041Ssobomax * Check if we really have AT keyboard controller. Poll status 230158041Ssobomax * register until we get "all clear" indication. If no such 231158041Ssobomax * indication comes, it probably means that there is no AT 232158041Ssobomax * keyboard controller present. Give up in such case. Check relies 233158041Ssobomax * on the fact that reading from non-existing in/out port returns 234158041Ssobomax * 0xff on i386. May or may not be true on other platforms. 235158041Ssobomax */ 236158041Ssobomax flags = intr_disable(); 237158041Ssobomax for (i = 0; i != 65535; i++) { 238158041Ssobomax if ((bus_space_read_1(tag, h1, 0) & 0x2) == 0) 239158041Ssobomax break; 240158041Ssobomax } 241158041Ssobomax intr_restore(flags); 242158041Ssobomax if (i == 65535) 243158041Ssobomax return ENXIO; 244158041Ssobomax#endif 245158041Ssobomax 24658271Syokota return atkbdc_setup(atkbdc_softc[0], tag, h0, h1); 24742421Syokota} 24842421Syokota 24942421Syokotastatic int 25058271Syokotaatkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0, 25158271Syokota bus_space_handle_t h1) 25242421Syokota{ 25358271Syokota if (sc->ioh0 == 0) { /* XXX */ 25442421Syokota sc->command_byte = -1; 25542421Syokota sc->command_mask = 0; 25642421Syokota sc->lock = FALSE; 25742421Syokota sc->kbd.head = sc->kbd.tail = 0; 25842421Syokota sc->aux.head = sc->aux.tail = 0; 25942421Syokota#if KBDIO_DEBUG >= 2 26042421Syokota sc->kbd.call_count = 0; 26142421Syokota sc->kbd.qcount = sc->kbd.max_qcount = 0; 26242421Syokota sc->aux.call_count = 0; 26342421Syokota sc->aux.qcount = sc->aux.max_qcount = 0; 26442421Syokota#endif 26542421Syokota } 26658271Syokota sc->iot = tag; 26758271Syokota sc->ioh0 = h0; 26858271Syokota sc->ioh1 = h1; 26942421Syokota return 0; 27042421Syokota} 27142421Syokota 27258271Syokota/* open a keyboard controller */ 27342421SyokotaKBDC 27458271Syokotaatkbdc_open(int unit) 27542421Syokota{ 27658271Syokota if (unit <= 0) 27758271Syokota unit = 0; 27858271Syokota if (unit >= MAXKBDC) 27958271Syokota return NULL; 28058271Syokota if ((atkbdc_softc[unit]->port0 != NULL) 28158271Syokota || (atkbdc_softc[unit]->ioh0 != 0)) /* XXX */ 28258271Syokota return (KBDC)atkbdc_softc[unit]; 28342421Syokota return NULL; 28442421Syokota} 28542421Syokota 28642421Syokota/* 28742421Syokota * I/O access arbitration in `kbdio' 28842421Syokota * 28942421Syokota * The `kbdio' module uses a simplistic convention to arbitrate 29042421Syokota * I/O access to the controller/keyboard/mouse. The convention requires 29142421Syokota * close cooperation of the calling device driver. 29242421Syokota * 29393279Smurray * The device drivers which utilize the `kbdio' module are assumed to 29442421Syokota * have the following set of routines. 29542421Syokota * a. An interrupt handler (the bottom half of the driver). 29693279Smurray * b. Timeout routines which may briefly poll the keyboard controller. 29742421Syokota * c. Routines outside interrupt context (the top half of the driver). 29842421Syokota * They should follow the rules below: 29942421Syokota * 1. The interrupt handler may assume that it always has full access 30042421Syokota * to the controller/keyboard/mouse. 30142421Syokota * 2. The other routines must issue `spltty()' if they wish to 30242421Syokota * prevent the interrupt handler from accessing 30342421Syokota * the controller/keyboard/mouse. 30442421Syokota * 3. The timeout routines and the top half routines of the device driver 30542421Syokota * arbitrate I/O access by observing the lock flag in `kbdio'. 30642421Syokota * The flag is manipulated via `kbdc_lock()'; when one wants to 30742421Syokota * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if 30842421Syokota * the call returns with TRUE. Otherwise the caller must back off. 30942421Syokota * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion 31042421Syokota * is finished. This mechanism does not prevent the interrupt 31142421Syokota * handler from being invoked at any time and carrying out I/O. 31242421Syokota * Therefore, `spltty()' must be strategically placed in the device 31342421Syokota * driver code. Also note that the timeout routine may interrupt 31442421Syokota * `kbdc_lock()' called by the top half of the driver, but this 31593279Smurray * interruption is OK so long as the timeout routine observes 31693279Smurray * rule 4 below. 31742421Syokota * 4. The interrupt and timeout routines should not extend I/O operation 31893279Smurray * across more than one interrupt or timeout; they must complete any 31993279Smurray * necessary I/O operation within one invocation of the routine. 32093279Smurray * This means that if the timeout routine acquires the lock flag, 32142421Syokota * it must reset the flag to FALSE before it returns. 32242421Syokota */ 32342421Syokota 32442421Syokota/* set/reset polling lock */ 32542421Syokotaint 32642421Syokotakbdc_lock(KBDC p, int lock) 32742421Syokota{ 32842421Syokota int prevlock; 32942421Syokota 33042421Syokota prevlock = kbdcp(p)->lock; 33142421Syokota kbdcp(p)->lock = lock; 33242421Syokota 33342421Syokota return (prevlock != lock); 33442421Syokota} 33542421Syokota 33642421Syokota/* check if any data is waiting to be processed */ 33742421Syokotaint 33842421Syokotakbdc_data_ready(KBDC p) 33942421Syokota{ 34042421Syokota return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux) 34158271Syokota || (read_status(kbdcp(p)) & KBDS_ANY_BUFFER_FULL)); 34242421Syokota} 34342421Syokota 34442421Syokota/* queuing functions */ 34542421Syokota 34642421Syokotastatic int 34742421Syokotaaddq(kqueue *q, int c) 34842421Syokota{ 34942421Syokota if (nextq(q->tail) != q->head) { 35042421Syokota q->q[q->tail] = c; 35142421Syokota q->tail = nextq(q->tail); 35242421Syokota#if KBDIO_DEBUG >= 2 35342421Syokota ++q->call_count; 35442421Syokota ++q->qcount; 35542421Syokota if (q->qcount > q->max_qcount) 35642421Syokota q->max_qcount = q->qcount; 35742421Syokota#endif 35842421Syokota return TRUE; 35942421Syokota } 36042421Syokota return FALSE; 36142421Syokota} 36242421Syokota 36342421Syokotastatic int 36442421Syokotaremoveq(kqueue *q) 36542421Syokota{ 36642421Syokota int c; 36742421Syokota 36842421Syokota if (q->tail != q->head) { 36942421Syokota c = q->q[q->head]; 37042421Syokota q->head = nextq(q->head); 37142421Syokota#if KBDIO_DEBUG >= 2 37242421Syokota --q->qcount; 37342421Syokota#endif 37442421Syokota return c; 37542421Syokota } 37642421Syokota return -1; 37742421Syokota} 37842421Syokota 37942421Syokota/* 38042421Syokota * device I/O routines 38142421Syokota */ 38242421Syokotastatic int 38342421Syokotawait_while_controller_busy(struct atkbdc_softc *kbdc) 38442421Syokota{ 38542421Syokota /* CPU will stay inside the loop for 100msec at most */ 38642421Syokota int retry = 5000; 38742421Syokota int f; 38842421Syokota 38958271Syokota while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) { 39042421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 39142421Syokota DELAY(KBDD_DELAYTIME); 39258271Syokota addq(&kbdc->kbd, read_data(kbdc)); 39342421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 39442421Syokota DELAY(KBDD_DELAYTIME); 39558271Syokota addq(&kbdc->aux, read_data(kbdc)); 39642421Syokota } 39742421Syokota DELAY(KBDC_DELAYTIME); 39842421Syokota if (--retry < 0) 39942421Syokota return FALSE; 40042421Syokota } 40142421Syokota return TRUE; 40242421Syokota} 40342421Syokota 40442421Syokota/* 40542421Syokota * wait for any data; whether it's from the controller, 40642421Syokota * the keyboard, or the aux device. 40742421Syokota */ 40842421Syokotastatic int 40942421Syokotawait_for_data(struct atkbdc_softc *kbdc) 41042421Syokota{ 41142421Syokota /* CPU will stay inside the loop for 200msec at most */ 41242421Syokota int retry = 10000; 41342421Syokota int f; 41442421Syokota 41558271Syokota while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) { 41642421Syokota DELAY(KBDC_DELAYTIME); 41742421Syokota if (--retry < 0) 41842421Syokota return 0; 41942421Syokota } 42042421Syokota DELAY(KBDD_DELAYTIME); 42142421Syokota return f; 42242421Syokota} 42342421Syokota 42442421Syokota/* wait for data from the keyboard */ 42542421Syokotastatic int 42642421Syokotawait_for_kbd_data(struct atkbdc_softc *kbdc) 42742421Syokota{ 42842421Syokota /* CPU will stay inside the loop for 200msec at most */ 42942421Syokota int retry = 10000; 43042421Syokota int f; 43142421Syokota 43258271Syokota while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) 43342421Syokota != KBDS_KBD_BUFFER_FULL) { 43442421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 43542421Syokota DELAY(KBDD_DELAYTIME); 43658271Syokota addq(&kbdc->aux, read_data(kbdc)); 43742421Syokota } 43842421Syokota DELAY(KBDC_DELAYTIME); 43942421Syokota if (--retry < 0) 44042421Syokota return 0; 44142421Syokota } 44242421Syokota DELAY(KBDD_DELAYTIME); 44342421Syokota return f; 44442421Syokota} 44542421Syokota 44642421Syokota/* 44742421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard. 44842421Syokota * queue anything else. 44942421Syokota */ 45042421Syokotastatic int 45142421Syokotawait_for_kbd_ack(struct atkbdc_softc *kbdc) 45242421Syokota{ 45342421Syokota /* CPU will stay inside the loop for 200msec at most */ 45442421Syokota int retry = 10000; 45542421Syokota int f; 45642421Syokota int b; 45742421Syokota 45842421Syokota while (retry-- > 0) { 45958271Syokota if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { 46042421Syokota DELAY(KBDD_DELAYTIME); 46158271Syokota b = read_data(kbdc); 46242421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 46342421Syokota if ((b == KBD_ACK) || (b == KBD_RESEND) 46442421Syokota || (b == KBD_RESET_FAIL)) 46542421Syokota return b; 46642421Syokota addq(&kbdc->kbd, b); 46742421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 46842421Syokota addq(&kbdc->aux, b); 46942421Syokota } 47042421Syokota } 47142421Syokota DELAY(KBDC_DELAYTIME); 47242421Syokota } 47342421Syokota return -1; 47442421Syokota} 47542421Syokota 47642421Syokota/* wait for data from the aux device */ 47742421Syokotastatic int 47842421Syokotawait_for_aux_data(struct atkbdc_softc *kbdc) 47942421Syokota{ 48042421Syokota /* CPU will stay inside the loop for 200msec at most */ 48142421Syokota int retry = 10000; 48242421Syokota int f; 48342421Syokota 48458271Syokota while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) 48542421Syokota != KBDS_AUX_BUFFER_FULL) { 48642421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 48742421Syokota DELAY(KBDD_DELAYTIME); 48858271Syokota addq(&kbdc->kbd, read_data(kbdc)); 48942421Syokota } 49042421Syokota DELAY(KBDC_DELAYTIME); 49142421Syokota if (--retry < 0) 49242421Syokota return 0; 49342421Syokota } 49442421Syokota DELAY(KBDD_DELAYTIME); 49542421Syokota return f; 49642421Syokota} 49742421Syokota 49842421Syokota/* 49942421Syokota * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device. 50042421Syokota * queue anything else. 50142421Syokota */ 50242421Syokotastatic int 50342421Syokotawait_for_aux_ack(struct atkbdc_softc *kbdc) 50442421Syokota{ 50542421Syokota /* CPU will stay inside the loop for 200msec at most */ 50642421Syokota int retry = 10000; 50742421Syokota int f; 50842421Syokota int b; 50942421Syokota 51042421Syokota while (retry-- > 0) { 51158271Syokota if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { 51242421Syokota DELAY(KBDD_DELAYTIME); 51358271Syokota b = read_data(kbdc); 51442421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 51542421Syokota if ((b == PSM_ACK) || (b == PSM_RESEND) 51642421Syokota || (b == PSM_RESET_FAIL)) 51742421Syokota return b; 51842421Syokota addq(&kbdc->aux, b); 51942421Syokota } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 52042421Syokota addq(&kbdc->kbd, b); 52142421Syokota } 52242421Syokota } 52342421Syokota DELAY(KBDC_DELAYTIME); 52442421Syokota } 52542421Syokota return -1; 52642421Syokota} 52742421Syokota 52842421Syokota/* write a one byte command to the controller */ 52942421Syokotaint 53042421Syokotawrite_controller_command(KBDC p, int c) 53142421Syokota{ 53242421Syokota if (!wait_while_controller_busy(kbdcp(p))) 53342421Syokota return FALSE; 53458271Syokota write_command(kbdcp(p), c); 53542421Syokota return TRUE; 53642421Syokota} 53742421Syokota 53842421Syokota/* write a one byte data to the controller */ 53942421Syokotaint 54042421Syokotawrite_controller_data(KBDC p, int c) 54142421Syokota{ 54242421Syokota if (!wait_while_controller_busy(kbdcp(p))) 54342421Syokota return FALSE; 54458271Syokota write_data(kbdcp(p), c); 54542421Syokota return TRUE; 54642421Syokota} 54742421Syokota 54842421Syokota/* write a one byte keyboard command */ 54942421Syokotaint 55042421Syokotawrite_kbd_command(KBDC p, int c) 55142421Syokota{ 55242421Syokota if (!wait_while_controller_busy(kbdcp(p))) 55342421Syokota return FALSE; 55458271Syokota write_data(kbdcp(p), c); 55542421Syokota return TRUE; 55642421Syokota} 55742421Syokota 55842421Syokota/* write a one byte auxiliary device command */ 55942421Syokotaint 56042421Syokotawrite_aux_command(KBDC p, int c) 56142421Syokota{ 56242421Syokota if (!write_controller_command(p, KBDC_WRITE_TO_AUX)) 56342421Syokota return FALSE; 56442421Syokota return write_controller_data(p, c); 56542421Syokota} 56642421Syokota 56742421Syokota/* send a command to the keyboard and wait for ACK */ 56842421Syokotaint 56942421Syokotasend_kbd_command(KBDC p, int c) 57042421Syokota{ 57142421Syokota int retry = KBD_MAXRETRY; 57242421Syokota int res = -1; 57342421Syokota 57442421Syokota while (retry-- > 0) { 57542421Syokota if (!write_kbd_command(p, c)) 57642421Syokota continue; 57742421Syokota res = wait_for_kbd_ack(kbdcp(p)); 57842421Syokota if (res == KBD_ACK) 57942421Syokota break; 58042421Syokota } 58142421Syokota return res; 58242421Syokota} 58342421Syokota 58442421Syokota/* send a command to the auxiliary device and wait for ACK */ 58542421Syokotaint 58642421Syokotasend_aux_command(KBDC p, int c) 58742421Syokota{ 58842421Syokota int retry = KBD_MAXRETRY; 58942421Syokota int res = -1; 59042421Syokota 59142421Syokota while (retry-- > 0) { 59242421Syokota if (!write_aux_command(p, c)) 59342421Syokota continue; 59442421Syokota /* 59542421Syokota * FIXME: XXX 59642421Syokota * The aux device may have already sent one or two bytes of 59742421Syokota * status data, when a command is received. It will immediately 59842421Syokota * stop data transmission, thus, leaving an incomplete data 59942421Syokota * packet in our buffer. We have to discard any unprocessed 60042421Syokota * data in order to remove such packets. Well, we may remove 60142421Syokota * unprocessed, but necessary data byte as well... 60242421Syokota */ 60342421Syokota emptyq(&kbdcp(p)->aux); 60442421Syokota res = wait_for_aux_ack(kbdcp(p)); 60542421Syokota if (res == PSM_ACK) 60642421Syokota break; 60742421Syokota } 60842421Syokota return res; 60942421Syokota} 61042421Syokota 61142421Syokota/* send a command and a data to the keyboard, wait for ACKs */ 61242421Syokotaint 61342421Syokotasend_kbd_command_and_data(KBDC p, int c, int d) 61442421Syokota{ 61542421Syokota int retry; 61642421Syokota int res = -1; 61742421Syokota 61842421Syokota for (retry = KBD_MAXRETRY; retry > 0; --retry) { 61942421Syokota if (!write_kbd_command(p, c)) 62042421Syokota continue; 62142421Syokota res = wait_for_kbd_ack(kbdcp(p)); 62242421Syokota if (res == KBD_ACK) 62342421Syokota break; 62442421Syokota else if (res != KBD_RESEND) 62542421Syokota return res; 62642421Syokota } 62742421Syokota if (retry <= 0) 62842421Syokota return res; 62942421Syokota 63042421Syokota for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { 63142421Syokota if (!write_kbd_command(p, d)) 63242421Syokota continue; 63342421Syokota res = wait_for_kbd_ack(kbdcp(p)); 63442421Syokota if (res != KBD_RESEND) 63542421Syokota break; 63642421Syokota } 63742421Syokota return res; 63842421Syokota} 63942421Syokota 64042421Syokota/* send a command and a data to the auxiliary device, wait for ACKs */ 64142421Syokotaint 64242421Syokotasend_aux_command_and_data(KBDC p, int c, int d) 64342421Syokota{ 64442421Syokota int retry; 64542421Syokota int res = -1; 64642421Syokota 64742421Syokota for (retry = KBD_MAXRETRY; retry > 0; --retry) { 64842421Syokota if (!write_aux_command(p, c)) 64942421Syokota continue; 65042421Syokota emptyq(&kbdcp(p)->aux); 65142421Syokota res = wait_for_aux_ack(kbdcp(p)); 65242421Syokota if (res == PSM_ACK) 65342421Syokota break; 65442421Syokota else if (res != PSM_RESEND) 65542421Syokota return res; 65642421Syokota } 65742421Syokota if (retry <= 0) 65842421Syokota return res; 65942421Syokota 66042421Syokota for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { 66142421Syokota if (!write_aux_command(p, d)) 66242421Syokota continue; 66342421Syokota res = wait_for_aux_ack(kbdcp(p)); 66442421Syokota if (res != PSM_RESEND) 66542421Syokota break; 66642421Syokota } 66742421Syokota return res; 66842421Syokota} 66942421Syokota 67042421Syokota/* 67142421Syokota * read one byte from any source; whether from the controller, 67242421Syokota * the keyboard, or the aux device 67342421Syokota */ 67442421Syokotaint 67542421Syokotaread_controller_data(KBDC p) 67642421Syokota{ 67742421Syokota if (availq(&kbdcp(p)->kbd)) 67842421Syokota return removeq(&kbdcp(p)->kbd); 67942421Syokota if (availq(&kbdcp(p)->aux)) 68042421Syokota return removeq(&kbdcp(p)->aux); 68142421Syokota if (!wait_for_data(kbdcp(p))) 68242421Syokota return -1; /* timeout */ 68358271Syokota return read_data(kbdcp(p)); 68442421Syokota} 68542421Syokota 68642421Syokota#if KBDIO_DEBUG >= 2 68742421Syokotastatic int call = 0; 68842421Syokota#endif 68942421Syokota 69042421Syokota/* read one byte from the keyboard */ 69142421Syokotaint 69242421Syokotaread_kbd_data(KBDC p) 69342421Syokota{ 69442421Syokota#if KBDIO_DEBUG >= 2 69542421Syokota if (++call > 2000) { 69642421Syokota call = 0; 69742421Syokota log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, " 69842421Syokota "aux q: %d calls, max %d chars\n", 69942421Syokota kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, 70042421Syokota kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); 70142421Syokota } 70242421Syokota#endif 70342421Syokota 70442421Syokota if (availq(&kbdcp(p)->kbd)) 70542421Syokota return removeq(&kbdcp(p)->kbd); 70642421Syokota if (!wait_for_kbd_data(kbdcp(p))) 70742421Syokota return -1; /* timeout */ 70858271Syokota return read_data(kbdcp(p)); 70942421Syokota} 71042421Syokota 71142421Syokota/* read one byte from the keyboard, but return immediately if 71242421Syokota * no data is waiting 71342421Syokota */ 71442421Syokotaint 71542421Syokotaread_kbd_data_no_wait(KBDC p) 71642421Syokota{ 71742421Syokota int f; 71842421Syokota 71942421Syokota#if KBDIO_DEBUG >= 2 72042421Syokota if (++call > 2000) { 72142421Syokota call = 0; 72242421Syokota log(LOG_DEBUG, "kbdc: kbd q: %d calls, max %d chars, " 72342421Syokota "aux q: %d calls, max %d chars\n", 72442421Syokota kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, 72542421Syokota kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); 72642421Syokota } 72742421Syokota#endif 72842421Syokota 72942421Syokota if (availq(&kbdcp(p)->kbd)) 73042421Syokota return removeq(&kbdcp(p)->kbd); 73158271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 73242421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 73342421Syokota DELAY(KBDD_DELAYTIME); 73458271Syokota addq(&kbdcp(p)->aux, read_data(kbdcp(p))); 73558271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 73642421Syokota } 73742421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 73842421Syokota DELAY(KBDD_DELAYTIME); 73958271Syokota return read_data(kbdcp(p)); 74042421Syokota } 74142421Syokota return -1; /* no data */ 74242421Syokota} 74342421Syokota 74442421Syokota/* read one byte from the aux device */ 74542421Syokotaint 74642421Syokotaread_aux_data(KBDC p) 74742421Syokota{ 74842421Syokota if (availq(&kbdcp(p)->aux)) 74942421Syokota return removeq(&kbdcp(p)->aux); 75042421Syokota if (!wait_for_aux_data(kbdcp(p))) 75142421Syokota return -1; /* timeout */ 75258271Syokota return read_data(kbdcp(p)); 75342421Syokota} 75442421Syokota 75542421Syokota/* read one byte from the aux device, but return immediately if 75642421Syokota * no data is waiting 75742421Syokota */ 75842421Syokotaint 75942421Syokotaread_aux_data_no_wait(KBDC p) 76042421Syokota{ 76142421Syokota int f; 76242421Syokota 76342421Syokota if (availq(&kbdcp(p)->aux)) 76442421Syokota return removeq(&kbdcp(p)->aux); 76558271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 76642421Syokota if (f == KBDS_KBD_BUFFER_FULL) { 76742421Syokota DELAY(KBDD_DELAYTIME); 76858271Syokota addq(&kbdcp(p)->kbd, read_data(kbdcp(p))); 76958271Syokota f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; 77042421Syokota } 77142421Syokota if (f == KBDS_AUX_BUFFER_FULL) { 77242421Syokota DELAY(KBDD_DELAYTIME); 77358271Syokota return read_data(kbdcp(p)); 77442421Syokota } 77542421Syokota return -1; /* no data */ 77642421Syokota} 77742421Syokota 77842421Syokota/* discard data from the keyboard */ 77942421Syokotavoid 78042421Syokotaempty_kbd_buffer(KBDC p, int wait) 78142421Syokota{ 78242421Syokota int t; 78342421Syokota int b; 78442421Syokota int f; 78542421Syokota#if KBDIO_DEBUG >= 2 78642421Syokota int c1 = 0; 78742421Syokota int c2 = 0; 78842421Syokota#endif 78942421Syokota int delta = 2; 79042421Syokota 79142421Syokota for (t = wait; t > 0; ) { 79258271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 79342421Syokota DELAY(KBDD_DELAYTIME); 79458271Syokota b = read_data(kbdcp(p)); 79542421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { 79642421Syokota addq(&kbdcp(p)->aux, b); 79742421Syokota#if KBDIO_DEBUG >= 2 79842421Syokota ++c2; 79942421Syokota } else { 80042421Syokota ++c1; 80142421Syokota#endif 80242421Syokota } 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_kbd_buffer)\n", c1, c2); 81242421Syokota#endif 81342421Syokota 81442421Syokota emptyq(&kbdcp(p)->kbd); 81542421Syokota} 81642421Syokota 81742421Syokota/* discard data from the aux device */ 81842421Syokotavoid 81942421Syokotaempty_aux_buffer(KBDC p, int wait) 82042421Syokota{ 82142421Syokota int t; 82242421Syokota int b; 82342421Syokota int f; 82442421Syokota#if KBDIO_DEBUG >= 2 82542421Syokota int c1 = 0; 82642421Syokota int c2 = 0; 82742421Syokota#endif 82842421Syokota int delta = 2; 82942421Syokota 83042421Syokota for (t = wait; t > 0; ) { 83158271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 83242421Syokota DELAY(KBDD_DELAYTIME); 83358271Syokota b = read_data(kbdcp(p)); 83442421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { 83542421Syokota addq(&kbdcp(p)->kbd, b); 83642421Syokota#if KBDIO_DEBUG >= 2 83742421Syokota ++c1; 83842421Syokota } else { 83942421Syokota ++c2; 84042421Syokota#endif 84142421Syokota } 84242421Syokota t = wait; 84342421Syokota } else { 84442421Syokota t -= delta; 84542421Syokota } 84642421Syokota DELAY(delta*1000); 84742421Syokota } 84842421Syokota#if KBDIO_DEBUG >= 2 84942421Syokota if ((c1 > 0) || (c2 > 0)) 85042421Syokota log(LOG_DEBUG, "kbdc: %d:%d char read (empty_aux_buffer)\n", c1, c2); 85142421Syokota#endif 85242421Syokota 85342421Syokota emptyq(&kbdcp(p)->aux); 85442421Syokota} 85542421Syokota 85642421Syokota/* discard any data from the keyboard or the aux device */ 85742421Syokotavoid 85842421Syokotaempty_both_buffers(KBDC p, int wait) 85942421Syokota{ 86042421Syokota int t; 86142421Syokota int f; 86242421Syokota#if KBDIO_DEBUG >= 2 86342421Syokota int c1 = 0; 86442421Syokota int c2 = 0; 86542421Syokota#endif 86642421Syokota int delta = 2; 86742421Syokota 86842421Syokota for (t = wait; t > 0; ) { 86958271Syokota if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { 87042421Syokota DELAY(KBDD_DELAYTIME); 87158271Syokota (void)read_data(kbdcp(p)); 87242421Syokota#if KBDIO_DEBUG >= 2 87342421Syokota if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) 87442421Syokota ++c1; 87542421Syokota else 87642421Syokota ++c2; 87742421Syokota#endif 87842421Syokota t = wait; 87942421Syokota } else { 88042421Syokota t -= delta; 88142421Syokota } 88242421Syokota DELAY(delta*1000); 88342421Syokota } 88442421Syokota#if KBDIO_DEBUG >= 2 88542421Syokota if ((c1 > 0) || (c2 > 0)) 88642421Syokota log(LOG_DEBUG, "kbdc: %d:%d char read (empty_both_buffers)\n", c1, c2); 88742421Syokota#endif 88842421Syokota 88942421Syokota emptyq(&kbdcp(p)->kbd); 89042421Syokota emptyq(&kbdcp(p)->aux); 89142421Syokota} 89242421Syokota 89342421Syokota/* keyboard and mouse device control */ 89442421Syokota 89542421Syokota/* NOTE: enable the keyboard port but disable the keyboard 89642421Syokota * interrupt before calling "reset_kbd()". 89742421Syokota */ 89842421Syokotaint 89942421Syokotareset_kbd(KBDC p) 90042421Syokota{ 90142421Syokota int retry = KBD_MAXRETRY; 90242421Syokota int again = KBD_MAXWAIT; 90342421Syokota int c = KBD_RESEND; /* keep the compiler happy */ 90442421Syokota 90542421Syokota while (retry-- > 0) { 90642421Syokota empty_both_buffers(p, 10); 90742421Syokota if (!write_kbd_command(p, KBDC_RESET_KBD)) 90842421Syokota continue; 90942421Syokota emptyq(&kbdcp(p)->kbd); 91042421Syokota c = read_controller_data(p); 91142421Syokota if (verbose || bootverbose) 91242421Syokota log(LOG_DEBUG, "kbdc: RESET_KBD return code:%04x\n", c); 91342421Syokota if (c == KBD_ACK) /* keyboard has agreed to reset itself... */ 91442421Syokota break; 91542421Syokota } 91642421Syokota if (retry < 0) 91742421Syokota return FALSE; 91842421Syokota 91942421Syokota while (again-- > 0) { 92042421Syokota /* wait awhile, well, in fact we must wait quite loooooooooooong */ 92142421Syokota DELAY(KBD_RESETDELAY*1000); 92242421Syokota c = read_controller_data(p); /* RESET_DONE/RESET_FAIL */ 92342421Syokota if (c != -1) /* wait again if the controller is not ready */ 92442421Syokota break; 92542421Syokota } 92642421Syokota if (verbose || bootverbose) 92742421Syokota log(LOG_DEBUG, "kbdc: RESET_KBD status:%04x\n", c); 92842421Syokota if (c != KBD_RESET_DONE) 92942421Syokota return FALSE; 93042421Syokota return TRUE; 93142421Syokota} 93242421Syokota 93342421Syokota/* NOTE: enable the aux port but disable the aux interrupt 93442421Syokota * before calling `reset_aux_dev()'. 93542421Syokota */ 93642421Syokotaint 93742421Syokotareset_aux_dev(KBDC p) 93842421Syokota{ 93942421Syokota int retry = KBD_MAXRETRY; 94042421Syokota int again = KBD_MAXWAIT; 94142421Syokota int c = PSM_RESEND; /* keep the compiler happy */ 94242421Syokota 94342421Syokota while (retry-- > 0) { 94442421Syokota empty_both_buffers(p, 10); 94542421Syokota if (!write_aux_command(p, PSMC_RESET_DEV)) 94642421Syokota continue; 94742421Syokota emptyq(&kbdcp(p)->aux); 94842421Syokota /* NOTE: Compaq Armada laptops require extra delay here. XXX */ 94942421Syokota for (again = KBD_MAXWAIT; again > 0; --again) { 95042421Syokota DELAY(KBD_RESETDELAY*1000); 95142421Syokota c = read_aux_data_no_wait(p); 95242421Syokota if (c != -1) 95342421Syokota break; 95442421Syokota } 95542421Syokota if (verbose || bootverbose) 95642421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX return code:%04x\n", c); 95742421Syokota if (c == PSM_ACK) /* aux dev is about to reset... */ 95842421Syokota break; 95942421Syokota } 96042421Syokota if (retry < 0) 96142421Syokota return FALSE; 96242421Syokota 96342421Syokota for (again = KBD_MAXWAIT; again > 0; --again) { 96442421Syokota /* wait awhile, well, quite looooooooooooong */ 96542421Syokota DELAY(KBD_RESETDELAY*1000); 96642421Syokota c = read_aux_data_no_wait(p); /* RESET_DONE/RESET_FAIL */ 96742421Syokota if (c != -1) /* wait again if the controller is not ready */ 96842421Syokota break; 96942421Syokota } 97042421Syokota if (verbose || bootverbose) 97142421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX status:%04x\n", c); 97242421Syokota if (c != PSM_RESET_DONE) /* reset status */ 97342421Syokota return FALSE; 97442421Syokota 97542421Syokota c = read_aux_data(p); /* device ID */ 97642421Syokota if (verbose || bootverbose) 97742421Syokota log(LOG_DEBUG, "kbdc: RESET_AUX ID:%04x\n", c); 97842421Syokota /* NOTE: we could check the device ID now, but leave it later... */ 97942421Syokota return TRUE; 98042421Syokota} 98142421Syokota 98242421Syokota/* controller diagnostics and setup */ 98342421Syokota 98442421Syokotaint 98542421Syokotatest_controller(KBDC p) 98642421Syokota{ 98742421Syokota int retry = KBD_MAXRETRY; 98842421Syokota int again = KBD_MAXWAIT; 98942421Syokota int c = KBD_DIAG_FAIL; 99042421Syokota 99142421Syokota while (retry-- > 0) { 99242421Syokota empty_both_buffers(p, 10); 99342421Syokota if (write_controller_command(p, KBDC_DIAGNOSE)) 99442421Syokota break; 99542421Syokota } 99642421Syokota if (retry < 0) 99742421Syokota return FALSE; 99842421Syokota 99942421Syokota emptyq(&kbdcp(p)->kbd); 100042421Syokota while (again-- > 0) { 100142421Syokota /* wait awhile */ 100242421Syokota DELAY(KBD_RESETDELAY*1000); 100342421Syokota c = read_controller_data(p); /* DIAG_DONE/DIAG_FAIL */ 100442421Syokota if (c != -1) /* wait again if the controller is not ready */ 100542421Syokota break; 100642421Syokota } 100742421Syokota if (verbose || bootverbose) 100842421Syokota log(LOG_DEBUG, "kbdc: DIAGNOSE status:%04x\n", c); 100942421Syokota return (c == KBD_DIAG_DONE); 101042421Syokota} 101142421Syokota 101242421Syokotaint 101342421Syokotatest_kbd_port(KBDC p) 101442421Syokota{ 101542421Syokota int retry = KBD_MAXRETRY; 101642421Syokota int again = KBD_MAXWAIT; 101742421Syokota int c = -1; 101842421Syokota 101942421Syokota while (retry-- > 0) { 102042421Syokota empty_both_buffers(p, 10); 102142421Syokota if (write_controller_command(p, KBDC_TEST_KBD_PORT)) 102242421Syokota break; 102342421Syokota } 102442421Syokota if (retry < 0) 102542421Syokota return FALSE; 102642421Syokota 102742421Syokota emptyq(&kbdcp(p)->kbd); 102842421Syokota while (again-- > 0) { 102942421Syokota c = read_controller_data(p); 103042421Syokota if (c != -1) /* try again if the controller is not ready */ 103142421Syokota break; 103242421Syokota } 103342421Syokota if (verbose || bootverbose) 103442421Syokota log(LOG_DEBUG, "kbdc: TEST_KBD_PORT status:%04x\n", c); 103542421Syokota return c; 103642421Syokota} 103742421Syokota 103842421Syokotaint 103942421Syokotatest_aux_port(KBDC p) 104042421Syokota{ 104142421Syokota int retry = KBD_MAXRETRY; 104242421Syokota int again = KBD_MAXWAIT; 104342421Syokota int c = -1; 104442421Syokota 104542421Syokota while (retry-- > 0) { 104642421Syokota empty_both_buffers(p, 10); 104742421Syokota if (write_controller_command(p, KBDC_TEST_AUX_PORT)) 104842421Syokota break; 104942421Syokota } 105042421Syokota if (retry < 0) 105142421Syokota return FALSE; 105242421Syokota 105342421Syokota emptyq(&kbdcp(p)->kbd); 105442421Syokota while (again-- > 0) { 105542421Syokota c = read_controller_data(p); 105642421Syokota if (c != -1) /* try again if the controller is not ready */ 105742421Syokota break; 105842421Syokota } 105942421Syokota if (verbose || bootverbose) 106042421Syokota log(LOG_DEBUG, "kbdc: TEST_AUX_PORT status:%04x\n", c); 106142421Syokota return c; 106242421Syokota} 106342421Syokota 106442421Syokotaint 106542421Syokotakbdc_get_device_mask(KBDC p) 106642421Syokota{ 106742421Syokota return kbdcp(p)->command_mask; 106842421Syokota} 106942421Syokota 107042421Syokotavoid 107142421Syokotakbdc_set_device_mask(KBDC p, int mask) 107242421Syokota{ 107342421Syokota kbdcp(p)->command_mask = 107442421Syokota mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS); 107542421Syokota} 107642421Syokota 107742421Syokotaint 107842421Syokotaget_controller_command_byte(KBDC p) 107942421Syokota{ 108042421Syokota if (kbdcp(p)->command_byte != -1) 108142421Syokota return kbdcp(p)->command_byte; 108242421Syokota if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE)) 108342421Syokota return -1; 108442421Syokota emptyq(&kbdcp(p)->kbd); 108542421Syokota kbdcp(p)->command_byte = read_controller_data(p); 108642421Syokota return kbdcp(p)->command_byte; 108742421Syokota} 108842421Syokota 108942421Syokotaint 109042421Syokotaset_controller_command_byte(KBDC p, int mask, int command) 109142421Syokota{ 109242421Syokota if (get_controller_command_byte(p) == -1) 109342421Syokota return FALSE; 109442421Syokota 109542421Syokota command = (kbdcp(p)->command_byte & ~mask) | (command & mask); 109642421Syokota if (command & KBD_DISABLE_KBD_PORT) { 109742421Syokota if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT)) 109842421Syokota return FALSE; 109942421Syokota } 110042421Syokota if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE)) 110142421Syokota return FALSE; 110242421Syokota if (!write_controller_data(p, command)) 110342421Syokota return FALSE; 110442421Syokota kbdcp(p)->command_byte = command; 110542421Syokota 110642421Syokota if (verbose) 110742421Syokota log(LOG_DEBUG, "kbdc: new command byte:%04x (set_controller...)\n", 110842421Syokota command); 110942421Syokota 111042421Syokota return TRUE; 111142421Syokota} 1112