1#include <linux/keyboard.h> 2 3#include "defkeymap.c" /* yeah I know it's bad -- Cort */ 4 5 6unsigned char shfts, ctls, alts, caps; 7 8#define KBDATAP 0x60 /* kbd data port */ 9#define KBSTATUSPORT 0x61 /* kbd status */ 10#define KBSTATP 0x64 /* kbd status port */ 11#define KBINRDY 0x01 12#define KBOUTRDY 0x02 13 14extern unsigned char inb(int port); 15extern void outb(int port, char val); 16extern void puts(const char *); 17extern void puthex(unsigned long val); 18extern void udelay(long x); 19 20static int kbd(int noblock) 21{ 22 unsigned char dt, brk, val; 23 unsigned code; 24loop: 25 if (noblock) { 26 if ((inb(KBSTATP) & KBINRDY) == 0) 27 return (-1); 28 } else while((inb(KBSTATP) & KBINRDY) == 0) ; 29 30 dt = inb(KBDATAP); 31 32 brk = dt & 0x80; /* brk == 1 on key release */ 33 dt = dt & 0x7f; /* keycode */ 34 35 if (shfts) 36 code = shift_map[dt]; 37 else if (ctls) 38 code = ctrl_map[dt]; 39 else 40 code = plain_map[dt]; 41 42 val = KVAL(code); 43 switch (KTYP(code) & 0x0f) { 44 case KT_LATIN: 45 if (brk) 46 break; 47 if (alts) 48 val |= 0x80; 49 if (val == 0x7f) /* map delete to backspace */ 50 val = '\b'; 51 return val; 52 53 case KT_LETTER: 54 if (brk) 55 break; 56 if (caps) 57 val -= 'a'-'A'; 58 return val; 59 60 case KT_SPEC: 61 if (brk) 62 break; 63 if (val == KVAL(K_CAPS)) 64 caps = !caps; 65 else if (val == KVAL(K_ENTER)) { 66enter: /* Wait for key up */ 67 while (1) { 68 while((inb(KBSTATP) & KBINRDY) == 0) ; 69 dt = inb(KBDATAP); 70 if (dt & 0x80) /* key up */ break; 71 } 72 return 10; 73 } 74 break; 75 76 case KT_PAD: 77 if (brk) 78 break; 79 if (val < 10) 80 return val; 81 if (val == KVAL(K_PENTER)) 82 goto enter; 83 break; 84 85 case KT_SHIFT: 86 switch (val) { 87 case KG_SHIFT: 88 case KG_SHIFTL: 89 case KG_SHIFTR: 90 shfts = brk ? 0 : 1; 91 break; 92 case KG_ALT: 93 case KG_ALTGR: 94 alts = brk ? 0 : 1; 95 break; 96 case KG_CTRL: 97 case KG_CTRLL: 98 case KG_CTRLR: 99 ctls = brk ? 0 : 1; 100 break; 101 } 102 break; 103 104 case KT_LOCK: 105 switch (val) { 106 case KG_SHIFT: 107 case KG_SHIFTL: 108 case KG_SHIFTR: 109 if (brk) 110 shfts = !shfts; 111 break; 112 case KG_ALT: 113 case KG_ALTGR: 114 if (brk) 115 alts = !alts; 116 break; 117 case KG_CTRL: 118 case KG_CTRLL: 119 case KG_CTRLR: 120 if (brk) 121 ctls = !ctls; 122 break; 123 } 124 break; 125 } 126 if (brk) return (-1); /* Ignore initial 'key up' codes */ 127 goto loop; 128} 129 130static int __kbdreset(void) 131{ 132 unsigned char c; 133 int i, t; 134 135 /* flush input queue */ 136 t = 2000; 137 while ((inb(KBSTATP) & KBINRDY)) 138 { 139 (void)inb(KBDATAP); 140 if (--t == 0) 141 return 1; 142 } 143 /* Send self-test */ 144 t = 20000; 145 while (inb(KBSTATP) & KBOUTRDY) 146 if (--t == 0) 147 return 2; 148 outb(KBSTATP,0xAA); 149 t = 200000; 150 while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */ 151 if (--t == 0) 152 return 3; 153 if ((c = inb(KBDATAP)) != 0x55) 154 { 155 puts("Keyboard self test failed - result:"); 156 puthex(c); 157 puts("\n"); 158 } 159 /* Enable interrupts and keyboard controller */ 160 t = 20000; 161 while (inb(KBSTATP) & KBOUTRDY) 162 if (--t == 0) return 4; 163 outb(KBSTATP,0x60); 164 t = 20000; 165 while (inb(KBSTATP) & KBOUTRDY) 166 if (--t == 0) return 5; 167 outb(KBDATAP,0x45); 168 for (i = 0; i < 10000; i++) udelay(1); 169 170 t = 20000; 171 while (inb(KBSTATP) & KBOUTRDY) 172 if (--t == 0) return 6; 173 outb(KBSTATP,0x20); 174 t = 200000; 175 while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */ 176 if (--t == 0) return 7; 177 if (! (inb(KBDATAP) & 0x40)) { 178 /* 179 * Quote from PS/2 System Reference Manual: 180 * 181 * "Address hex 0060 and address hex 0064 should be 182 * written only when the input-buffer-full bit and 183 * output-buffer-full bit in the Controller Status 184 * register are set 0." (KBINRDY and KBOUTRDY) 185 */ 186 t = 200000; 187 while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) 188 if (--t == 0) return 8; 189 outb(KBDATAP,0xF0); 190 t = 200000; 191 while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) 192 if (--t == 0) return 9; 193 outb(KBDATAP,0x01); 194 } 195 t = 20000; 196 while (inb(KBSTATP) & KBOUTRDY) 197 if (--t == 0) return 10; 198 outb(KBSTATP,0xAE); 199 return 0; 200} 201 202static void kbdreset(void) 203{ 204 int ret = __kbdreset(); 205 206 if (ret) { 207 puts("__kbdreset failed: "); 208 puthex(ret); 209 puts("\n"); 210 } 211} 212 213/* We have to actually read the keyboard when CRT_tstc is called, 214 * since the pending data might be a key release code, and therefore 215 * not valid data. In this case, kbd() will return -1, even though there's 216 * data to be read. Of course, we might actually read a valid key press, 217 * in which case it gets queued into key_pending for use by CRT_getc. 218 */ 219 220static int kbd_reset = 0; 221 222static int key_pending = -1; 223 224int CRT_getc(void) 225{ 226 int c; 227 if (!kbd_reset) {kbdreset(); kbd_reset++; } 228 229 if (key_pending != -1) { 230 c = key_pending; 231 key_pending = -1; 232 return c; 233 } else { 234 while ((c = kbd(0)) == 0) ; 235 return c; 236 } 237} 238 239int CRT_tstc(void) 240{ 241 if (!kbd_reset) {kbdreset(); kbd_reset++; } 242 243 while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) { 244 key_pending = kbd(1); 245 } 246 247 return (key_pending != -1); 248} 249