better multiplexing support

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2006-01-21 13:09:47 +00:00
parent 0219459ba0
commit 03d0d41ac7
6 changed files with 129 additions and 19 deletions

View File

@ -48,7 +48,8 @@ sem_id gDeviceOpenSemaphore;
static sem_id sKbcSem;
static int32 sIgnoreInterrupts = 0;
static bool sMultiplexingActive = false;
bool gMultiplexingActive = false;
inline uint8
@ -68,6 +69,8 @@ ps2_read_data()
inline void
ps2_write_ctrl(uint8 ctrl)
{
dprintf("ps2_write_ctrl 0x%02x\n", ctrl);
gIsa->write_io_8(PS2_PORT_CTRL, ctrl);
}
@ -75,6 +78,8 @@ ps2_write_ctrl(uint8 ctrl)
inline void
ps2_write_data(uint8 data)
{
dprintf("ps2_write_data 0x%02x\n", data);
gIsa->write_io_8(PS2_PORT_DATA, data);
}
@ -162,22 +167,18 @@ ps2_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
return res;
}
status_t
ps2_keyboard_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
return B_OK;
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], cmd, out, out_count, in, in_count);
}
status_t
ps2_mouse_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
return B_OK;
}
return ps2_dev_command(&ps2_device[PS2_DEVICE_MOUSE], cmd, out, out_count, in, in_count);
}
// #pragma mark -
@ -205,8 +206,6 @@ ps2_interrupt(void* cookie)
uint8 data;
ps2_dev *dev;
TRACE(("ps2_interrupt\n"));
ctrl = ps2_read_ctrl();
if (!(ctrl & PS2_STATUS_OUTPUT_BUFFER_FULL))
return B_UNHANDLED_INTERRUPT;
@ -221,7 +220,12 @@ ps2_interrupt(void* cookie)
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) {
uint8 idx = 0;
uint8 idx;
if (gMultiplexingActive) {
idx = ctrl >> 6;
} else {
idx = 0;
}
dev = &ps2_device[PS2_DEVICE_MOUSE + idx];
} else {
dev = &ps2_device[PS2_DEVICE_KEYB];
@ -264,7 +268,7 @@ ps2_init_driver(void)
goto err_4;
{
uint8 d;
uint8 d, in, out;
status_t res;
res = ps2_get_command_byte(&d);
@ -275,11 +279,56 @@ ps2_init_driver(void)
res = ps2_set_command_byte(d);
dprintf("ps2_set_command_byte: res 0x%08x, d 0x%02x\n", res, d);
in = 0x00;
out = 0xf0;
res = ps2_command(0xd3, &out, 1, &in, 1);
dprintf("step1: res 0x%08x, out 0x%02x, in 0x%02x\n", res, out, in);
in = 0x00;
out = 0x56;
res = ps2_command(0xd3, &out, 1, &in, 1);
dprintf("step2: res 0x%08x, out 0x%02x, in 0x%02x\n", res, out, in);
in = 0x00;
out = 0xa4;
res = ps2_command(0xd3, &out, 1, &in, 1);
dprintf("step3: res 0x%08x, out 0x%02x, in 0x%02x\n", res, out, in);
if (res == B_OK && in != 0xa4) {
dprintf("found active multiplexing v%d.%d\n", (in >> 4), in & 0xf);
gMultiplexingActive = true;
res = ps2_command(0xa8, NULL, 0, NULL, 0);
dprintf("step4: res 0x%08x\n", res);
res = ps2_command(0x90, NULL, 0, NULL, 0);
dprintf("step5: res 0x%08x\n", res);
res = ps2_command(0xa8, NULL, 0, NULL, 0);
dprintf("step6: res 0x%08x\n", res);
res = ps2_command(0x91, NULL, 0, NULL, 0);
dprintf("step7: res 0x%08x\n", res);
res = ps2_command(0xa8, NULL, 0, NULL, 0);
dprintf("step8: res 0x%08x\n", res);
res = ps2_command(0x92, NULL, 0, NULL, 0);
dprintf("step9: res 0x%08x\n", res);
res = ps2_command(0xa8, NULL, 0, NULL, 0);
dprintf("step10: res 0x%08x\n", res);
res = ps2_command(0x93, NULL, 0, NULL, 0);
dprintf("step11: res 0x%08x\n", res);
res = ps2_command(0xa8, NULL, 0, NULL, 0);
dprintf("step12: res 0x%08x\n", res);
}
}
ps2_service_handle_device_added(&ps2_device[PS2_DEVICE_KEYB]);
ps2_service_handle_device_added(&ps2_device[PS2_DEVICE_MOUSE]);
if (sMultiplexingActive) {
if (gMultiplexingActive) {
ps2_service_handle_device_added(&ps2_device[PS2_DEVICE_MOUSE + 1]);
ps2_service_handle_device_added(&ps2_device[PS2_DEVICE_MOUSE + 2]);
ps2_service_handle_device_added(&ps2_device[PS2_DEVICE_MOUSE + 3]);

View File

@ -35,6 +35,8 @@ extern sem_id gDeviceOpenSemaphore;
extern device_hooks sKeyboardDeviceHooks;
extern device_hooks sMouseDeviceHooks;
extern bool gMultiplexingActive;
// prototypes from common.c
status_t ps2_init_driver(void);

View File

@ -16,10 +16,10 @@
ps2_dev ps2_device[PS2_DEV_COUNT] =
{
{ .name = "input/mouse/ps2/0", .active = false, .result_sem = -1 },
{ .name = "input/mouse/ps2/1", .active = false, .result_sem = -1 },
{ .name = "input/mouse/ps2/2", .active = false, .result_sem = -1 },
{ .name = "input/mouse/ps2/3", .active = false, .result_sem = -1 },
{ .name = "input/mouse/ps2/0", .active = false, .idx = 0, .result_sem = -1 },
{ .name = "input/mouse/ps2/1", .active = false, .idx = 1, .result_sem = -1 },
{ .name = "input/mouse/ps2/2", .active = false, .idx = 2, .result_sem = -1 },
{ .name = "input/mouse/ps2/3", .active = false, .idx = 3, .result_sem = -1 },
{ .name = "input/keyboard/at/0", .active = false, .result_sem = -1, .flags = PS2_FLAG_KEYB }
};
@ -115,3 +115,57 @@ ps2_dev_handle_int(ps2_dev *dev, uint8 data)
return mouse_handle_int(data);
}
status_t
ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
status_t res = B_OK;
int i, count;
dprintf("ps2_dev_command %02x, %d out, in %d, dev %s\n", cmd, out_count, in_count, dev->name);
dev->result_buf_cnt = in_count;
dev->result_buf_idx = 0;
dev->result_buf = in;
for (i = -1; res == B_OK && i < out_count; i++) {
if (!(dev->flags & PS2_FLAG_KEYB)) {
uint8 prefix_cmd;
if (gMultiplexingActive)
prefix_cmd = 0x90 + dev->idx;
else
prefix_cmd = 0xd4;
res = ps2_wait_write();
if (res == B_OK)
ps2_write_ctrl(prefix_cmd);
}
res = ps2_wait_write();
if (res == B_OK) {
ps2_write_data(i == -1 ? cmd : out[i]);
}
}
if (res != B_OK) {
dprintf("ps2_dev_command send failed\n");
}
if (in_count != 0) {
dprintf("ps2_dev_command waiting for result\n");
res = acquire_sem_etc(dev->result_sem, 1, B_RELATIVE_TIMEOUT, 4000000);
count = in_count - dev->result_buf_cnt;
dev->result_buf_cnt = 0;
dprintf("ps2_dev_command res %08x, in %d\n", res, count);
for (i = 0; i < count; i++)
dprintf("ps2_dev_command data %02x\n", in[i]);
}
return res;
}

View File

@ -17,6 +17,7 @@ typedef struct
const char * name;
bool active;
uint32 flags;
uint8 idx;
sem_id result_sem;
uint8 * result_buf;
int result_buf_idx;
@ -33,6 +34,9 @@ extern ps2_dev ps2_device[5];
status_t ps2_dev_init(void);
void ps2_dev_exit(void);
status_t ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count);
void ps2_dev_publish(ps2_dev *dev);
void ps2_dev_unpublish(ps2_dev *dev);

View File

@ -282,6 +282,7 @@ probe_mouse(size_t *probed_packet_size)
&& ps2_set_sample_rate(80) == B_OK) {
// get device id, again
ps2_mouse_command(PS2_CMD_GET_DEVICE_ID, NULL, 0, &deviceId, 1);
TRACE(("probe_mouse(): device id: %2x\n", deviceId));
break;
}
}

View File

@ -69,7 +69,7 @@ ps2_service_probe_device(ps2_dev *dev)
status_t res;
TRACE(("ps2_service_probe_device %s\n", dev->name));
/*
if (dev->flags & PS2_FLAG_KEYB) {
res = ps2_command(0xae, NULL, 0, NULL, 0);
@ -86,7 +86,7 @@ ps2_service_probe_device(ps2_dev *dev)
res = ps2_command(0xa9, NULL, 0, &d, 1);
dprintf("AUX test: res 0x%08x, d 0x%02x\n", res, d);
}
*/
return B_OK;
}