i8042.c revision fd9cb95cbb2f626355a60efb9d02c5f0a33c10e6
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * CDDL HEADER START
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * The contents of this file are subject to the terms of the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Common Development and Distribution License, Version 1.0 only
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * (the "License"). You may not use this file except in compliance
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * with the License.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * See the License for the specific language governing permissions
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * and limitations under the License.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * When distributing Covered Code, include this CDDL HEADER in each
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * If applicable, add the following below this CDDL HEADER, with the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * fields enclosed by brackets "[]" replaced with your own identifying
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * information: Portions Copyright [yyyy] [name of copyright owner]
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * CDDL HEADER END
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Use is subject to license terms.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome#pragma ident "%Z%%M% %I% %E% SMI"
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Note: For x86, this driver is used to create keyboard/mouse nodes when
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * booting with ACPI enumeration turned off (acpi-enum=off).
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Unfortunately, soft interrupts are implemented poorly. Each additional
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * soft interrupt user impacts the performance of all existing soft interrupt
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * users. This is not the case on SPARC, however.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * The command bytes are different for x86 and for SPARC because on x86,
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * all modern 8042s can properly translate scan code set 2 codes to
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * scan code set 1. On SPARC systems that have 8042s (e.g. Tadpole laptops),
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * setting the "translation" bit in the command byte has no effect.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * This is potentially dangerous if, in the future, new SPARC systems uses 8042s
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * that implement the scan code translation when the translation bit is set.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * On SPARC, kb8042 will attempt to detect which scan code set the keyboard
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * is using. In order for that code to work, the real scan code set must be the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * set that is returned by the keyboard (and not a different set that is
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * translated by the 8042). (e.g. If the translation bit were enabled here,
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * and the keyboard returned scan code set 2 when kb8042 queried it, kb8042
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * would not be able to know with certainty that the scan codes it will receive
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * are set 2 scancodes, or set 1 translations made by the 8042).
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 8042 Command Byte Layout:
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x80: 0 = Reserved, must be zero.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x40: 1 = Translate to XT codes. (0=No translation)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x20: 1 = Disable aux (mouse) port. (0=Enable port)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x10: 1 = Disable main (keyboard) port. (0=Enable port)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x08: 0 = Reserved, must be zero.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x04: 1 = System flag, 1 means passed self-test.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Caution: setting this bit to zero causes some
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * systems (HP Kayak XA) to fail to reboot without
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * a hard reset.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x02: 0 = Disable aux port interrupts. (1=Enable aux port interrupts)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * 0x01: 0 = Disable main port interrupts. (1=Enable main port interrupts)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Child nodes, used to determine which to create at bus_config time
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * Only register at most MAX_INTERRUPTS interrupt handlers,
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * regardless of the number of interrupts in the prom node.
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * This is important, as registering for all interrupts on
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * some systems (e.g. Tadpole laptops) results in a flood
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * of spurious interrupts (for Tadpole, the first 2 interrupts
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * are for the keyboard and mouse, respectively, and the
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * third is for a proprietary device that is also accessed
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * via the same I/O addresses.)
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * One of these for each port - main (keyboard) and aux (mouse).
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome uint_t (*intr_func)(caddr_t arg1, caddr_t arg2);
afc2ba1deb75b323afde536f2dd18bcafdaa308dToomas Soome * wptr is next byte to write
int wptr;
int rptr;
int overruns;
struct i8042 {
int nintrs;
#ifdef __sparc
#ifdef __sparc
(s), strlen(s)) == 0)
void *, dev_info_t **);
ddi_bus_config_op_t, void *);
#ifdef __sparc
NULL,
NULL,
NULL,
(struct cb_ops *)0,
_init(void)
_fini(void)
unsigned int i8042_unclaimed_interrupts = 0;
int which_port, i;
return (DDI_FAILURE);
#if defined(USE_SOFT_INTRS)
return (DDI_FAILURE);
return (DDI_FAILURE);
#ifdef __sparc
#ifndef USE_SOFT_INTRS
sizeof (ddi_iblock_cookie_t));
return (DDI_SUCCESS);
unsigned char stat;
#ifdef __sparc
int interval;
switch (cmd) {
case DDI_RESUME:
#ifdef __sparc
return (DDI_SUCCESS);
case DDI_ATTACH:
return (DDI_FAILURE);
!= DDI_SUCCESS)
goto fail;
goto fail;
#ifdef __sparc
goto fail;
goto fail;
goto fail;
#if defined(USE_SOFT_INTRS)
? which_port : 0]);
for (i = 0; i < MAX_JUNK_ITERATIONS; i++) {
if (i == MAX_JUNK_ITERATIONS)
goto fail;
goto fail;
#ifdef __sparc
if (i8042_polled_mode) {
return (DDI_SUCCESS);
fail:
return (DDI_FAILURE);
switch (cmd) {
case DDI_SUSPEND:
#ifdef __sparc
return (DDI_SUCCESS);
case DDI_DETACH:
return (DDI_FAILURE);
int *iprop;
unsigned int iprop_len;
int rnumber;
case DDI_MT_REGSPEC:
case DDI_MT_RNUMBER:
DDI_SUCCESS) {
#if defined(DEBUG)
return (DDI_FAILURE);
#if defined(DEBUG)
return (DDI_FAILURE);
return (DDI_FAILURE);
#if defined(DEBUG)
return (DDI_FAILURE);
#if defined(DEBUG)
return (DDI_FAILURE);
#if defined(DEBUG)
case DDI_MO_MAP_LOCKED:
#if defined(USE_SOFT_INTRS)
*addrp = 0;
return (DDI_SUCCESS);
case DDI_MO_UNMAP:
return (DDI_SUCCESS);
return (DDI_FAILURE);
#ifdef __sparc
int interval;
if (i8042_polled_mode)
unsigned char stat;
unsigned char byte;
int new_wptr;
return (DDI_INTR_UNCLAIMED);
return (DDI_INTR_CLAIMED);
#if defined(DEBUG)
return (DDI_INTR_CLAIMED);
#if defined(USE_SOFT_INTRS)
#if !defined(USE_SOFT_INTRS)
return (DDI_INTR_CLAIMED);
int tries = 0;
#ifdef DEBUG
static uint8_t
ddi_acc_hdl_t *h;
case I8042_INT_INPUT_AVAIL:
return (ret);
case I8042_INT_INPUT_DATA:
#if defined(DEBUG)
ret = 0;
#if defined(DEBUG)
case I8042_INT_OUTPUT_DATA:
case I8042_POLL_OUTPUT_DATA:
(void *)addr);
ret = 0;
case I8042_POLL_INPUT_AVAIL:
return (B_TRUE);
return (B_FALSE);
case MAIN_PORT:
return (B_TRUE);
case AUX_PORT:
return (B_TRUE);
case I8042_POLL_INPUT_DATA:
return (ret);
#if defined(DEBUG)
case MAIN_PORT:
return (ret);
case AUX_PORT:
return (ret);
#if defined(DEBUG)
#if defined(DEBUG)
(void *)addr);
ret = 0;
return (ret);
ddi_acc_hdl_t *h;
case I8042_INT_OUTPUT_DATA:
case I8042_POLL_OUTPUT_DATA:
#if defined(DEBUG)
case I8042_INT_INPUT_AVAIL:
case I8042_INT_INPUT_DATA:
case I8042_POLL_INPUT_AVAIL:
case I8042_POLL_INPUT_DATA:
(void *)addr);
(void *)addr);
#if defined(USE_SOFT_INTRS)
int ret;
switch (intr_op) {
case DDI_INTROP_GETCAP:
== DDI_FAILURE)
*(int *)result = 0;
case DDI_INTROP_NINTRS:
case DDI_INTROP_ALLOC:
case DDI_INTROP_FREE:
case DDI_INTROP_GETPRI:
case DDI_INTROP_ADDISR:
#if defined(USE_SOFT_INTRS)
#if defined(DEBUG)
return (ret);
case DDI_INTROP_REMISR:
#if defined(USE_SOFT_INTRS)
case DDI_INTROP_ENABLE:
#if defined(USE_SOFT_INTRS)
case DDI_INTROP_DISABLE:
#if defined(USE_SOFT_INTRS)
case DDI_INTROP_NAVAIL:
return (DDI_FAILURE);
return (DDI_SUCCESS);
int *iprop;
unsigned int iprop_len;
int which_port;
switch (op) {
case DDI_CTLOPS_INITCHILD:
DDI_SUCCESS) {
#if defined(DEBUG)
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_CTLOPS_UNINITCHILD:
return (DDI_SUCCESS);
case DDI_CTLOPS_REPORTDEV:
return (DDI_SUCCESS);
static dev_info_t *
return (child);
int acpi_off = 0;
char *acpi_prop;
if (acpi_off == 0) {
int nodes_needed = 0;
int circ;
if (nodes_needed)
#ifdef __sparc
return (DDI_FAILURE);
!= DDI_PROP_SUCCESS) {
return (DDI_FAILURE);
return (DDI_SUCCESS);
static boolean_t
return (B_TRUE);
return (B_FALSE);