reactos/boot/armllb/hw/versatile/hwkmi.c

134 lines
3.2 KiB
C

/*
* PROJECT: ReactOS Boot Loader
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: boot/armllb/hw/versatile/hwkmi.c
* PURPOSE: LLB KMI Support for Versatile
* PROGRAMMERS: ReactOS Portable Systems Group
*/
#include "precomp.h"
//
// Control Register Bits
//
#define KMICR_TYPE (1 << 5)
#define KMICR_RXINTREN (1 << 4)
#define KMICR_TXINTREN (1 << 3)
#define KMICR_EN (1 << 2)
#define KMICR_FD (1 << 1)
#define KMICR_FC (1 << 0)
//
// Status Register Bits
//
#define KMISTAT_TXEMPTY (1 << 6)
#define KMISTAT_TXBUSY (1 << 5)
#define KMISTAT_RXFULL (1 << 4)
#define KMISTAT_RXBUSY (1 << 3)
#define KMISTAT_RXPARITY (1 << 2)
#define KMISTAT_IC (1 << 1)
#define KMISTAT_ID (1 << 0)
//
// KMI Registers
//
#define PL050_KMICR (LlbHwVersaKmiBase + 0x00)
#define PL050_KMISTAT (LlbHwVersaKmiBase + 0x04)
#define PL050_KMIDATA (LlbHwVersaKmiBase + 0x08)
#define PL050_KMICLKDIV (LlbHwVersaKmiBase + 0x0c)
static const ULONG LlbHwVersaKmiBase = 0x10006000;
//
// PS/2 Commands/Requests
//
#define PS2_O_RESET 0xff
#define PS2_O_RESEND 0xfe
#define PS2_O_DISABLE 0xf5
#define PS2_O_ENABLE 0xf4
#define PS2_O_ECHO 0xee
#define PS2_O_SET_DEFAULT 0xf6
#define PS2_O_SET_RATE_DELAY 0xf3
#define PS2_O_SET_SCANSET 0xf0
#define PS2_O_INDICATORS 0xed
#define PS2_I_RESEND 0xfe
#define PS2_I_DIAGFAIL 0xfd
#define PS2_I_ACK 0xfa
#define PS2_I_BREAK 0xf0
#define PS2_I_ECHO 0xee
#define PS2_I_BAT_OK 0xaa
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
LlbHwVersaKmiSendAndWait(IN ULONG Value)
{
volatile int i = 1000;
/* Send the value */
LlbHwKbdSend(Value);
/* Wait a bit */
while (--i);
/* Now make sure we received an ACK */
if (LlbHwKbdRead() != PS2_I_ACK) DbgPrint("PS/2 FAILURE!\n");
}
VOID
NTAPI
LlbHwVersaKmiInitialize(VOID)
{
UCHAR Divisor;
/* Setup divisor and enable KMI */
Divisor = (LlbHwGetPClk() / 8000000) - 1;
WRITE_REGISTER_UCHAR(PL050_KMICLKDIV, Divisor);
WRITE_REGISTER_UCHAR(PL050_KMICR, KMICR_EN);
/* Reset PS/2 controller */
LlbHwVersaKmiSendAndWait(PS2_O_RESET);
if (LlbHwKbdRead() != PS2_I_BAT_OK) DbgPrint("PS/2 RESET FAILURE!\n");
/* Send PS/2 Initialization Stream */
LlbHwVersaKmiSendAndWait(PS2_O_DISABLE);
LlbHwVersaKmiSendAndWait(PS2_O_SET_DEFAULT);
LlbHwVersaKmiSendAndWait(PS2_O_SET_SCANSET);
LlbHwVersaKmiSendAndWait(1);
LlbHwVersaKmiSendAndWait(PS2_O_ENABLE);
}
VOID
NTAPI
LlbHwKbdSend(IN ULONG Value)
{
ULONG Status;
/* Wait for ready signal */
do
{
/* Read TX buffer state */
Status = READ_REGISTER_UCHAR(PL050_KMISTAT);
} while (!(Status & KMISTAT_TXEMPTY));
/* Send value */
WRITE_REGISTER_UCHAR(PL050_KMIDATA, Value);
}
BOOLEAN
NTAPI
LlbHwKbdReady(VOID)
{
return READ_REGISTER_UCHAR(PL050_KMISTAT) & KMISTAT_RXFULL;
}
INT
NTAPI
LlbHwKbdRead(VOID)
{
/* Read current data on keyboard */
return READ_REGISTER_UCHAR(PL050_KMIDATA);
}
/* EOF */