00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00039 #include <arch/kbd.h>
00040 #include <ipc/ipc.h>
00041 #include <unistd.h>
00042 #include <kbd.h>
00043 #include <keys.h>
00044
00045
00046 #define i8042_OUTPUT_FULL 0x1
00047 #define i8042_INPUT_FULL 0x2
00048 #define i8042_MOUSE_DATA 0x20
00049
00050
00051 #define i8042_CMD_KBD 0x60
00052 #define i8042_CMD_MOUSE 0xd4
00053
00054
00055 #define i8042_KBD_IE 0x1
00056 #define i8042_MOUSE_IE 0x2
00057 #define i8042_KBD_DISABLE 0x10
00058 #define i8042_MOUSE_DISABLE 0x20
00059 #define i8042_KBD_TRANSLATE 0x40
00060
00061
00062 #define MOUSE_OUT_INIT 0xf4
00063 #define MOUSE_ACK 0xfa
00064
00065
00066 #define SPECIAL 255
00067 #define KEY_RELEASE 0x80
00068
00072 #define IGNORE_CODE 0x7f
00073
00074 #define PRESSED_SHIFT (1<<0)
00075 #define PRESSED_CAPSLOCK (1<<1)
00076 #define LOCKED_CAPSLOCK (1<<0)
00077
00079 #define SC_ESC 0x01
00080 #define SC_BACKSPACE 0x0e
00081 #define SC_LSHIFT 0x2a
00082 #define SC_RSHIFT 0x36
00083 #define SC_CAPSLOCK 0x3a
00084 #define SC_SPEC_ESCAPE 0xe0
00085 #define SC_LEFTARR 0x4b
00086 #define SC_RIGHTARR 0x4d
00087 #define SC_UPARR 0x48
00088 #define SC_DOWNARR 0x50
00089 #define SC_DELETE 0x53
00090 #define SC_HOME 0x47
00091 #define SC_END 0x4f
00092
00093 #define FUNCTION_KEYS 0x100
00094
00095 static volatile int keyflags;
00096 static volatile int lockflags;
00099 static int sc_primary_map[] = {
00100 SPECIAL,
00101 SPECIAL,
00102 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
00103 '\b',
00104 '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
00105 SPECIAL,
00106 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'',
00107 '`',
00108 SPECIAL,
00109 '\\',
00110 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
00111 SPECIAL,
00112 '*',
00113 SPECIAL,
00114 ' ',
00115 SPECIAL,
00116 (FUNCTION_KEYS | 1),
00117 (FUNCTION_KEYS | 2),
00118 (FUNCTION_KEYS | 3),
00119 (FUNCTION_KEYS | 4),
00120 (FUNCTION_KEYS | 5),
00121 (FUNCTION_KEYS | 6),
00122 (FUNCTION_KEYS | 7),
00123 (FUNCTION_KEYS | 8),
00124 (FUNCTION_KEYS | 9),
00125 (FUNCTION_KEYS | 10),
00126 SPECIAL,
00127 SPECIAL,
00128 '7', '8', '9', '-',
00129 '4', '5', '6', '+',
00130 '1', '2', '3',
00131 '0', '.',
00132 SPECIAL,
00133 SPECIAL,
00134 SPECIAL,
00135 (FUNCTION_KEYS | 11),
00136 (FUNCTION_KEYS | 12),
00137 SPECIAL,
00138 SPECIAL,
00139 SPECIAL,
00140 SPECIAL,
00141 SPECIAL,
00142 SPECIAL,
00143 SPECIAL,
00144 SPECIAL,
00145 SPECIAL,
00146 SPECIAL,
00147 SPECIAL,
00148 SPECIAL,
00149 SPECIAL,
00150 SPECIAL,
00151 SPECIAL,
00152 SPECIAL,
00153 SPECIAL,
00154 SPECIAL,
00155 SPECIAL,
00156 SPECIAL,
00157 SPECIAL,
00158 SPECIAL,
00159 SPECIAL,
00160 SPECIAL,
00161 SPECIAL,
00162 SPECIAL,
00163 SPECIAL,
00164 SPECIAL,
00165 SPECIAL,
00166 SPECIAL,
00167 SPECIAL,
00168 SPECIAL,
00169 SPECIAL,
00170 SPECIAL,
00171 SPECIAL,
00172 SPECIAL,
00173 SPECIAL,
00174 SPECIAL,
00175 SPECIAL,
00176 };
00177
00179 static int sc_secondary_map[] = {
00180 SPECIAL,
00181 0x1b,
00182 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
00183 SPECIAL,
00184 '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
00185 SPECIAL,
00186 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"',
00187 '~',
00188 SPECIAL,
00189 '|',
00190 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
00191 SPECIAL,
00192 '*',
00193 SPECIAL,
00194 ' ',
00195 SPECIAL,
00196 SPECIAL,
00197 SPECIAL,
00198 SPECIAL,
00199 SPECIAL,
00200 SPECIAL,
00201 SPECIAL,
00202 SPECIAL,
00203 SPECIAL,
00204 SPECIAL,
00205 SPECIAL,
00206 SPECIAL,
00207 SPECIAL,
00208 '7', '8', '9', '-',
00209 '4', '5', '6', '+',
00210 '1', '2', '3',
00211 '0', '.',
00212 SPECIAL,
00213 SPECIAL,
00214 SPECIAL,
00215 SPECIAL,
00216 SPECIAL,
00217 SPECIAL,
00218 SPECIAL,
00219 SPECIAL,
00220 SPECIAL,
00221 SPECIAL,
00222 SPECIAL,
00223 SPECIAL,
00224 SPECIAL,
00225 SPECIAL,
00226 SPECIAL,
00227 SPECIAL,
00228 SPECIAL,
00229 SPECIAL,
00230 SPECIAL,
00231 SPECIAL,
00232 SPECIAL,
00233 SPECIAL,
00234 SPECIAL,
00235 SPECIAL,
00236 SPECIAL,
00237 SPECIAL,
00238 SPECIAL,
00239 SPECIAL,
00240 SPECIAL,
00241 SPECIAL,
00242 SPECIAL,
00243 SPECIAL,
00244 SPECIAL,
00245 SPECIAL,
00246 SPECIAL,
00247 SPECIAL,
00248 SPECIAL,
00249 SPECIAL,
00250 SPECIAL,
00251 SPECIAL,
00252 SPECIAL,
00253 SPECIAL,
00254 SPECIAL,
00255 SPECIAL,
00256 };
00257
00258 irq_cmd_t i8042_cmds[2] = {
00259 { CMD_PORT_READ_1, (void *)0x64, 0, 1 },
00260 { CMD_PORT_READ_1, (void *)0x60, 0, 2 }
00261 };
00262
00263 irq_code_t i8042_kbd = {
00264 2,
00265 i8042_cmds
00266 };
00267
00268 static void key_released(keybuffer_t *keybuffer, unsigned char key)
00269 {
00270 switch (key) {
00271 case SC_LSHIFT:
00272 case SC_RSHIFT:
00273 keyflags &= ~PRESSED_SHIFT;
00274 break;
00275 case SC_CAPSLOCK:
00276 keyflags &= ~PRESSED_CAPSLOCK;
00277 if (lockflags & LOCKED_CAPSLOCK)
00278 lockflags &= ~LOCKED_CAPSLOCK;
00279 else
00280 lockflags |= LOCKED_CAPSLOCK;
00281 break;
00282 default:
00283 break;
00284 }
00285 }
00286
00287 static void key_pressed(keybuffer_t *keybuffer, unsigned char key)
00288 {
00289 int *map = sc_primary_map;
00290 int ascii = sc_primary_map[key];
00291 int shift, capslock;
00292 int letter = 0;
00293
00294 static int esc_count=0;
00295
00296
00297 if ( key == SC_ESC ) {
00298 esc_count++;
00299 if ( esc_count == 3 ) {
00300 __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
00301 }
00302 } else {
00303 esc_count=0;
00304 }
00305
00306
00307
00308 switch (key) {
00309 case SC_LSHIFT:
00310 case SC_RSHIFT:
00311 keyflags |= PRESSED_SHIFT;
00312 break;
00313 case SC_CAPSLOCK:
00314 keyflags |= PRESSED_CAPSLOCK;
00315 break;
00316 case SC_SPEC_ESCAPE:
00317 break;
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 default:
00369 letter = ((ascii >= 'a') && (ascii <= 'z'));
00370 capslock = (keyflags & PRESSED_CAPSLOCK) || (lockflags & LOCKED_CAPSLOCK);
00371 shift = keyflags & PRESSED_SHIFT;
00372 if (letter && capslock)
00373 shift = !shift;
00374 if (shift)
00375 map = sc_secondary_map;
00376 if (map[key] != SPECIAL)
00377 keybuffer_push(keybuffer, map[key]);
00378 break;
00379 }
00380 }
00381
00382
00383 static void wait_ready(void) {
00384 while (i8042_status_read() & i8042_INPUT_FULL)
00385 ;
00386 }
00387
00391 int kbd_arch_init(void)
00392 {
00393 int i;
00394 int mouseenabled = 0;
00395
00396 iospace_enable(task_get_id(),(void *)i8042_DATA, 5);
00397
00398 i8042_command_write(i8042_CMD_KBD);
00399 wait_ready();
00400 i8042_command_write(i8042_CMD_KBD);
00401 wait_ready();
00402 i8042_data_write(i8042_KBD_DISABLE);
00403 wait_ready();
00404
00405
00406 while (i8042_status_read() & i8042_OUTPUT_FULL)
00407 i8042_data_read();
00408
00409 i8042_command_write(i8042_CMD_MOUSE);
00410 wait_ready();
00411 i8042_data_write(MOUSE_OUT_INIT);
00412 wait_ready();
00413
00414 int mouseanswer = 0;
00415 for (i=0;i < 1000; i++) {
00416 int status = i8042_status_read();
00417 if (status & i8042_OUTPUT_FULL) {
00418 int data = i8042_data_read();
00419 if (status & i8042_MOUSE_DATA) {
00420 mouseanswer = data;
00421 break;
00422 }
00423 }
00424 usleep(1000);
00425 }
00426 if (mouseanswer == MOUSE_ACK) {
00427
00428 mouseenabled = 1;
00429
00430 ipc_register_irq(MOUSE_IRQ, &i8042_kbd);
00431 }
00432
00433 ipc_register_irq(KBD_IRQ, &i8042_kbd);
00434
00435 ipc_register_irq(IPC_IRQ_KBDRESTART, NULL);
00436
00437 int newcontrol = i8042_KBD_IE | i8042_KBD_TRANSLATE;
00438 if (mouseenabled)
00439 newcontrol |= i8042_MOUSE_IE;
00440
00441 i8042_command_write(i8042_CMD_KBD);
00442 wait_ready();
00443 i8042_data_write(newcontrol);
00444 wait_ready();
00445
00446 return 0;
00447 }
00448
00450 int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
00451 {
00452 int status = IPC_GET_ARG1(*call);
00453
00454 if (IPC_GET_METHOD(*call) == IPC_IRQ_KBDRESTART) {
00455 kbd_arch_init();
00456 return 1;
00457 }
00458
00459 if ((status & i8042_MOUSE_DATA))
00460 return 0;
00461
00462 int scan_code = IPC_GET_ARG2(*call);
00463
00464 if (scan_code != IGNORE_CODE) {
00465 if (scan_code & KEY_RELEASE)
00466 key_released(keybuffer, scan_code ^ KEY_RELEASE);
00467 else
00468 key_pressed(keybuffer, scan_code);
00469 }
00470 return 1;
00471 }
00472