combined mouse and keyboard interrupt handler, work in progress...

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15931 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2006-01-12 23:01:17 +00:00
parent 741e5c2d81
commit 582d6d64ae
5 changed files with 91 additions and 123 deletions

View File

@ -1,29 +1,13 @@
SubDir HAIKU_TOP src add-ons kernel drivers input ps2_hid ;
SubDir HAIKU_TOP src add-ons kernel drivers input ps2_hid_new ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders input ;
UsePrivateHeaders kernel ;
if ! $(HAIKU_COMPATIBLE) {
SubDirCcFlags -DCOMPILE_FOR_R5 ;
KernelAddon ps2_hid : kernel drivers bin :
common.c
keyboard.c
mouse.c
;
} else {
KernelAddon ps2_hid : kernel drivers bin :
KernelAddon ps2_hid_new : kernel drivers bin :
common.c
keyboard.c
mouse.c
packet_buffer.cpp
;
}
Package haiku-inputkit-cvs :
ps2_hid :
boot home config add-ons kernel drivers bin ;
PackageDriverSymLink haiku-inputkit-cvs : input ps2_hid ;

View File

@ -62,6 +62,35 @@ static uint8 *sResultBuffer;
static int32 sResultBytes;
inline uint8
ps2_read_ctrl()
{
return gIsa->read_io_8(PS2_PORT_CTRL);
}
inline uint8
ps2_read_data()
{
return gIsa->read_io_8(PS2_PORT_DATA);
}
inline void
ps2_write_ctrl(uint8 ctrl)
{
gIsa->write_io_8(PS2_PORT_CTRL, ctrl);
}
inline void
ps2_write_data(uint8 data)
{
gIsa->write_io_8(PS2_PORT_DATA, data);
}
/** Wait until the specified status bits are cleared or set, depending on the
* second parameter.
* This currently busy waits, but should nonetheless be avoided in interrupt
@ -248,42 +277,27 @@ ps2_wait_for_result(void)
}
void
ps2_common_uninitialize(void)
static int32
ps2_interrupt(void* cookie)
{
// do we still need the resources?
if (atomic_add(&sInitialized, -1) > 1)
return;
uint8 ctrl;
uint8 data;
ctrl = ps2_read_ctrl();
if (!(ctrl & PS2_STATUS_OUTPUT_BUFFER_FULL))
return B_UNHANDLED_INTERRUPT;
data = ps2_read_data();
delete_sem(sResultSemaphore);
delete_sem(sResultOwnerSemaphore);
TRACE(("ps2_interrupt: ctrl 0x%02x, data 0x%02x (%s)\n", ctrl, data, (ctrl & PS2_STATUS_MOUSE_DATA) ? "mouse" : "keyb"));
if (ctrl & PS2_STATUS_MOUSE_DATA)
return mouse_handle_int(data);
else
return keyboard_handle_int(data);
}
status_t
ps2_common_initialize(void)
{
if (atomic_add(&sInitialized, 1) > 0) {
// we're already initialized
return B_OK;
}
sResultSemaphore = create_sem(0, "ps/2 result");
if (sResultSemaphore < B_OK)
return sResultSemaphore;
sResultOwnerSemaphore = create_sem(1, "ps/2 result owner");
if (sResultOwnerSemaphore < B_OK) {
delete_sem(sResultSemaphore);
return sResultOwnerSemaphore;
}
sResultBytes = 0;
sResultBuffer = NULL;
return B_OK;
}
// #pragma mark -
// driver interface
@ -302,10 +316,8 @@ publish_devices(void)
static char *kDevices[3];
int index = 0;
if (sMouseDetected)
kDevices[index++] = DEVICE_MOUSE_NAME;
if (sKeyboardDetected)
kDevices[index++] = DEVICE_KEYBOARD_NAME;
kDevices[index++] = NULL;
@ -332,45 +344,46 @@ init_driver(void)
status_t status;
status = get_module(B_ISA_MODULE_NAME, (module_info **)&gIsa);
if (status < B_OK) {
TRACE(("Failed getting isa module: %s\n", strerror(status)));
return status;
}
// Try to probe for the mouse first, as this can hang the keyboard if no
// mouse is found.
// Probing the mouse first and initializing the keyboard later appearantly
// clears the keyboard stall.
if (probe_mouse(NULL) == B_OK)
sMouseDetected = true;
else
dprintf("ps2_hid: no mouse detected!\n");
if (probe_keyboard() == B_OK)
sKeyboardDetected = true;
else
dprintf("ps2_hid: no keyboard detected!\n");
// If there is no keyboard or mouse, we don't need to publish ourselves
if (!sKeyboardDetected && !sMouseDetected) {
put_module(B_ISA_MODULE_NAME);
return B_ERROR;
}
// A semaphore to synchronize open keyboard and mouse devices
if (status < B_OK)
goto err_1;
gDeviceOpenSemaphore = create_sem(1, "ps/2 open");
if (gDeviceOpenSemaphore < B_OK)
return gDeviceOpenSemaphore;
goto err_2;
return get_command_byte(&sCommandByte);
status = install_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL, 0);
if (status)
goto err_3;
status = install_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL, 0);
if (status)
goto err_4;
//goto err_5;
return B_OK;
err_5:
remove_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL);
err_4:
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL);
err_3:
delete_sem(gDeviceOpenSemaphore);
err_2:
put_module(B_ISA_MODULE_NAME);
err_1:
return B_ERROR;
}
void
uninit_driver(void)
{
remove_io_interrupt_handler(INT_PS2_MOUSE, &ps2_interrupt, NULL);
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &ps2_interrupt, NULL);
delete_sem(gDeviceOpenSemaphore);
put_module(B_ISA_MODULE_NAME);
put_module(B_ISA_MODULE_NAME);
}

View File

@ -52,6 +52,10 @@ extern status_t ps2_common_initialize(void);
extern status_t probe_keyboard(void);
extern status_t probe_mouse(size_t *probed_packet_size);
extern int32 mouse_handle_int(uint8 data);
extern int32 keyboard_handle_int(uint8 data);
extern status_t keyboard_open(const char *name, uint32 flags, void **cookie);
extern status_t keyboard_close(void *cookie);
extern status_t keyboard_freecookie(void *cookie);

View File

@ -146,31 +146,24 @@ set_leds(led_info *ledInfo)
}
static int32
handle_keyboard_interrupt(void *data)
int32 keyboard_handle_int(uint8 data)
{
uint8 read = gIsa->read_io_8(PS2_PORT_CTRL);
TRACE(("handle_keyboard_interrupt: read = 0x%x\n", read));
if (atomic_and(&sKeyboardOpenMask, 1) == 0)
return B_HANDLED_INTERRUPT;
if (read & PS2_STATUS_OUTPUT_BUFFER_FULL) {
at_kbd_io keyInfo;
uint8 scancode;
read = gIsa->read_io_8(PS2_PORT_DATA);
// someone else might wait for a result from the keyboard controller
if (ps2_handle_result(read))
return B_INVOKE_SCHEDULER;
// TODO: Handle braindead "pause" key special case
if (read == EXTENDED_KEY) {
if (data == EXTENDED_KEY) {
sIsExtended = true;
TRACE(("Extended key\n"));
return B_HANDLED_INTERRUPT;
}
scancode = read;
scancode = data;
TRACE(("scancode: %x\n", scancode));
@ -200,11 +193,6 @@ handle_keyboard_interrupt(void *data)
}
release_sem_etc(sKeyboardSem, 1, B_DO_NOT_RESCHEDULE);
} else {
// ToDo: the buffer is not yet available, we should come back soon...
// (depending on how often we see the message below... :-)
dprintf("ps2_hid: keyboard: buffer not available!\n");
}
return B_INVOKE_SCHEDULER;
}
@ -309,10 +297,6 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
acquire_sem(gDeviceOpenSemaphore);
status = ps2_common_initialize();
if (status != B_OK)
goto err1;
sKeyboardSem = create_sem(0, "keyboard_sem");
if (sKeyboardSem < 0) {
status = sKeyboardSem;
@ -337,12 +321,6 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
goto err4;
}
status = install_io_interrupt_handler(INT_PS2_KEYBOARD,
&handle_keyboard_interrupt, NULL, 0);
if (status < B_OK)
goto err4;
sInterruptHandlerInstalled = true;
release_sem(gDeviceOpenSemaphore);
*_cookie = NULL;
@ -355,7 +333,6 @@ err4:
err3:
delete_sem(sKeyboardSem);
err2:
ps2_common_uninitialize();
err1:
atomic_and(&sKeyboardOpenMask, 0);
release_sem(gDeviceOpenSemaphore);
@ -369,13 +346,10 @@ keyboard_close(void *cookie)
{
TRACE(("keyboard_close()\n"));
remove_io_interrupt_handler(INT_PS2_KEYBOARD, &handle_keyboard_interrupt, NULL);
sInterruptHandlerInstalled = false;
delete_packet_buffer(sKeyBuffer);
delete_sem(sKeyboardSem);
ps2_common_uninitialize();
atomic_and(&sKeyboardOpenMask, 0);
return B_OK;

View File

@ -249,17 +249,10 @@ set_mouse_enabled(bool enable)
* calls to the handler, each holds a different byte on the data port.
*/
static int32
handle_mouse_interrupt(void* cookie)
int32 mouse_handle_int(uint8 data)
{
uint8 data = gIsa->read_io_8(PS2_PORT_CTRL);
if (!(data & PS2_STATUS_OUTPUT_BUFFER_FULL)) {
TRACE(("no ps2 mouse data available\n"));
return B_UNHANDLED_INTERRUPT;
}
data = gIsa->read_io_8(PS2_PORT_DATA);
TRACE(("mouse interrupt: %d byte: 0x%02x\n", sPacketIndex, data));
if (atomic_and(&sMouseOpenMask, 1) == 0)
return B_HANDLED_INTERRUPT;
if (sPacketIndex == 0 && !(data & 8)) {
TRACE(("bad mouse data, trying resync\n"));