NT4/private/ntos/fw/alpha/kbdtest.c
2020-09-30 17:12:29 +02:00

415 lines
7.0 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Copyright (c) 1993 Digital Equipment Corporation
Module Name:
Kbdtest.c
Abstract:
This module implements the Keyboard and mouse test for the self-test.
Author:
Lluis Abello (lluis) 10-Feb-1991
Environment:
Rom self-test.
Revision History:
10-July-1992 John DeRosa [DEC]
Added Alpha/Jensen modifications.
--*/
#include <ntos.h>
#include "iodevice.h"
#include "kbdmouse.h"
#ifdef JENSEN
#include "jnsnprom.h"
#include "jnsnrtc.h"
#else
#include "mrgnrtc.h" // morgan
#endif
volatile ULONG TimerTicks;
//
// If the user accidentally types on the keyboard or moves the mouse
// during the power-up tests, there will be a failure. So, this code
// retries an initialization of the keyboard controller and keyboard
// this many times before giving up.
//
#define MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT 20
//
// function prototypes
//
VOID
FwpWriteIOChip(
ULONG ComboInternalAddress,
UCHAR ComboRegisterAddress
);
VOID
ClearKbdFifo(
)
/*++
Routine Description:
This routine empties the Keyboard controller Fifo.
Arguments:
None.
Return Value:
None.
--*/
{
UCHAR Trash, Stat;
volatile Timeout;
//
// wait until the previous command is processed.
//
while ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) != 0) {
}
while ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_OBF_MASK) != 0) {
Trash= READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data);
for (Timeout=0;Timeout<10000;Timeout++) {
}
}
}
BOOLEAN
GetKbdData(
PUCHAR C,
ULONG msec
)
/*++
Routine Description:
This routine polls the Status Register until Data is available or timeout,
then it reads and returns the Data.
Arguments:
C - pointer to a byte where to write the read value
msec - time-out time in milliseconds
Return Value:
TRUE if timeout, FALSE if OK;
--*/
{
//
// HACKHACK: This should be made smarter. For now it assumes
// 90,000,000 instruction per second and 12 instructions per iteration.
//
TimerTicks = msec * 1000 * 90 / 12;
while (TimerTicks--) {
if (READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_OBF_MASK) {
*C = READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data);
return FALSE;
}
}
return TRUE;
}
BOOLEAN
SendKbdData(
IN UCHAR Data
)
/*++
Routine Description:
This routine polls the Status Register until the controller is ready to
accept a data or timeout, then it send the Data.
Arguments:
None.
Return Value:
TRUE if timeout, FALSE if OK;
--*/
{
ULONG i;
for (i=0; i <KBD_TIMEOUT; i++) {
if ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) == 0) {
WRITE_PORT_UCHAR((PUCHAR)&KEYBOARD_WRITE->Data,Data);
return FALSE;
}
}
return TRUE;
}
BOOLEAN
SendKbdCommand(
IN UCHAR Command
)
/*++
Routine Description:
This routine polls the Status Register until the controller is ready to
accept a command or timeout, then it send the Command.
Arguments:
None.
Return Value:
TRUE if timeout, FALSE if OK;
--*/
{
ULONG i;
for (i=0; i <KBD_TIMEOUT; i++) {
if ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) == 0) {
WRITE_PORT_UCHAR((PUCHAR)&KEYBOARD_WRITE->Command,Command);
return FALSE;
}
}
return TRUE;
}
BOOLEAN
InitKeyboard(
)
/*++
Routine Description:
This routine enables and initializes the keyboard. It assumes a
101-key keyboard. It leaves the keyboard in XT mode (scan code = 01).
To account for the user accidentally typing on the keyboard, this
routine repeats the test a few times before giving up.
Arguments:
None.
Return Value:
FALSE if passed,
TRUE if bad ACK or BAT received, or if no response is received from
the keyboard.
--*/
{
UCHAR Result;
ULONG i;
ULONG Index;
BOOLEAN TestPassed;
TestPassed = FALSE;
for (Index = 0; Index < MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT; Index++) {
//
// Send Reset to Keyboard.
//
ClearKbdFifo();
for (;;) {
if (SendKbdData(KbdReset)) {
goto LoopAgain;
}
if (GetKbdData(&Result,1000)) {
goto LoopAgain;
}
if (Result == KbdResend) {
if (GetKbdData(&Result,1000)) {
goto LoopAgain;
}
continue;
}
if (Result != KbdAck) {
goto LoopAgain;
}
if (GetKbdData(&Result,7000)) {
goto LoopAgain;
}
if (Result != KbdBat) {
goto LoopAgain;
}
break;
}
//
// Enable Kbd and Select keyboard Scan code.
//
if (SendKbdCommand(KBD_CTR_ENABLE_KBD)) {
continue;
}
if (SendKbdData(KbdSelScanCode)) {
continue;
}
if (GetKbdData(&Result,1000)) {
continue;
}
if (SendKbdData(1)) { // select Scan code 1
continue;
}
if (GetKbdData(&Result,1000)) {
continue;
}
TestPassed = TRUE;
break;
//
// Here when an inner loop init fails and we want to do the outer
// loop again.
//
LoopAgain:
continue;
}
if (TestPassed) {
return FALSE;
} else {
return TRUE;
}
}
ULONG
InitKeyboardController(
)
/*++
Routine Description:
This routine Initializes the Keyboard controller. To account for
the user accidentally moving the mouse or typing on the keyboard, this
routine repeats the test a few times before giving up.
Arguments:
None.
Return Value:
FALSE if passed,
TRUE if bad response received from keyboard controller,
--*/
{
UCHAR Result;
ULONG Index;
BOOLEAN TestPassed;
TestPassed = FALSE;
for (Index = 0; Index < MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT; Index++) {
//
// Clear both fifos.
//
ClearKbdFifo();
//
// Init Control Register 1 with the PS/2/AT bit clear.
// This puts the keyboard into PS/2 mode.
//
FwpWriteIOChip (RTC_APORT, RTC_REGNUMBER_RTC_CR1);
Result = FwpReadIOChip(RTC_DPORT) & ~0x2;
FwpWriteIOChip (RTC_APORT, RTC_REGNUMBER_RTC_CR1);
FwpWriteIOChip (RTC_DPORT, Result);
//
// Send Selftest Command. This has to be done before anything else.
//
if (SendKbdCommand(KBD_CTR_SELFTEST)) {
continue;
}
if (GetKbdData(&Result,1000)) {
continue;
}
if (Result != Kbd_Ctr_Selftest_Passed) {
continue;
}
//
// Now the Keyboard and Mouse are disabled.
//
//
// Test Keyboard lines.
//
if (SendKbdCommand(KBD_CTR_KBDLINES_TEST)) {
continue;
}
if (GetKbdData(&Result,1000)) {
continue;
}
if (Result != INTERFACE_NO_ERROR) {
continue;
}
//
// Test Aux lines.
//
if (SendKbdCommand(KBD_CTR_AUXLINES_TEST)) {
continue;
}
if (GetKbdData(&Result,1000)) {
continue;
}
#ifndef ALPHA
// This test is disabled for Alpha/Jensen. It fails for some reason,
// but the VMS/OSF console front-end has more comprehensive
// tests than this routine anyway.
if (Result != INTERFACE_NO_ERROR) {
continue;
}
#endif
TestPassed = TRUE;
break;
}
if (TestPassed) {
return FALSE;
} else {
return TRUE;
}
}