NetBSD/sys/arch/arm32/shark/i8042.c

411 lines
12 KiB
C
Raw Normal View History

/* $NetBSD: i8042.c,v 1.2 1998/05/01 21:18:40 cgd Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
**++
**
** FACILITY:
**
** 8042 controller functions.
**
** ABSTRACT:
**
** This file contains routines to access the 8042 keyboard microprocessor.
** It hopefully allows a level of abstraction which will permit
** simplification of keyboard and mouse drivers which have to share the
** same registers when talking to the 8042.
**
** AUTHORS:
**
** John Court, Digital Equipment Corporation.
**
** CREATION DATE:
**
** 16/4/1997
**
**--
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <machine/kerndebug.h>
#include <machine/bus.h>
#include <arm32/shark/i8042reg.h>
/*
** Global variables
*/
/* Variable to control which debugs printed. No debug code gets
** built into this driver unless KERN_DEBUG is defined in the config
** file.
*/
int i8042debug = KERN_DEBUG_WARNING | KERN_DEBUG_ERROR;
/*
**++
** FUNCTIONAL DESCRIPTION
**
** i8042_flush
**
** This routine waits until the input and output buffers
** on the 8042 are empty, discarding any characters
** in the input buffer.
**
** FORMAL PARAMETERS:
**
** iot I/O tag for the mapped register space
** ioh I/O handle for the mapped register space
**
** IMPLICIT INPUTS:
**
** none.
**
** IMPLICIT OUTPUTS:
**
** none.
**
** FUNCTION VALUE:
**
** none.
**--
*/
void
i8042_flush( bus_space_tag_t iot,
bus_space_handle_t ioh)
{
/* Wait until input and output buffers are empty */
(void)i8042_wait_output(iot,ioh);
while (i8042_wait_input(iot,ioh,I8042_ANY_DATA))
{
(void)bus_space_read_1(iot, ioh, KBDATAPO);
}
return;
} /* End i8042_flush */
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** i8042_wait_output
**
** This function is boring. It just waits until output
** can be sent to the 8042 buffer.
**
** FORMAL PARAMETERS:
**
** iot I/O tag for the mapped register space
** ioh I/O handle for the mapped register space
**
** IMPLICIT INPUTS:
**
** none.
**
** IMPLICIT OUTPUTS:
**
** none.
**
** FUNCTION VALUE:
**
** 0 - Timed out waiting to send output.
** 1 - Can now send output to the 8042.
**--
*/
int
i8042_wait_output( bus_space_tag_t iot,
bus_space_handle_t ioh )
{
register u_int count;
int retValue = 0;
for (count = I8042_WAIT_THRESHOLD; count; count--)
{
/* Check if output buffer empty */
if ((bus_space_read_1(iot, ioh, KBSTATPO) & KBS_IBF) == 0)
{
retValue = 1;
break;
}
}
return (retValue);
} /* End i8042_wait_output */
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** i8042_wait_input
**
** This function waits until input is available to be read from
** the 8042 output buffer.
**
** FORMAL PARAMETERS:
**
** iot I/O tag for the mapped register space
** ioh I/O handle for the mapped register space
** type Type of input to wait for (auxiliary, keyboard or any).
**
** IMPLICIT INPUTS:
**
** none.
**
** IMPLICIT OUTPUTS:
**
** none.
**
** FUNCTION VALUE:
**
** 0 - Timed out waiting for input
** 1 - Input available to be read
**--
*/
int
i8042_wait_input(bus_space_tag_t iot,
bus_space_handle_t ioh,
u_char type)
{
register u_int count;
register u_char status;
int retValue = 0;
for (count = I8042_WAIT_THRESHOLD; count; count--)
{
/* Check if there is a character to be read */
status = bus_space_read_1(iot, ioh, KBSTATPO);
if (((status & type) == type) ||
((type == I8042_ANY_DATA) && (status & KBS_DIB)))
{
retValue = 1;
break;
}
I8042_DELAY;
}
KERN_DEBUG(i8042debug, KERN_DEBUG_INFO,
("i8042_wait_input: returning : %s\n\tlast status : 0x%x\n",
retValue ? "Found Data" : "Exceeded Wait Threshold",
status));
return (retValue);
} /* End i8042_wait_input */
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** i8042_cmd
**
** This function sends a command to the 8042 device or the auxiliary
** device hanging off it. The command is retried a
** number of times if a resend response is received.
**
** FORMAL PARAMETERS:
**
** iot I/O tag for the mapped register space
** ioh I/O handle for the mapped register space
** auxCmd An indication of what type of command this is.
** checkResponse A switch indicating whether to read a result after
** executing the command and compare ot with
** "responseExpected".
** responseExpected Only valid if "checkResponse" is non-zero. This
** is compared with the data value read after the
** command has been executed.
** value Command to send to the device selected by "auxCmd".
**
** IMPLICIT INPUTS:
**
** none.
**
** IMPLICIT OUTPUTS:
**
** none.
**
** FUNCTION VALUE:
**
** 0 - Failed to send command or receive acknowledgement for it
** 1 - Command sent and responded to successfully.
**--
*/
int
i8042_cmd(bus_space_tag_t iot,
bus_space_handle_t ioh,
u_char auxCmd,
u_char checkResponse,
u_char responseExpected,
u_char value)
{
u_int retries;
register u_char c = NULL;
int status;
/* Assume failure
*/
status = 0;
for (retries = I8042_RETRIES;
i8042_wait_output(iot,ioh) && retries;
retries--)
{
if (auxCmd == I8042_AUX_CMD)
{
/* Setup to write command to auxiliary device
*/
bus_space_write_1(iot, ioh, KBCMDPO, KBC_AUXWRITE);
/* Write actual command to selected device
*/
if (i8042_wait_output(iot,ioh))
{
bus_space_write_1(iot, ioh, KBOUTPO, value);
}
else
{
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: failed aux device request of 0x%x\n",
value));
break;
}
}
else if (auxCmd == I8042_CMD)
{
/* Write command to keyboard controller requested.
*/
bus_space_write_1(iot, ioh, KBCMDPO, value);
}
else if (auxCmd == I8042_KBD_CMD)
{
/* Write a command to actual keyboard H/W device.
*/
bus_space_write_1(iot, ioh, KBOUTPO, value);
}
else if (auxCmd == I8042_WRITE_CCB)
{
/* Write 8042 Controller Command Byte requested
*/
bus_space_write_1(iot, ioh, KBCMDPO, K_LDCMDBYTE);
/* Write actual command to selected device
*/
if (i8042_wait_output(iot,ioh))
{
bus_space_write_1(iot, ioh, KBOUTPO, value);
}
else
{
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: failed contoller command byte "
"write request of 0x%x\n",
value));
break;
}
}
else
{
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: invalid device identifier of 0x%x\n",
auxCmd));
break;
}
/* Does anyone need to check the result of this command ?
*/
if (checkResponse == I8042_CHECK_RESPONSE)
{
/* get response from device and check if
** successfull.
*/
if (i8042_wait_input(iot,ioh,I8042_ANY_DATA))
{
c = bus_space_read_1(iot, ioh, KBDATAPO);
if (c == responseExpected)
{
/* Successfull command so we're outa here
*/
status = 1;
break;
}
else if (c == KBR_RESEND)
{
/* Hmm response was try again so lets.
*/
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: resend of 0x%x\n", value));
}
else
{
/* response was nothing we expected so we're
** outa here.
*/
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: unexpected response 0x%x\n", c));
break;
}
} /* End If able to get response from device */
else
{
/* Timmed out waiting for a response .... maybe we
** weren't meant to get one ??
*/
KERN_DEBUG(i8042debug, KERN_DEBUG_WARNING,
("i8042_cmd: no response to command 0x%x\n",
value));
break;
}
} /* End if need to check for response */
else
{
/* Not requested to check for response and we did send the
** command so I guess we were successfull :-)
*/
status = 1;
break;
}
} /* End loop for several retries if needed a response */
/* Diagnostic output on command value, result and status returned
*/
KERN_DEBUG(i8042debug, KERN_DEBUG_INFO,
("i8042_cmd: %s Device : Command 0x%x: %s:\n\t "
"Check Value 0x%x: "
"Response Value 0x%x: Status being returned 0x%x\n",
(auxCmd == I8042_AUX_CMD) ? "Auxiliary" : "Keyboard",
value,
(checkResponse == I8042_CHECK_RESPONSE) ?
"Checking response" : "NOT checking response",
responseExpected, c, status));
return (status);
} /* End i8042_cmd */