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
00035 #include <genarch/i8042/i8042.h>
00036 #include <arch/drivers/i8042.h>
00037 #include <arch/interrupt.h>
00038 #include <cpu.h>
00039 #include <arch/asm.h>
00040 #include <arch.h>
00041 #include <synch/spinlock.h>
00042 #include <typedefs.h>
00043 #include <console/chardev.h>
00044 #include <console/console.h>
00045 #include <macros.h>
00046 #include <interrupt.h>
00047
00054 #define KBD_ENABLE 0xf4
00055 #define KBD_DISABLE 0xf5
00056 #define KBD_ACK 0xfa
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #define i8042_SET_COMMAND 0x60
00074 #define i8042_COMMAND 0x49
00075
00076 #define i8042_BUFFER_FULL_MASK 0x01
00077 #define i8042_WAIT_MASK 0x02
00078
00079 #define SPECIAL '?'
00080 #define KEY_RELEASE 0x80
00081
00085 #define IGNORE_CODE 0x7f
00086
00087 static void key_released(__u8 sc);
00088 static void key_pressed(__u8 sc);
00089 static char key_read(chardev_t *d);
00090
00091 #define PRESSED_SHIFT (1<<0)
00092 #define PRESSED_CAPSLOCK (1<<1)
00093 #define LOCKED_CAPSLOCK (1<<0)
00094
00095 #define ACTIVE_READ_BUFF_SIZE 16
00096
00097 static __u8 active_read_buff[ACTIVE_READ_BUFF_SIZE];
00098
00099 SPINLOCK_INITIALIZE(keylock);
00100 static volatile int keyflags;
00101 static volatile int lockflags;
00103 static void i8042_suspend(chardev_t *);
00104 static void i8042_resume(chardev_t *);
00105
00106 static chardev_t kbrd;
00107 static chardev_operations_t ops = {
00108 .suspend = i8042_suspend,
00109 .resume = i8042_resume,
00110 .read = key_read
00111 };
00112
00114 static char sc_primary_map[] = {
00115 SPECIAL,
00116 SPECIAL,
00117 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
00118 '\b',
00119 '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
00120 SPECIAL,
00121 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'',
00122 '`',
00123 SPECIAL,
00124 '\\',
00125 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
00126 SPECIAL,
00127 '*',
00128 SPECIAL,
00129 ' ',
00130 SPECIAL,
00131 SPECIAL,
00132 SPECIAL,
00133 SPECIAL,
00134 SPECIAL,
00135 SPECIAL,
00136 SPECIAL,
00137 SPECIAL,
00138 SPECIAL,
00139 SPECIAL,
00140 SPECIAL,
00141 SPECIAL,
00142 SPECIAL,
00143 '7', '8', '9', '-',
00144 '4', '5', '6', '+',
00145 '1', '2', '3',
00146 '0', '.',
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 SPECIAL,
00177 SPECIAL,
00178 SPECIAL,
00179 SPECIAL,
00180 SPECIAL,
00181 SPECIAL,
00182 SPECIAL,
00183 SPECIAL,
00184 SPECIAL,
00185 SPECIAL,
00186 SPECIAL,
00187 SPECIAL,
00188 SPECIAL,
00189 SPECIAL,
00190 SPECIAL,
00191 };
00192
00194 static char sc_secondary_map[] = {
00195 SPECIAL,
00196 SPECIAL,
00197 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
00198 SPECIAL,
00199 '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
00200 SPECIAL,
00201 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"',
00202 '~',
00203 SPECIAL,
00204 '|',
00205 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
00206 SPECIAL,
00207 '*',
00208 SPECIAL,
00209 ' ',
00210 SPECIAL,
00211 SPECIAL,
00212 SPECIAL,
00213 SPECIAL,
00214 SPECIAL,
00215 SPECIAL,
00216 SPECIAL,
00217 SPECIAL,
00218 SPECIAL,
00219 SPECIAL,
00220 SPECIAL,
00221 SPECIAL,
00222 SPECIAL,
00223 '7', '8', '9', '-',
00224 '4', '5', '6', '+',
00225 '1', '2', '3',
00226 '0', '.',
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 SPECIAL,
00257 SPECIAL,
00258 SPECIAL,
00259 SPECIAL,
00260 SPECIAL,
00261 SPECIAL,
00262 SPECIAL,
00263 SPECIAL,
00264 SPECIAL,
00265 SPECIAL,
00266 SPECIAL,
00267 SPECIAL,
00268 SPECIAL,
00269 SPECIAL,
00270 SPECIAL,
00271 };
00272
00273 static void i8042_interrupt(int n, istate_t *istate);
00274 static void i8042_wait(void);
00275
00276 static iroutine oldvector;
00278 void i8042_grab(void)
00279 {
00280 oldvector = exc_register(VECTOR_KBD, "i8042_interrupt", (iroutine) i8042_interrupt);
00281 i8042_wait();
00282 i8042_command_write(i8042_SET_COMMAND);
00283 i8042_wait();
00284 i8042_data_write(i8042_COMMAND);
00285 i8042_wait();
00286 }
00288 void i8042_release(void)
00289 {
00290 if (oldvector)
00291 exc_register(VECTOR_KBD, "user_interrupt", oldvector);
00292 }
00293
00295 void i8042_init(void)
00296 {
00297 int i;
00298
00299 i8042_grab();
00300
00301
00302
00303 oldvector = NULL;
00304
00305 trap_virtual_enable_irqs(1<<IRQ_KBD);
00306 chardev_initialize("i8042_kbd", &kbrd, &ops);
00307 stdin = &kbrd;
00308
00309
00310
00311
00312
00313 for (i = 0; (i8042_status_read() & i8042_BUFFER_FULL_MASK) && i < 100; i++) {
00314 i8042_data_read();
00315 }
00316 }
00317
00323 void i8042_interrupt(int n, istate_t *istate)
00324 {
00325 __u8 x;
00326
00327 trap_virtual_eoi();
00328 x = i8042_data_read();
00329 if (x & KEY_RELEASE)
00330 key_released(x ^ KEY_RELEASE);
00331 else
00332 key_pressed(x);
00333 }
00334
00336 void i8042_wait(void) {
00337 while (i8042_status_read() & i8042_WAIT_MASK) {
00338
00339 }
00340 }
00341
00346 void key_released(__u8 sc)
00347 {
00348 spinlock_lock(&keylock);
00349 switch (sc) {
00350 case SC_LSHIFT:
00351 case SC_RSHIFT:
00352 keyflags &= ~PRESSED_SHIFT;
00353 break;
00354 case SC_CAPSLOCK:
00355 keyflags &= ~PRESSED_CAPSLOCK;
00356 if (lockflags & LOCKED_CAPSLOCK)
00357 lockflags &= ~LOCKED_CAPSLOCK;
00358 else
00359 lockflags |= LOCKED_CAPSLOCK;
00360 break;
00361 default:
00362 break;
00363 }
00364 spinlock_unlock(&keylock);
00365 }
00366
00371 void key_pressed(__u8 sc)
00372 {
00373 char *map = sc_primary_map;
00374 char ascii = sc_primary_map[sc];
00375 bool shift, capslock;
00376 bool letter = false;
00377
00378 spinlock_lock(&keylock);
00379 switch (sc) {
00380 case SC_LSHIFT:
00381 case SC_RSHIFT:
00382 keyflags |= PRESSED_SHIFT;
00383 break;
00384 case SC_CAPSLOCK:
00385 keyflags |= PRESSED_CAPSLOCK;
00386 break;
00387 case SC_SPEC_ESCAPE:
00388 break;
00389 case SC_LEFTARR:
00390 chardev_push_character(&kbrd, 0x1b);
00391 chardev_push_character(&kbrd, 0x5b);
00392 chardev_push_character(&kbrd, 0x44);
00393 break;
00394 case SC_RIGHTARR:
00395 chardev_push_character(&kbrd, 0x1b);
00396 chardev_push_character(&kbrd, 0x5b);
00397 chardev_push_character(&kbrd, 0x43);
00398 break;
00399 case SC_UPARR:
00400 chardev_push_character(&kbrd, 0x1b);
00401 chardev_push_character(&kbrd, 0x5b);
00402 chardev_push_character(&kbrd, 0x41);
00403 break;
00404 case SC_DOWNARR:
00405 chardev_push_character(&kbrd, 0x1b);
00406 chardev_push_character(&kbrd, 0x5b);
00407 chardev_push_character(&kbrd, 0x42);
00408 break;
00409 case SC_HOME:
00410 chardev_push_character(&kbrd, 0x1b);
00411 chardev_push_character(&kbrd, 0x4f);
00412 chardev_push_character(&kbrd, 0x48);
00413 break;
00414 case SC_END:
00415 chardev_push_character(&kbrd, 0x1b);
00416 chardev_push_character(&kbrd, 0x4f);
00417 chardev_push_character(&kbrd, 0x46);
00418 break;
00419 case SC_DELETE:
00420 chardev_push_character(&kbrd, 0x1b);
00421 chardev_push_character(&kbrd, 0x5b);
00422 chardev_push_character(&kbrd, 0x33);
00423 chardev_push_character(&kbrd, 0x7e);
00424 break;
00425 default:
00426 letter = is_lower(ascii);
00427 capslock = (keyflags & PRESSED_CAPSLOCK) || (lockflags & LOCKED_CAPSLOCK);
00428 shift = keyflags & PRESSED_SHIFT;
00429 if (letter && capslock)
00430 shift = !shift;
00431 if (shift)
00432 map = sc_secondary_map;
00433 chardev_push_character(&kbrd, map[sc]);
00434 break;
00435 }
00436 spinlock_unlock(&keylock);
00437 }
00438
00439
00440 void i8042_resume(chardev_t *d)
00441 {
00442 }
00443
00444
00445 void i8042_suspend(chardev_t *d)
00446 {
00447 }
00448
00449 static __u8 active_read_buff_read(void)
00450 {
00451 static int i=0;
00452 i &= (ACTIVE_READ_BUFF_SIZE-1);
00453 if(!active_read_buff[i]) {
00454 return 0;
00455 }
00456 return active_read_buff[i++];
00457 }
00458
00459 static void active_read_buff_write(__u8 ch)
00460 {
00461 static int i=0;
00462 active_read_buff[i] = ch;
00463 i++;
00464 i &= (ACTIVE_READ_BUFF_SIZE-1);
00465 active_read_buff[i]=0;
00466 }
00467
00468
00469 static void active_read_key_pressed(__u8 sc)
00470 {
00471 char *map = sc_primary_map;
00472 char ascii = sc_primary_map[sc];
00473 bool shift, capslock;
00474 bool letter = false;
00475
00476
00477 switch (sc) {
00478 case SC_LSHIFT:
00479 case SC_RSHIFT:
00480 keyflags |= PRESSED_SHIFT;
00481 break;
00482 case SC_CAPSLOCK:
00483 keyflags |= PRESSED_CAPSLOCK;
00484 break;
00485 case SC_SPEC_ESCAPE:
00486 break;
00487 case SC_LEFTARR:
00488 active_read_buff_write(0x1b);
00489 active_read_buff_write(0x5b);
00490 active_read_buff_write(0x44);
00491 break;
00492 case SC_RIGHTARR:
00493 active_read_buff_write(0x1b);
00494 active_read_buff_write(0x5b);
00495 active_read_buff_write(0x43);
00496 break;
00497 case SC_UPARR:
00498 active_read_buff_write(0x1b);
00499 active_read_buff_write(0x5b);
00500 active_read_buff_write(0x41);
00501 break;
00502 case SC_DOWNARR:
00503 active_read_buff_write(0x1b);
00504 active_read_buff_write(0x5b);
00505 active_read_buff_write(0x42);
00506 break;
00507 case SC_HOME:
00508 active_read_buff_write(0x1b);
00509 active_read_buff_write(0x4f);
00510 active_read_buff_write(0x48);
00511 break;
00512 case SC_END:
00513 active_read_buff_write(0x1b);
00514 active_read_buff_write(0x4f);
00515 active_read_buff_write(0x46);
00516 break;
00517 case SC_DELETE:
00518 active_read_buff_write(0x1b);
00519 active_read_buff_write(0x5b);
00520 active_read_buff_write(0x33);
00521 active_read_buff_write(0x7e);
00522 break;
00523 default:
00524 letter = is_lower(ascii);
00525 capslock = (keyflags & PRESSED_CAPSLOCK) || (lockflags & LOCKED_CAPSLOCK);
00526 shift = keyflags & PRESSED_SHIFT;
00527 if (letter && capslock)
00528 shift = !shift;
00529 if (shift)
00530 map = sc_secondary_map;
00531 active_read_buff_write(map[sc]);
00532 break;
00533 }
00534
00535
00536 }
00537
00538 static char key_read(chardev_t *d)
00539 {
00540 char ch;
00541
00542 while(!(ch = active_read_buff_read())) {
00543 __u8 x;
00544 while (!((x=i8042_status_read() & i8042_BUFFER_FULL_MASK)))
00545 ;
00546 x = i8042_data_read();
00547 if (x != IGNORE_CODE) {
00548 if (x & KEY_RELEASE)
00549 key_released(x ^ KEY_RELEASE);
00550 else
00551 active_read_key_pressed(x);
00552 }
00553 }
00554 return ch;
00555 }
00556
00561 void i8042_poll(void)
00562 {
00563 __u8 x;
00564
00565 while (((x = i8042_status_read() & i8042_BUFFER_FULL_MASK))) {
00566 x = i8042_data_read();
00567 if (x != IGNORE_CODE) {
00568 if (x & KEY_RELEASE)
00569 key_released(x ^ KEY_RELEASE);
00570 else
00571 key_pressed(x);
00572 }
00573 }
00574 }
00575