X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fkeyboard.c;h=65e8797e13f3841d3b163445003738a276c10cb2;hb=183211e5bf60474e63c4159a63ca1f5d445491fd;hp=9c15efa5be3c1cc2411e3a7eda35ea56d788e9b3;hpb=6ba597e93de8a1511d3be40066ae5082b9dbeb70;p=palacios.releases.git diff --git a/palacios/src/devices/keyboard.c b/palacios/src/devices/keyboard.c index 9c15efa..65e8797 100644 --- a/palacios/src/devices/keyboard.c +++ b/palacios/src/devices/keyboard.c @@ -21,6 +21,8 @@ #include #include +#include + #ifndef DEBUG_KEYBOARD #undef PrintDebug @@ -205,28 +207,27 @@ struct keyboard_internal { uchar_t input_byte; // input port of onboard uC - // Data for 8042 - uchar_t input_queue; // - uint_t input_queue_len; // - //uint_t input_queue_read; - //uint_t input_queue_write; // Data for system uchar_t output_queue; // uint_t output_queue_len; // //uint_t output_queue_read; //uint_t output_queue_write; + v3_lock_t kb_lock; }; static int keyboard_interrupt(struct vm_device * dev, uint_t irq) { + struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); + PrintDebug("keyboard: interrupt 0x%x\n", irq); - v3_raise_irq(dev->vm, irq); + if (state->cmd_byte & CMD_INTR) { + v3_raise_irq(dev->vm, irq); + } return 0; - } @@ -252,16 +253,13 @@ static int PushToOutputQueue(struct vm_device * dev, uchar_t value, uchar_t over if (mouse) { state->status_byte |= STATUS_MOUSE_BUFFER_FULL; - } - - { - state->status_byte |= STATUS_OUTPUT_BUFFER_FULL; - } - - if (state->cmd_byte & CMD_INTR) { + keyboard_interrupt(dev, MOUSE_IRQ); + } else { keyboard_interrupt(dev, KEYBOARD_IRQ); } + state->status_byte |= STATUS_OUTPUT_BUFFER_FULL; + return 0; } else { @@ -270,7 +268,7 @@ static int PushToOutputQueue(struct vm_device * dev, uchar_t value, uchar_t over } } -#if 1 + // // pull item from outputqueue // returns 0 if successful @@ -303,55 +301,6 @@ static int PullFromOutputQueue(struct vm_device * dev, uchar_t * value) return -1; } } -#endif - -#if 0 -// -// push item onto inputqueue, optionally overwriting if there is no room -// returns 0 if successful -// -static int PushToInputQueue(struct vm_device * dev, uchar_t value, uchar_t overwrite) -{ - struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); - - if ((state->input_queue_len == 0) || overwrite) { - - state->input_queue = value; - state->input_queue_len = 1; - state->status_byte |= STATUS_INPUT_BUFFER_FULL; - - return 0; - } else { - PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n"); - return -1; - } -} - -// -// pull item from inputqueue -// returns 0 if successful -// -static int PullFromInputQueue(struct vm_device *dev, uchar_t *value) -{ - struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data); - - if (state->input_queue_len == 1) { - - *value = state->input_queue; - state->input_queue_len = 0; - state->status_byte &= ~STATUS_INPUT_BUFFER_FULL; - - return 0; - } else { - PrintError("keyboard: PullFromInputQueue Failed - Queue Empty\n"); - return -1; - } -} - -#endif - - - @@ -363,16 +312,21 @@ static int key_event_handler(struct guest_info * info, struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code); - + + if (evt->scan_code == 0x44) { // F10 debug dump + v3_print_guest_state(info); + // PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3); + } + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + if ( (state->status_byte & STATUS_ENABLED) // onboard is enabled && (!(state->cmd_byte & CMD_DISABLE)) ) { // keyboard is enabled PushToOutputQueue(dev, evt->scan_code, OVERWRITE, DATA, KEYBOARD); - - if (state->cmd_byte & CMD_INTR) { - keyboard_interrupt(dev, KEYBOARD_IRQ); - } } + + v3_unlock_irqrestore(state->kb_lock, irq_state); return 0; } @@ -383,10 +337,12 @@ static int mouse_event_handler(struct guest_info * info, void * private_data) { struct vm_device * dev = (struct vm_device *)private_data; struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data); - + int ret = 0; PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n", evt->data[0], evt->data[1], evt->data[2]); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + memcpy(state->mouse_packet, evt->data, 3); state->status_byte |= STATUS_MOUSE_BUFFER_FULL; @@ -401,11 +357,15 @@ static int mouse_event_handler(struct guest_info * info, } break; default: - return -1; + PrintError("Invalid mouse state\n"); + ret = -1; break; } - return 0; + + v3_unlock_irqrestore(state->kb_lock, irq_state); + + return ret; } @@ -822,6 +782,9 @@ static int keyboard_write_command(ushort_t port, cmd = *((uchar_t*)src); + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + if (state->state != NORMAL) { PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n"); } @@ -999,8 +962,9 @@ static int keyboard_write_command(ushort_t port, break; } - return 1; + v3_unlock_irqrestore(state->kb_lock, irq_state); + return length; } static int keyboard_read_status(ushort_t port, @@ -1010,19 +974,21 @@ static int keyboard_read_status(ushort_t port, { struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); - if (length == 1) { - - PrintDebug("keyboard: read status (64h): "); - - *((uchar_t*)dest) = state->status_byte; - - PrintDebug("0x%x\n", *((uchar_t*)dest)); - - return 1; - } else { + if (length != 1) { PrintError("keyboard: >1 byte read for status (64h)\n"); return -1; } + + + PrintDebug("keyboard: read status (64h): "); + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + *((uchar_t*)dest) = state->status_byte; + v3_unlock_irqrestore(state->kb_lock, irq_state); + + PrintDebug("0x%x\n", *((uchar_t*)dest)); + + return length; } static int keyboard_write_output(ushort_t port, @@ -1031,6 +997,7 @@ static int keyboard_write_output(ushort_t port, struct vm_device * dev) { struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); + int ret = 0; if (length != 1) { PrintError("keyboard: write of 60h with >1 byte\n"); @@ -1041,6 +1008,8 @@ static int keyboard_write_output(ushort_t port, PrintDebug("keyboard: output 0x%x on 60h\n", data); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); + switch (state->state) { case WRITING_CMD_BYTE: state->cmd_byte = data; @@ -1133,13 +1102,15 @@ static int keyboard_write_output(ushort_t port, case 0xf8: // set all make/break case 0xf7: // set all typemaktic case 0xf6: // set defaults - PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data); - return -1; + PrintError("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data); + + ret = -1; break; default: - PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data); + PrintError("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data); state->status_byte |= 0x1; - return -1; + + ret = -1; break; } break; @@ -1147,7 +1118,13 @@ static int keyboard_write_output(ushort_t port, } - return 1; + v3_unlock_irqrestore(state->kb_lock, irq_state); + + if (ret == -1) { + return -1; + } + + return length; } static int keyboard_read_input(ushort_t port, @@ -1155,48 +1132,53 @@ static int keyboard_read_input(ushort_t port, uint_t length, struct vm_device * dev) { - struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); - if (length == 1) { - uchar_t data; - int done_mouse; + uchar_t data; + int done_mouse; + struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data); + + if (length != 1) { + PrintError("keyboard: unknown size read from input (60h)\n"); + return -1; + } + + PrintDebug("keyboard: read from input (60h): "); - PrintDebug("keyboard: read from input (60h): "); + addr_t irq_state = v3_lock_irqsave(state->kb_lock); - if (state->state == IN_MOUSE) { - done_mouse = mouse_read_input(dev); - if (done_mouse) { - state->state = NORMAL; - } - } - - PullFromOutputQueue(dev, &data); - - if (state->state == RESET) { - // We just delivered the ack for the reset - // now we will ready ourselves to deliver the BAT code (success) - PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD); + if (state->state == IN_MOUSE) { + done_mouse = mouse_read_input(dev); + if (done_mouse) { state->state = NORMAL; - PrintDebug(" (in reset, pushing BAT test code 0xaa) "); - } else if (state->state == KBD_ID1) { - PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD); - state->state = KBD_ID2; - PrintDebug(" (in kbd id request, pushing 1st ID val) "); - } else if (state->state == KBD_ID2) { - PushToOutputQueue(dev, 0x83, OVERWRITE, COMMAND, KEYBOARD); - state->state = NORMAL; - PrintDebug(" (in kbd id request, pushing 2nd ID val) "); } + } + + PullFromOutputQueue(dev, &data); + + if (state->state == RESET) { + // We just delivered the ack for the reset + // now we will ready ourselves to deliver the BAT code (success) + PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD); + state->state = NORMAL; + PrintDebug(" (in reset, pushing BAT test code 0xaa) "); + } else if (state->state == KBD_ID1) { + PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD); + state->state = KBD_ID2; + PrintDebug(" (in kbd id request, pushing 1st ID val) "); + } else if (state->state == KBD_ID2) { + PushToOutputQueue(dev, 0x83, OVERWRITE, COMMAND, KEYBOARD); + state->state = NORMAL; + PrintDebug(" (in kbd id request, pushing 2nd ID val) "); + } - PrintDebug("0x%x\n", data); + v3_unlock_irqrestore(state->kb_lock, irq_state); + + PrintDebug("0x%x\n", data); + + *((uchar_t*)dest) = data; + + return length; - *((uchar_t*)dest) = data; - - return 1; - } else { - PrintError("keyboard: unknown size read from input (60h)\n"); - return -1; - } } @@ -1206,14 +1188,16 @@ static int keyboard_read_input(ushort_t port, static int keyboard_init_device(struct vm_device * dev) { - // struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data; + struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data; PrintDebug("keyboard: init_device\n"); - // Would read state here - keyboard_reset_device(dev); + + v3_lock_init(&(data->kb_lock)); + + // 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);