From 74708d31cecf6129ed2ba2f058d92f47c0abdd48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 30 Sep 2002 01:43:28 +0000 Subject: [PATCH] Cleaned up the code, merged _keyboard_read() and keyboard_read(), and merged setup_keyboard() and init_driver(). Added TRACE_KEYBOARD define to easily enable debug output from the keyboard driver. Also made the escape key dropping into KDL - all special keys (like the F-keys, etc.) aren't working in BeBochs, so that's a simple work-around for that problem. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1302 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/arch/x86/keyboard/keyboard.c | 358 ++++++++++-------- 1 file changed, 198 insertions(+), 160 deletions(-) diff --git a/src/add-ons/kernel/drivers/arch/x86/keyboard/keyboard.c b/src/add-ons/kernel/drivers/arch/x86/keyboard/keyboard.c index ea2b4d4111..86f0af57f0 100644 --- a/src/add-ons/kernel/drivers/arch/x86/keyboard/keyboard.c +++ b/src/add-ons/kernel/drivers/arch/x86/keyboard/keyboard.c @@ -18,26 +18,44 @@ #define DEVICE_NAME "keyboard" -#define LSHIFT 42 -#define RSHIFT 54 -#define SCRLOCK 70 -#define NUMLOCK 69 -#define CAPS 58 -#define SYSREQ 55 -#define F11 87 -#define F12 88 +#define TRACE_KEYBOARD 0 +#if TRACE_KEYBOARD +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif -#define LED_SCROLL 1 -#define LED_NUM 2 -#define LED_CAPS 4 + +enum keycodes { + ESCAPE = 1, + + LSHIFT = 42, + RSHIFT = 54, + CAPS_LOCK = 58, + NUM_LOCK = 69, + SCR_LOCK = 70, + SYS_REQ = 55, + + F1 = 0x3b, + F2, F3, F4, F5, F6, + F7, F8, F9, F10, + + F11 = 87, + F12 = 88, +}; + +#define LED_SCROLL 1 +#define LED_NUM 2 +#define LED_CAPS 4 + +int32 api_version = B_CUR_DRIVER_API_VERSION; static bool shift; -static int leds; +static int leds; static sem_id keyboard_sem; static mutex keyboard_read_mutex; static char keyboard_buf[1024]; static unsigned int head, tail; -int32 api_version = B_CUR_DRIVER_API_VERSION; // stolen from nujeffos const char unshifted_keymap[128] = { @@ -73,13 +91,15 @@ const char caps_keymap[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static void wait_for_output(void) { - while(in8(0x64) & 0x2) + while (in8(0x64) & 0x2) ; } + static void set_leds(void) { @@ -89,59 +109,6 @@ set_leds(void) out8(leds, 0x60); } -static ssize_t -_keyboard_read(void *_buf, size_t len) -{ - unsigned int saved_tail; - char *buf = _buf; - size_t copied_bytes = 0; - size_t copy_len; - int rc; - - if(len > sizeof(keyboard_buf) - 1) - len = sizeof(keyboard_buf) - 1; - -retry: - // block here until data is ready - rc = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0); - if(rc == EINTR) { - return 0; - } - - // critical section - mutex_lock(&keyboard_read_mutex); - - saved_tail = tail; - if(head == saved_tail) { - mutex_unlock(&keyboard_read_mutex); - goto retry; - } else { - // copy out of the buffer - if(head < saved_tail) - copy_len = min(len, saved_tail - head); - else - copy_len = min(len, sizeof(keyboard_buf) - head); - memcpy(buf, &keyboard_buf[head], copy_len); - copied_bytes = copy_len; - head = (head + copy_len) % sizeof(keyboard_buf); - if(head == 0 && saved_tail > 0 && copied_bytes < len) { - // we wrapped around and have more bytes to read - // copy the first part of the buffer - copy_len = min(saved_tail, len - copied_bytes); - memcpy(&buf[len], &keyboard_buf[0], copy_len); - copied_bytes += copy_len; - head = copy_len; - } - } - if(head != saved_tail) { - // we did not empty the keyboard queue - release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE); - } - - mutex_unlock(&keyboard_read_mutex); - - return copied_bytes; -} static void insert_in_buf(char c) @@ -151,7 +118,7 @@ insert_in_buf(char c) // see if the next char will collide with the head temp_tail++; temp_tail %= sizeof(keyboard_buf); - if(temp_tail == head) { + if (temp_tail == head) { // buffer overflow, ditch this char return; } @@ -160,127 +127,197 @@ insert_in_buf(char c) release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE); } + static int32 -handle_keyboard_interrupt(void* data) +handle_keyboard_interrupt(void *data) { unsigned char key; int32 retval = B_HANDLED_INTERRUPT; key = in8(0x60); -// dprintf("handle_keyboard_interrupt: key = 0x%x\n", key); + TRACE(("handle_keyboard_interrupt: key = 0x%x\n", key)); - if(key & 0x80) { - // keyup - if(key == LSHIFT + 0x80 || key == RSHIFT + 0x80) + if (key & 0x80) { + // key up + if (key == LSHIFT + 0x80 || key == RSHIFT + 0x80) shift = false; - } else { - switch(key) { - case LSHIFT: - case RSHIFT: - shift = true; - break; - case CAPS: - if(leds & LED_CAPS) - leds &= ~LED_CAPS; - else - leds |= LED_CAPS; - set_leds(); - break; - case SCRLOCK: - if(leds & LED_SCROLL) { - leds &= ~LED_SCROLL; - dbg_set_serial_debug(false); - } else { - leds |= LED_SCROLL; - dbg_set_serial_debug(true); - } - set_leds(); - break; - case NUMLOCK: - if(leds & LED_NUM) - leds &= ~LED_NUM; - else - leds |= LED_NUM; - set_leds(); - break; - case SYSREQ: - panic("Keyboard Requested Halt\n"); - break; - case F11: - dbg_set_serial_debug(dbg_get_serial_debug()?false:true); - break; - case F12: - reboot(); - break; - default: { - char ascii; - if(shift) - ascii = shifted_keymap[key]; - else - if (leds & LED_CAPS) - ascii = caps_keymap[key]; - else - ascii = unshifted_keymap[key]; + return B_HANDLED_INTERRUPT; + } -// dprintf("ascii = 0x%x, '%c'\n", ascii, ascii); - if(ascii != 0) { - insert_in_buf(ascii); - retval = B_INVOKE_SCHEDULER; - } else { -// dprintf("keyboard: unknown scan-code 0x%x\n",key); - } + switch (key) { + case LSHIFT: + case RSHIFT: + shift = true; + break; + case CAPS_LOCK: + if (leds & LED_CAPS) + leds &= ~LED_CAPS; + else + leds |= LED_CAPS; + set_leds(); + break; + case SCR_LOCK: + if (leds & LED_SCROLL) { + leds &= ~LED_SCROLL; + dbg_set_serial_debug(false); + } else { + leds |= LED_SCROLL; + dbg_set_serial_debug(true); } + set_leds(); + break; + case NUM_LOCK: + if (leds & LED_NUM) + leds &= ~LED_NUM; + else + leds |= LED_NUM; + set_leds(); + break; + + /* the following code has two possibilities because of issues + * with BeBochs & BeOS (all special keys don't map to anything + * useful, and SYS_REQ does a screen dump in BeOS). + * ToDo: remove these key functions some day... + */ + case ESCAPE: + case SYS_REQ: + panic("Keyboard Requested Halt\n"); + break; + case F11: + dbg_set_serial_debug(dbg_get_serial_debug() ? false : true); + break; + case F12: + reboot(); + break; + + default: { + char ascii; + + if (shift) + ascii = shifted_keymap[key]; + else { + if (leds & LED_CAPS) + ascii = caps_keymap[key]; + else + ascii = unshifted_keymap[key]; + } + + TRACE(("ascii = 0x%x, '%c'\n", ascii, ascii)); + + if (ascii != 0) { + insert_in_buf(ascii); + retval = B_INVOKE_SCHEDULER; + } else + TRACE(("keyboard: unknown scan-code 0x%x\n", key)); } } + return retval; } + static status_t -keyboard_open(const char *name, uint32 flags, void * *cookie) +keyboard_open(const char *name, uint32 flags, void **cookie) { *cookie = NULL; return 0; } -static status_t -keyboard_close(void * cookie) -{ - return 0; -} static status_t -keyboard_freecookie(void * cookie) +keyboard_close(void *cookie) { return 0; } -static ssize_t -keyboard_read(void * cookie, off_t pos, void *buf, size_t *len) -{ - int rv; - if (*len < 0) - return 0; - rv = _keyboard_read(buf, *len); - if (rv < 0) - return rv; - *len = rv; +static status_t +keyboard_freecookie(void *cookie) +{ return 0; } -static ssize_t -keyboard_write(void * cookie, off_t pos, const void *buf, size_t *len) + +static status_t +keyboard_read(void *cookie, off_t pos, void *buffer, size_t *_length) +{ + unsigned int savedTail; + size_t length = *_length; + size_t copiedBytes = 0; + int status; + + if (length < 0) { + *_length = 0; + return B_OK; + } + + if (length > sizeof(keyboard_buf) - 1) + length = sizeof(keyboard_buf) - 1; + +retry: + // block here until data is ready + status = acquire_sem_etc(keyboard_sem, 1, B_CAN_INTERRUPT, 0); + if (status == B_INTERRUPTED) { + *_length = 0; + return B_OK; + } + + // critical section + mutex_lock(&keyboard_read_mutex); + + savedTail = tail; + if (head == savedTail) { + // buffer queue is empty + mutex_unlock(&keyboard_read_mutex); + goto retry; + } else { + size_t copyLength; + + // copy out of the buffer + if (head < savedTail) + copyLength = min(length, savedTail - head); + else + copyLength = min(length, sizeof(keyboard_buf) - head); + memcpy(buffer, &keyboard_buf[head], copyLength); + copiedBytes = copyLength; + + head = (head + copyLength) % sizeof(keyboard_buf); + if (head == 0 && savedTail > 0 && copiedBytes < length) { + // we wrapped around and have more bytes to read + // copy the first part of the buffer + copyLength = min(savedTail, length - copiedBytes); + memcpy((uint8 *)buffer + length, keyboard_buf, copyLength); + copiedBytes += copyLength; + head = copyLength; + } + } + if (head != savedTail) { + // we did not empty the keyboard queue + release_sem_etc(keyboard_sem, 1, B_DO_NOT_RESCHEDULE); + } + + mutex_unlock(&keyboard_read_mutex); + + *_length = copiedBytes; + return B_OK; +} + + +static status_t +keyboard_write(void *cookie, off_t pos, const void *buf, size_t *len) { return EROFS; } + static status_t -keyboard_ioctl(void * cookie, uint32 op, void *buf, size_t len) +keyboard_ioctl(void *cookie, uint32 op, void *buf, size_t len) { return EINVAL; } + device_hooks keyboard_hooks = { &keyboard_open, &keyboard_close, @@ -294,37 +331,35 @@ device_hooks keyboard_hooks = { NULL }; -static int -setup_keyboard(void) + +/***** driver hooks *****/ + +status_t +init_hardware() { keyboard_sem = create_sem(0, "keyboard_sem"); - if(keyboard_sem < 0) + if (keyboard_sem < 0) panic("could not create keyboard sem!\n"); - if(mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0) + if (mutex_init(&keyboard_read_mutex, "keyboard_read_mutex") < 0) panic("could not create keyboard read mutex!\n"); shift = 0; leds = 0; + // have the scroll lock reflect the state of serial debugging - if(dbg_get_serial_debug()) + if (dbg_get_serial_debug()) leds |= LED_SCROLL; set_leds(); head = tail = 0; - return 0; -} - -status_t -init_hardware() -{ - setup_keyboard(); install_io_interrupt_handler(0x01, &handle_keyboard_interrupt, NULL, 0); return 0; } + const char ** publish_devices(void) { @@ -336,6 +371,7 @@ publish_devices(void) return devices; } + device_hooks * find_device(const char *name) { @@ -345,12 +381,14 @@ find_device(const char *name) return NULL; } + status_t init_driver() { return 0; } + void uninit_driver() {