From e7ff33a8bc2e5cf761e2deeb2abc12a65e86931e Mon Sep 17 00:00:00 2001 From: evb Date: Wed, 3 Feb 2010 01:19:26 +0000 Subject: [PATCH] - Implement logical keyboard interface. Converts scan code to ASCII codes (just ok). - Implement firmware ConsGetCh based on keyboard interface. - Implement KMI (Keyboard & Mouse Interface) PL050 driver for Versatile to init PS/2 and read keyboard scancodes. Can now press ENTER/whatever when FreeLDR gives "Cannot find freeldr.ini" error. - More fixes svn path=/trunk/; revision=45385 --- reactos/boot/armllb/armllb.rbuild | 2 + reactos/boot/armllb/crtsupp.c | 14 ++ reactos/boot/armllb/fw.c | 5 +- reactos/boot/armllb/hw/keyboard.c | 242 ++++++++++++++++++++++ reactos/boot/armllb/hw/versatile/hwinit.c | 3 + reactos/boot/armllb/hw/versatile/hwkmi.c | 135 ++++++++++++ reactos/boot/armllb/inc/hw.h | 12 ++ reactos/boot/armllb/inc/keyboard.h | 15 ++ reactos/boot/armllb/inc/precomp.h | 7 + reactos/boot/armllb/inc/versa.h | 6 + reactos/boot/armllb/main.c | 14 -- 11 files changed, 438 insertions(+), 17 deletions(-) create mode 100755 reactos/boot/armllb/hw/keyboard.c create mode 100755 reactos/boot/armllb/hw/versatile/hwkmi.c create mode 100755 reactos/boot/armllb/inc/keyboard.h diff --git a/reactos/boot/armllb/armllb.rbuild b/reactos/boot/armllb/armllb.rbuild index 6def3c93f1e..ea39a50c5c1 100644 --- a/reactos/boot/armllb/armllb.rbuild +++ b/reactos/boot/armllb/armllb.rbuild @@ -24,6 +24,7 @@ envir.c fw.c + keyboard.c serial.c video.c @@ -38,6 +39,7 @@ hwclcd.c + hwkmi.c hwuart.c hwinfo.c hwinit.c diff --git a/reactos/boot/armllb/crtsupp.c b/reactos/boot/armllb/crtsupp.c index df0f37cd1c5..ba2dde3937c 100644 --- a/reactos/boot/armllb/crtsupp.c +++ b/reactos/boot/armllb/crtsupp.c @@ -40,4 +40,18 @@ int printf(const char *fmt, ...) return puts(printbuffer); } +VOID +DbgPrint(const char *fmt, ...) +{ + va_list args; + unsigned int i, j; + char Buffer[1024]; + + va_start(args, fmt); + i = vsprintf(Buffer, fmt, args); + va_end(args); + + for (j = 0; j < i; j++) LlbSerialPutChar(Buffer[j]); +} + /* EOF */ diff --git a/reactos/boot/armllb/fw.c b/reactos/boot/armllb/fw.c index 0dad84141c1..baa9cdedfff 100644 --- a/reactos/boot/armllb/fw.c +++ b/reactos/boot/armllb/fw.c @@ -28,9 +28,8 @@ LlbFwKbHit(VOID) INT LlbFwGetCh(VOID) { - /* Not yet implemented */ - while (TRUE); - return 0; + /* Return the key pressed */ + return LlbKeyboardGetChar(); } /* EOF */ diff --git a/reactos/boot/armllb/hw/keyboard.c b/reactos/boot/armllb/hw/keyboard.c new file mode 100755 index 00000000000..06d2c6706dd --- /dev/null +++ b/reactos/boot/armllb/hw/keyboard.c @@ -0,0 +1,242 @@ +/* + * PROJECT: ReactOS Boot Loader + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/armllb/hw/keyboard.c + * PURPOSE: LLB Keyboard Routines + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +#include "precomp.h" + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 +#define E1_PAUSE 119 +#define E0_MACRO 112 +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +#define E0_OK 124 +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +/* US 101 KEYBOARD LAYOUT *****************************************************/ + +CHAR LlbHwScanCodeToAsciiTable[58][2] = +{ + { 0,0 } , + { 27, 27 } , + { '1','!' } , + { '2','@' } , + { '3','#' } , + { '4','$' } , + { '5','%' } , + { '6','^' } , + { '7','&' } , + { '8','*' } , + { '9','(' } , + { '0',')' } , + { '-','_' } , + { '=','+' } , + { 8,8 } , + { 9,9 } , + { 'q','Q' } , + { 'w','W' } , + { 'e','E' } , + { 'r','R' } , + { 't','T' } , + { 'y','Y' } , + { 'u','U' } , + { 'i','I' } , + { 'o','O' } , + { 'p','P' } , + { '[','{' } , + { ']','}' } , + { 13,13 } , + { 0,0 } , + { 'a','A' } , + { 's','S' } , + { 'd','D' } , + { 'f','F' } , + { 'g','G' } , + { 'h','H' } , + { 'j','J' } , + { 'k','K' } , + { 'l','L' } , + { ';',':' } , + { 39,34 } , + { '`','~' } , + { 0,0 } , + { '\\','|'} , + { 'z','Z' } , + { 'x','X' } , + { 'c','C' } , + { 'v','V' } , + { 'b','B' } , + { 'n','N' } , + { 'm','M' } , + { ',','<' } , + { '.','>' } , + { '/','?' } , + { 0,0 } , + { 0,0 } , + { 0,0 } , + { ' ',' ' } , +}; + +/* EXTENDED KEY TABLE *********************************************************/ + +UCHAR LlbHwExtendedScanCodeTable[128] = +{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + E0_KPENTER, E0_RCTRL, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, E0_KPSLASH, 0, E0_PRSCR, + E0_RALT, 0, 0, 0, + 0, E0_F13, E0_F14, E0_HELP, + E0_DO, E0_F17, 0, 0, + 0, 0, E0_BREAK, E0_HOME, + E0_UP, E0_PGUP, 0, E0_LEFT, + E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, + 0, 0, 0, 0, + 0, 0, 0, E0_MSLW, + E0_MSRW, E0_MSTM, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, E0_MACRO, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + +/* FUNCTIONS ******************************************************************/ + +USHORT LlbKbdLastScanCode; + +UCHAR +NTAPI +LlbKbdTranslateScanCode(IN USHORT ScanCode, + IN PUCHAR KeyCode) +{ + ULONG LastScanCode; + + /* Check for extended scan codes */ + if ((ScanCode == 0xE0) || (ScanCode == 0xE1)) + { + /* We'll get these on the next scan */ + LlbKbdLastScanCode = ScanCode; + return 0; + } + + /* Check for bogus scan codes */ + if ((ScanCode == 0x00) || (ScanCode == 0xFF)) + { + /* Reset */ + LlbKbdLastScanCode = 0; + return 0; + } + + /* Only act on the break, not the make */ + if (ScanCode > 0x80) return 0; + + /* Keep only simple scan codes */ + ScanCode &= 0x7F; + + /* Check if this was part of an extended sequence */ + if (LlbKbdLastScanCode) + { + /* Save the last scan code and clear it, since we've consumed it now */ + LastScanCode = LlbKbdLastScanCode; + LlbKbdLastScanCode = 0; + switch (LastScanCode) + { + /* E0 extended codes */ + case 0xE0: + + /* Skip bogus codes */ + if ((ScanCode == 0x2A) || (ScanCode == 0x36)) return 0; + + /* Lookup the code for it */ + if (!LlbHwExtendedScanCodeTable[ScanCode]) return 0; + *KeyCode = LlbHwExtendedScanCodeTable[ScanCode]; + break; + + /* E1 extended codes */ + case 0xE1: + + /* Only recognize one (the SYSREQ/PAUSE sequence) */ + if (ScanCode != 0x1D) return 0; + LlbKbdLastScanCode = 0x100; + break; + + /* PAUSE sequence */ + case 0x100: + + /* Make sure it's the one */ + if (ScanCode != 0x45) return 0; + *KeyCode = E1_PAUSE; + break; + } + } + else + { + /* Otherwise, the scancode is the key code */ + LlbKbdLastScanCode = 0; + *KeyCode = ScanCode; + } + + /* Translation success */ + return 1; + } + +CHAR +NTAPI +LlbKeyboardGetChar(VOID) +{ + UCHAR ScanCode, KeyCode; + + do + { + /* Read the scan code and convert it to a virtual key code */ + ScanCode = LlbHwKbdRead(); + } while (!LlbKbdTranslateScanCode(ScanCode, &KeyCode)); + + /* Is this ASCII? */ + if (KeyCode > 96) return ScanCode; + + /* Return the ASCII character */ + return LlbHwScanCodeToAsciiTable[KeyCode][0]; +} + +/* EOF */ diff --git a/reactos/boot/armllb/hw/versatile/hwinit.c b/reactos/boot/armllb/hw/versatile/hwinit.c index d1cc822a728..6aa73e6461d 100755 --- a/reactos/boot/armllb/hw/versatile/hwinit.c +++ b/reactos/boot/armllb/hw/versatile/hwinit.c @@ -17,6 +17,9 @@ LlbHwInitialize(VOID) /* Setup the UART (PL011) */ LlbHwVersaUartInitialize(); + + /* Setup the KMI (PL050) */ + LlbHwVersaKmiInitialize(); } // diff --git a/reactos/boot/armllb/hw/versatile/hwkmi.c b/reactos/boot/armllb/hw/versatile/hwkmi.c new file mode 100755 index 00000000000..1963b0cb979 --- /dev/null +++ b/reactos/boot/armllb/hw/versatile/hwkmi.c @@ -0,0 +1,135 @@ +/* + * 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); +} + +INT +NTAPI +LlbHwKbdRead(VOID) +{ + ULONG Status; + + /* Wait for ready signal */ + do + { + /* Read TX buffer state */ + Status = READ_REGISTER_UCHAR(PL050_KMISTAT); + } while (!(Status & KMISTAT_RXFULL)); + + /* Read current data on keyboard */ + return READ_REGISTER_UCHAR(PL050_KMIDATA); +} + +/* EOF */ diff --git a/reactos/boot/armllb/inc/hw.h b/reactos/boot/armllb/inc/hw.h index 269c43e3508..1d8ad187a4f 100755 --- a/reactos/boot/armllb/inc/hw.h +++ b/reactos/boot/armllb/inc/hw.h @@ -86,6 +86,18 @@ LlbHwBuildMemoryMap( IN PBIOS_MEMORY_MAP MemoryMap ); +VOID +NTAPI +LlbHwKbdSend( + IN ULONG Value +); + +INT +NTAPI +LlbHwKbdRead( + VOID +); + POSLOADER_INIT NTAPI LlbHwLoadOsLoaderFromRam( diff --git a/reactos/boot/armllb/inc/keyboard.h b/reactos/boot/armllb/inc/keyboard.h new file mode 100755 index 00000000000..034f76d2bc2 --- /dev/null +++ b/reactos/boot/armllb/inc/keyboard.h @@ -0,0 +1,15 @@ +/* + * PROJECT: ReactOS Boot Loader + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/armllb/inc/keyboard.h + * PURPOSE: LLB Keyboard Functions + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +CHAR +NTAPI +LlbKeyboardGetChar( + VOID +); + +/* EOF */ diff --git a/reactos/boot/armllb/inc/precomp.h b/reactos/boot/armllb/inc/precomp.h index 6c211a1f658..ce2a63798c4 100755 --- a/reactos/boot/armllb/inc/precomp.h +++ b/reactos/boot/armllb/inc/precomp.h @@ -15,5 +15,12 @@ #include "fw.h" #include "serial.h" #include "video.h" +#include "keyboard.h" + +VOID +DbgPrint( + const char *fmt, + ... +); /* EOF */ diff --git a/reactos/boot/armllb/inc/versa.h b/reactos/boot/armllb/inc/versa.h index 3de745a2fe5..fae0835a82f 100755 --- a/reactos/boot/armllb/inc/versa.h +++ b/reactos/boot/armllb/inc/versa.h @@ -18,4 +18,10 @@ LlbHwVersaClcdInitialize( VOID ); +VOID +NTAPI +LlbHwVersaKmiInitialize( + VOID +); + /* EOF */ diff --git a/reactos/boot/armllb/main.c b/reactos/boot/armllb/main.c index 142b8392651..7248cbc17a6 100755 --- a/reactos/boot/armllb/main.c +++ b/reactos/boot/armllb/main.c @@ -25,18 +25,4 @@ LlbStartup(VOID) while (TRUE); } -VOID -DbgPrint(const char *fmt, ...) -{ - va_list args; - unsigned int i; - char Buffer[1024]; - - va_start(args, fmt); - i = vsprintf(Buffer, fmt, args); - va_end(args); - - while (*Buffer) LlbSerialPutChar(*Buffer); -} - /* EOF */ -- 2.17.1