1 /* 2 * PROJECT: ReactOS Boot Loader 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: boot/armllb/hw/versatile/hwkmi.c 5 * PURPOSE: LLB KMI Support for Versatile 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 #include "precomp.h" 10 11 // 12 // Control Register Bits 13 // 14 #define KMICR_TYPE (1 << 5) 15 #define KMICR_RXINTREN (1 << 4) 16 #define KMICR_TXINTREN (1 << 3) 17 #define KMICR_EN (1 << 2) 18 #define KMICR_FD (1 << 1) 19 #define KMICR_FC (1 << 0) 20 21 // 22 // Status Register Bits 23 // 24 #define KMISTAT_TXEMPTY (1 << 6) 25 #define KMISTAT_TXBUSY (1 << 5) 26 #define KMISTAT_RXFULL (1 << 4) 27 #define KMISTAT_RXBUSY (1 << 3) 28 #define KMISTAT_RXPARITY (1 << 2) 29 #define KMISTAT_IC (1 << 1) 30 #define KMISTAT_ID (1 << 0) 31 32 // 33 // KMI Registers 34 // 35 #define PL050_KMICR (LlbHwVersaKmiBase + 0x00) 36 #define PL050_KMISTAT (LlbHwVersaKmiBase + 0x04) 37 #define PL050_KMIDATA (LlbHwVersaKmiBase + 0x08) 38 #define PL050_KMICLKDIV (LlbHwVersaKmiBase + 0x0c) 39 static const ULONG LlbHwVersaKmiBase = 0x10006000; 40 41 // 42 // PS/2 Commands/Requests 43 // 44 #define PS2_O_RESET 0xff 45 #define PS2_O_RESEND 0xfe 46 #define PS2_O_DISABLE 0xf5 47 #define PS2_O_ENABLE 0xf4 48 #define PS2_O_ECHO 0xee 49 #define PS2_O_SET_DEFAULT 0xf6 50 #define PS2_O_SET_RATE_DELAY 0xf3 51 #define PS2_O_SET_SCANSET 0xf0 52 #define PS2_O_INDICATORS 0xed 53 #define PS2_I_RESEND 0xfe 54 #define PS2_I_DIAGFAIL 0xfd 55 #define PS2_I_ACK 0xfa 56 #define PS2_I_BREAK 0xf0 57 #define PS2_I_ECHO 0xee 58 #define PS2_I_BAT_OK 0xaa 59 60 /* FUNCTIONS ******************************************************************/ 61 62 VOID 63 NTAPI 64 LlbHwVersaKmiSendAndWait(IN ULONG Value) 65 { 66 volatile int i = 1000; 67 68 /* Send the value */ 69 LlbHwKbdSend(Value); 70 71 /* Wait a bit */ 72 while (--i); 73 74 /* Now make sure we received an ACK */ 75 if (LlbHwKbdRead() != PS2_I_ACK) DbgPrint("PS/2 FAILURE!\n"); 76 } 77 78 VOID 79 NTAPI 80 LlbHwVersaKmiInitialize(VOID) 81 { 82 UCHAR Divisor; 83 84 /* Setup divisor and enable KMI */ 85 Divisor = (LlbHwGetPClk() / 8000000) - 1; 86 WRITE_REGISTER_UCHAR(PL050_KMICLKDIV, Divisor); 87 WRITE_REGISTER_UCHAR(PL050_KMICR, KMICR_EN); 88 89 /* Reset PS/2 controller */ 90 LlbHwVersaKmiSendAndWait(PS2_O_RESET); 91 if (LlbHwKbdRead() != PS2_I_BAT_OK) DbgPrint("PS/2 RESET FAILURE!\n"); 92 93 /* Send PS/2 Initialization Stream */ 94 LlbHwVersaKmiSendAndWait(PS2_O_DISABLE); 95 LlbHwVersaKmiSendAndWait(PS2_O_SET_DEFAULT); 96 LlbHwVersaKmiSendAndWait(PS2_O_SET_SCANSET); 97 LlbHwVersaKmiSendAndWait(1); 98 LlbHwVersaKmiSendAndWait(PS2_O_ENABLE); 99 } 100 101 VOID 102 NTAPI 103 LlbHwKbdSend(IN ULONG Value) 104 { 105 ULONG Status; 106 107 /* Wait for ready signal */ 108 do 109 { 110 /* Read TX buffer state */ 111 Status = READ_REGISTER_UCHAR(PL050_KMISTAT); 112 } while (!(Status & KMISTAT_TXEMPTY)); 113 114 /* Send value */ 115 WRITE_REGISTER_UCHAR(PL050_KMIDATA, Value); 116 } 117 118 BOOLEAN 119 NTAPI 120 LlbHwKbdReady(VOID) 121 { 122 return READ_REGISTER_UCHAR(PL050_KMISTAT) & KMISTAT_RXFULL; 123 } 124 125 INT 126 NTAPI 127 LlbHwKbdRead(VOID) 128 { 129 /* Read current data on keyboard */ 130 return READ_REGISTER_UCHAR(PL050_KMIDATA); 131 } 132 133 /* EOF */ 134