diff options
Diffstat (limited to 'c/src/lib/libbsp/i386/pc386/console/pc_keyb.c')
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/console/pc_keyb.c | 627 |
1 files changed, 0 insertions, 627 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/console/pc_keyb.c b/c/src/lib/libbsp/i386/pc386/console/pc_keyb.c deleted file mode 100644 index b6f0eb216a..0000000000 --- a/c/src/lib/libbsp/i386/pc386/console/pc_keyb.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * linux/drivers/char/pc_keyb.c - * - * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 - * See keyboard.c for the whole history. - * - * Major cleanup by Martin Mares, May 1997 - * - * Combined the keyboard and PS/2 mouse handling into one file, - * because they share the same hardware. - * Johan Myreen <jem@iki.fi> 1998-10-08. - * - * Code fixes to handle mouse ACKs properly. - * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29. - * - * Ported to RTEMS by Rosimildo da Silva - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> - -#include <bsp.h> -#include <rtems/keyboard.h> -#include "i386kbd.h" - -static unsigned char handle_kbd_event(void); -static void kbd_write_command_w(int data); -static void kbd_write_output_w(int data); - -/* Some configuration switches are present in the include file... */ - -/* Simple translation table for the SysRq keys */ - -#ifdef CONFIG_MAGIC_SYSRQ -unsigned char pckbd_sysrq_xlate[128] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ - "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ - "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\r\000/"; /* 0x60 - 0x6f */ -#endif - -/* used only by send_data - set by keyboard_interrupt */ -static volatile unsigned char reply_expected = 0; -static volatile unsigned char acknowledge = 0; -static volatile unsigned char resend = 0; - -/* - * Translation of escaped scancodes to keycodes. - * This is now user-settable. - * The keycodes 1-88,96-111,119 are fairly standard, and - * should probably not be changed - changing might confuse X. - * X also interprets scancode 0x5d (KEY_Begin). - * - * For 1-88 keycode equals scancode. - */ - -#define E0_KPENTER 96 -#define E0_RCTRL 97 -#define E0_KPSLASH 98 -#define E0_PRSCR 99 -#define E0_RALT 100 -#define E0_BREAK 101 /* (control-pause) */ -#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 - -/* - * The keycodes below are randomly located in 89-95,112-118,120-127. - * They could be thrown away (and all occurrences below replaced by 0), - * but that would force many users to use the `setkeycodes' utility, where - * they needed not before. It does not matter that there are duplicates, as - * long as no duplication occurs for any single keyboard. - */ -#define SC_LIM 89 - -#define FOCUS_PF1 85 /* actual code! */ -#define FOCUS_PF2 89 -#define FOCUS_PF3 90 -#define FOCUS_PF4 91 -#define FOCUS_PF5 92 -#define FOCUS_PF6 93 -#define FOCUS_PF7 94 -#define FOCUS_PF8 95 -#define FOCUS_PF9 120 -#define FOCUS_PF10 121 -#define FOCUS_PF11 122 -#define FOCUS_PF12 123 - -#define JAP_86 124 -/* tfj@olivia.ping.dk: - * The four keys are located over the numeric keypad, and are - * labelled A1-A4. It's an rc930 keyboard, from - * Regnecentralen/RC International, Now ICL. - * Scancodes: 59, 5a, 5b, 5c. - */ -#define RGN1 124 -#define RGN2 125 -#define RGN3 126 -#define RGN4 127 - -static unsigned char high_keys[128 - SC_LIM] = { - RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ - 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ - 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ - FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ - FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ -}; - -/* BTC */ -#define E0_MACRO 112 -/* LK450 */ -#define E0_F13 113 -#define E0_F14 114 -#define E0_HELP 115 -#define E0_DO 116 -#define E0_F17 117 -#define E0_KPMINPLUS 118 -/* - * My OmniKey generates e0 4c for the "OMNI" key and the - * right alt key does nada. [kkoller@nyx10.cs.du.edu] - */ -#define E0_OK 124 -/* - * New microsoft keyboard is rumoured to have - * e0 5b (left window button), e0 5c (right window button), - * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] - * [or: Windows_L, Windows_R, TaskMan] - */ -#define E0_MSLW 125 -#define E0_MSRW 126 -#define E0_MSTM 127 - -static unsigned char e0_keys[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ - 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ - 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ - E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ - E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ - E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ - E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ - 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ - 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ - 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ -}; - -static void mdelay( unsigned long t ) -{ - Wait_X_ms( t ); -} - -int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) -{ - if (scancode < SC_LIM || scancode > 255 || keycode > 127) - return -EINVAL; - if (scancode < 128) - high_keys[scancode - SC_LIM] = keycode; - else - e0_keys[scancode - 128] = keycode; - return 0; -} - -int pckbd_getkeycode(unsigned int scancode) -{ - return - (scancode < SC_LIM || scancode > 255) ? -EINVAL : - (scancode < 128) ? high_keys[scancode - SC_LIM] : - e0_keys[scancode - 128]; -} - -static int do_acknowledge(unsigned char scancode) -{ - if (reply_expected) { - /* Unfortunately, we must recognise these codes only if we know they - * are known to be valid (i.e., after sending a command), because there - * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have - * keys with such codes :( - */ - if (scancode == KBD_REPLY_ACK) { - acknowledge = 1; - reply_expected = 0; - return 0; - } else if (scancode == KBD_REPLY_RESEND) { - resend = 1; - reply_expected = 0; - return 0; - } - /* Should not happen... */ - printk( "keyboard reply expected - got %02x\n", scancode); - } - return 1; -} - -int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) -{ - static int prev_scancode = 0; - - /* special prefix scancodes.. */ - if (scancode == 0xe0 || scancode == 0xe1) { - prev_scancode = scancode; - return 0; - } - - /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ - if (scancode == 0x00 || scancode == 0xff) { - prev_scancode = 0; - return 0; - } - - scancode &= 0x7f; - - if (prev_scancode) { - /* - * usually it will be 0xe0, but a Pause key generates - * e1 1d 45 e1 9d c5 when pressed, and nothing when released - */ - if (prev_scancode != 0xe0) { - if (prev_scancode == 0xe1 && scancode == 0x1d) { - prev_scancode = 0x100; - return 0; - } else if (prev_scancode == 0x100 && scancode == 0x45) { - *keycode = E1_PAUSE; - prev_scancode = 0; - } else { -#ifdef KBD_REPORT_UNKN - if (!raw_mode) - printk("keyboard: unknown e1 escape sequence\n"); -#endif - prev_scancode = 0; - return 0; - } - } else { - prev_scancode = 0; - /* - * The keyboard maintains its own internal caps lock and - * num lock statuses. In caps lock mode E0 AA precedes make - * code and E0 2A follows break code. In num lock mode, - * E0 2A precedes make code and E0 AA follows break code. - * We do our own book-keeping, so we will just ignore these. - */ - /* - * For my keyboard there is no caps lock mode, but there are - * both Shift-L and Shift-R modes. The former mode generates - * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. - * So, we should also ignore the latter. - aeb@cwi.nl - */ - if (scancode == 0x2a || scancode == 0x36) - return 0; - - if (e0_keys[scancode]) - *keycode = e0_keys[scancode]; - else { -#ifdef KBD_REPORT_UNKN - if (!raw_mode) - printk( "keyboard: unknown scancode e0 %02x\n", - scancode); -#endif - return 0; - } - } - } else if (scancode >= SC_LIM) { - /* This happens with the FOCUS 9000 keyboard - Its keys PF1..PF12 are reported to generate - 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f - Moreover, unless repeated, they do not generate - key-down events, so we have to zero up_flag below */ - /* Also, Japanese 86/106 keyboards are reported to - generate 0x73 and 0x7d for \ - and \ | respectively. */ - /* Also, some Brazilian keyboard is reported to produce - 0x73 and 0x7e for \ ? and KP-dot, respectively. */ - - *keycode = high_keys[scancode - SC_LIM]; - if (!*keycode) { - if (!raw_mode) { -#ifdef KBD_REPORT_UNKN - printk( "keyboard: unrecognized scancode (%02x)" - " - ignored\n", scancode); -#endif - } - return 0; - } - } else - *keycode = scancode; - return 1; -} - -char pckbd_unexpected_up(unsigned char keycode) -{ - /* unexpected, but this can happen: maybe this was a key release for a - FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ - if (keycode >= SC_LIM || keycode == 85) - return 0; - else - return 0200; -} - -static void kb_wait(void) -{ - unsigned long timeout = KBC_TIMEOUT; - - do { - /* - * "handle_kbd_event()" will handle any incoming events - * while we wait - keypresses or mouse movement. - */ - unsigned char status = handle_kbd_event(); - - if (! (status & KBD_STAT_IBF)) - return; - mdelay(1); - timeout--; - } while (timeout); -#ifdef KBD_REPORT_TIMEOUTS - printk( "Keyboard timed out[1]\n"); -#endif -} - -/* - * This reads the keyboard status port, and does the - * appropriate action. - * - * It requires that we hold the keyboard controller - * spinlock. - */ -static unsigned char handle_kbd_event(void) -{ - unsigned char status = kbd_read_status(); - unsigned int work = 10000; - - while (status & KBD_STAT_OBF) { - unsigned char scancode; - - scancode = kbd_read_input(); - if (status & KBD_STAT_MOUSE_OBF) { -#if 0 - handle_mouse_event(scancode); -#endif - } else { - if (do_acknowledge(scancode)) - handle_scancode(scancode, !(scancode & 0x80)); - mark_bh(KEYBOARD_BH); - } - - status = kbd_read_status(); - - if(!work--) - { - printk( "pc_keyb: controller jammed (0x%02X).\n", status); - break; - } - return status; - } - - /* - * the commands to set the leds for some reason, returns 0x14, 0x16 - * and I am intepreting as an ACK, because the original code from - * Linux was timeing out here... - */ - acknowledge = 1; - reply_expected = 0; - resend = 0; - return status; -} - -void keyboard_interrupt(void *unused) -{ - handle_kbd_event(); -} - -/* - * send_data sends a character to the keyboard and waits - * for an acknowledge, possibly retrying if asked to. Returns - * the success status. - * - * Don't use 'jiffies', so that we don't depend on interrupts - */ -static int send_data(unsigned char data) -{ - int retries = 3; - - do { - unsigned long timeout = KBD_TIMEOUT; - - acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */ - resend = 0; - reply_expected = 1; - kbd_write_output_w(data); - for (;;) { - if (acknowledge) - return 1; - if (resend) - break; - mdelay(1); - if (!--timeout) { -#ifdef KBD_REPORT_TIMEOUTS - printk("Keyboard timeout[2]\n"); -#endif - return 0; - } - } - } while (retries-- > 0); -#ifdef KBD_REPORT_TIMEOUTS - printk( "keyboard: Too many NACKs -- noisy kbd cable?\n"); -#endif - return 0; -} - -void pckbd_leds(unsigned char leds) -{ - if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds)) - send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ -} - -/* - * In case we run on a non-x86 hardware we need to initialize both the - * keyboard controller and the keyboard. On a x86, the BIOS will - * already have initialized them. - * - * Some x86 BIOSes do not correctly initialize the keyboard, so the - * "kbd-reset" command line options can be given to force a reset. - * [Ranger] - */ -#ifdef __i386__ - int kbd_startup_reset = 0; -#else - int kbd_startup_reset = 1; -#endif - -/* for "kbd-reset" cmdline param */ -void kbd_reset_setup(char *str, int *ints) -{ - kbd_startup_reset = 1; -} - -#define KBD_NO_DATA (-1) /* No data */ -#define KBD_BAD_DATA (-2) /* Parity or other error */ - -static int kbd_read_data(void) -{ - int retval = KBD_NO_DATA; - unsigned char status; - - status = kbd_read_status(); - if (status & KBD_STAT_OBF) { - unsigned char data = kbd_read_input(); - - retval = data; - if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) - retval = KBD_BAD_DATA; - } - return retval; -} - -static void kbd_clear_input(void) -{ - int maxread = 100; /* Random number */ - - do { - if (kbd_read_data() == KBD_NO_DATA) - break; - } while (--maxread); -} - -static int kbd_wait_for_input(void) -{ - long timeout = KBD_INIT_TIMEOUT; - - do { - int retval = kbd_read_data(); - if (retval >= 0) - return retval; - mdelay(1); - } while (--timeout); - return -1; -} - -static void kbd_write_command_w(int data) -{ - kb_wait(); - kbd_write_command(data); -} - -static void kbd_write_output_w(int data) -{ - kb_wait(); - kbd_write_output(data); -} - -static char * initialize_kbd(void) -{ - int status; - - /* - * Test the keyboard interface. - * This seems to be the only way to get it going. - * If the test is successful a x55 is placed in the input buffer. - */ - kbd_write_command_w(KBD_CCMD_SELF_TEST); - if (kbd_wait_for_input() != 0x55) - return "Keyboard failed self test"; - - /* - * Perform a keyboard interface test. This causes the controller - * to test the keyboard clock and data lines. The results of the - * test are placed in the input buffer. - */ - kbd_write_command_w(KBD_CCMD_KBD_TEST); - if (kbd_wait_for_input() != 0x00) - return "Keyboard interface failed self test"; - - /* - * Enable the keyboard by allowing the keyboard clock to run. - */ - kbd_write_command_w(KBD_CCMD_KBD_ENABLE); - - /* - * Reset keyboard. If the read times out - * then the assumption is that no keyboard is - * plugged into the machine. - * This defaults the keyboard to scan-code set 2. - * - * Set up to try again if the keyboard asks for RESEND. - */ - do { - kbd_write_output_w(KBD_CMD_RESET); - status = kbd_wait_for_input(); - if (status == KBD_REPLY_ACK) - break; - if (status != KBD_REPLY_RESEND) - return "Keyboard reset failed, no ACK"; - } while (1); - - if (kbd_wait_for_input() != KBD_REPLY_POR) - return "Keyboard reset failed, no POR"; - - /* - * Set keyboard controller mode. During this, the keyboard should be - * in the disabled state. - * - * Set up to try again if the keyboard asks for RESEND. - */ - do { - kbd_write_output_w(KBD_CMD_DISABLE); - status = kbd_wait_for_input(); - if (status == KBD_REPLY_ACK) - break; - if (status != KBD_REPLY_RESEND) - return "Disable keyboard: no ACK"; - } while (1); - - kbd_write_command_w(KBD_CCMD_WRITE_MODE); - kbd_write_output_w(KBD_MODE_KBD_INT - | KBD_MODE_SYS - | KBD_MODE_DISABLE_MOUSE - | KBD_MODE_KCC); - - /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ - kbd_write_command_w(KBD_CCMD_READ_MODE); - if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { - /* - * If the controller does not support conversion, - * Set the keyboard to scan-code set 1. - */ - kbd_write_output_w(0xF0); - kbd_wait_for_input(); - kbd_write_output_w(0x01); - kbd_wait_for_input(); - } - - kbd_write_output_w(KBD_CMD_ENABLE); - if (kbd_wait_for_input() != KBD_REPLY_ACK) - return "Enable keyboard: no ACK"; - /* - * Finally, set the typematic rate to maximum. - */ - kbd_write_output_w(KBD_CMD_SET_RATE); - if (kbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; - kbd_write_output_w(0x00); - if (kbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; - return NULL; -} - -void pckbd_init_hw(void) -{ - /* kbd_request_region(); */ - - /* Flush any pending input. */ - kbd_clear_input(); - - if (kbd_startup_reset) { - char *msg = initialize_kbd(); - if (msg) - printk( "initialize_kbd: %s\n", msg); - } - -#if defined CONFIG_PSMOUSE - psaux_init(); -#endif - - /* Ok, finally allocate the IRQ, and off we go.. */ -#if 0 - kbd_request_irq( keyboard_interrupt ); -#endif - -} |