X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fkeyboard.c;h=6d398782c6969b99938403bd99413edc8e0e755c;hb=5d1bbcc86de011e3f0d115b6f10fd8645cdf855e;hp=43dd816a7a33bca3bb102b82960350353a24d76f;hpb=a0d3be5212e7a5053ba213ce7bd26c7124cf01e3;p=palacios.git diff --git a/palacios/src/devices/keyboard.c b/palacios/src/devices/keyboard.c index 43dd816..6d39878 100644 --- a/palacios/src/devices/keyboard.c +++ b/palacios/src/devices/keyboard.c @@ -28,7 +28,7 @@ #include -#ifndef CONFIG_DEBUG_KEYBOARD +#ifndef V3_CONFIG_DEBUG_KEYBOARD #undef PrintDebug #define PrintDebug(fmt, args...) #endif @@ -185,6 +185,9 @@ struct keyboard_internal { // After the Keyboard SET_RATE is called // we wait for the output byte on 64? SET_RATE, + // after having a f0 sent to 60 + // we wait for a new output byte on 60 + GETSET_SCANCODES, } state; @@ -209,6 +212,7 @@ struct keyboard_internal { uint8_t wrap; int mouse_enabled; + int scancode_set; struct queue kbd_queue; struct queue mouse_queue; @@ -331,7 +335,7 @@ static int pull_from_output_queue(struct keyboard_internal * state, uint8_t * va #include -#ifdef CONFIG_SYMMOD +#ifdef V3_CONFIG_SYMMOD #include #endif @@ -349,7 +353,7 @@ static int key_event_handler(struct v3_vm_info * vm, } // PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3); } -#ifdef CONFIG_SYMCALL +#ifdef V3_CONFIG_SYMCALL else if (evt->scan_code == 0x43) { // F9 Sym test struct guest_info * core = &(vm->cores[0]); PrintDebug("Testing sym call\n"); @@ -381,13 +385,13 @@ static int key_event_handler(struct v3_vm_info * vm, v3_dbg_enable ^= 1; } -#ifdef CONFIG_TELEMETRY +#ifdef V3_CONFIG_TELEMETRY else if (evt->scan_code == 0x41) { // F7 telemetry dump v3_print_telemetry(vm); } #endif -#ifdef CONFIG_SYMMOD +#ifdef V3_CONFIG_SYMMOD else if (evt->scan_code == 0x40) { // F6 Test symmod load v3_load_sym_capsule(vm, "lnx_test"); } @@ -441,41 +445,7 @@ static int mouse_event_handler(struct v3_vm_info * vm, } -static int keyboard_reset_device(struct keyboard_internal * kbd) { - - memset(kbd, 0, sizeof(struct keyboard_internal)); - - kbd->state = NORMAL; - kbd->mouse_state = STREAM; - - - // PS2, keyboard+mouse enabled, generic translation - kbd->cmd.val = 0; - - kbd->cmd.irq_en = 1; - kbd->cmd.mouse_irq_en = 1; - kbd->cmd.self_test_ok = 1; - /** **/ - - - // buffers empty, no errors - kbd->status.val = 0; - - kbd->status.self_test_ok = 1; // self-tests passed - kbd->status.enabled = 1;// keyboard ready - /** **/ - - - kbd->output_byte = 0; // ? - - kbd->input_byte = INPUT_RAM; // we have some - // also display=color, jumper 0, keyboard enabled - - PrintDebug("keyboard: reset device\n"); - - return 0; -} @@ -900,6 +870,34 @@ static int keyboard_write_output(struct guest_info * core, ushort_t port, void * kbd->state = NORMAL; break; + case GETSET_SCANCODES: + switch (data) { + case 0: + PrintDebug("Keyboard: scancode set being read\n"); + push_to_output_queue(kbd, 0x45 - 2 * kbd->scancode_set, COMMAND, KEYBOARD); + break; + case 1: + PrintError("keyboard: unsupported scancode set %d selected\n", data); + return -1; + case 2: + PrintDebug("Keyboard: scancode set being set to %d\n", data); + kbd->scancode_set = data; + push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD); + break; + case 3: + /* OpenBSD wants scancode set 3, but falls back to 2 if a + * subsequent read reveals that the request was ignored + */ + PrintError("keyboard: ignoring request for scancode set %d\n", data); + break; + default: + PrintError("keyboard: unknown scancode set %d selected\n", data); + return -1; + + } + kbd->state = NORMAL; + break; + default: case NORMAL: { // command is being sent to keyboard controller @@ -939,6 +937,11 @@ static int keyboard_write_output(struct guest_info * core, ushort_t port, void * push_to_output_queue(kbd, 0xee, COMMAND, KEYBOARD); break; + case 0xf0: // get/set scancode set + push_to_output_queue(kbd, 0xfa, COMMAND, KEYBOARD); + kbd->state = GETSET_SCANCODES; + break; + case 0xfe: // resend case 0xfd: // set key type make case 0xfc: // set key typ make/break @@ -991,18 +994,84 @@ static int keyboard_read_input(struct guest_info * core, ushort_t port, void * d -static int keyboard_free(struct vm_device * dev) { +static int keyboard_free(struct keyboard_internal * kbd) { + + // unhook host events + + V3_Free(kbd); return 0; } +static int keyboard_reset_device(struct keyboard_internal * kbd) { + -static struct v3_device_ops dev_ops = { - .free = keyboard_free, + kbd->mouse_queue.start = 0; + kbd->mouse_queue.end = 0; + kbd->mouse_queue.count = 0; + + kbd->kbd_queue.start = 0; + kbd->kbd_queue.end = 0; + kbd->kbd_queue.count = 0; + kbd->mouse_enabled = 0; + kbd->scancode_set = 2; + + kbd->state = NORMAL; + kbd->mouse_state = STREAM; + + // PS2, keyboard+mouse enabled, generic translation + kbd->cmd.val = 0; + + kbd->cmd.irq_en = 1; + kbd->cmd.mouse_irq_en = 1; + kbd->cmd.self_test_ok = 1; + /** **/ + + + // buffers empty, no errors + kbd->status.val = 0; + + kbd->status.self_test_ok = 1; // self-tests passed + kbd->status.enabled = 1;// keyboard ready + /** **/ + + + kbd->output_byte = 0; // ? + + kbd->input_byte = INPUT_RAM; // we have some + // also display=color, jumper 0, keyboard enabled + + PrintDebug("keyboard: reset device\n"); + + return 0; + +} + +#ifdef V3_CONFIG_CHECKPOINT +static int keyboard_save(struct v3_chkpt_ctx * ctx, void * private_data) { + return 0; +} + + +static int keyboard_load(struct v3_chkpt_ctx * ctx, void * private_data) { + struct keyboard_internal * kbd = (struct keyboard_internal *)private_data; + keyboard_reset_device(kbd); + return 0; +} + +#endif + + +static struct v3_device_ops dev_ops = { + .free = (int (*)(void *))keyboard_free, +#ifdef V3_CONFIG_CHECKPOINT + .save = keyboard_save, + .load = keyboard_load +#endif }; @@ -1011,6 +1080,7 @@ static struct v3_device_ops dev_ops = { static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct keyboard_internal * kbd = NULL; char * dev_id = v3_cfg_val(cfg, "ID"); + int ret = 0; PrintDebug("keyboard: init_device\n"); @@ -1020,20 +1090,11 @@ static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { kbd->vm = vm; - kbd->mouse_queue.start = 0; - kbd->mouse_queue.end = 0; - kbd->mouse_queue.count = 0; - - kbd->kbd_queue.start = 0; - kbd->kbd_queue.end = 0; - kbd->kbd_queue.count = 0; - - kbd->mouse_enabled = 0; - - struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, kbd); + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, kbd); - if (v3_attach_device(vm, dev) == -1) { + if (dev == NULL) { PrintError("Could not attach device %s\n", dev_id); + V3_Free(kbd); return -1; } @@ -1044,11 +1105,17 @@ static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { // hook ports - v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command); - v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output); + ret |= v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command); + ret |= v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output); + + if (ret != 0) { + PrintError("Error hooking keyboard IO ports\n"); + v3_remove_device(dev); + return -1; + } - v3_hook_host_event(vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), dev); - v3_hook_host_event(vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), dev); + v3_hook_host_event(vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), kbd); + v3_hook_host_event(vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), kbd); #if KEYBOARD_DEBUG_80H