1 #include <devices/keyboard.h>
3 #include <palacios/vmm.h>
4 #include <palacios/vmm_types.h>
6 #define KEYBOARD_DEBUG 1
8 #define KEYBOARD_DEBUG_80H 1
11 #define KEYBOARD_DEBUG_PRINT(first, rest...) PrintDebug(first, ##rest)
13 #define KEYBOARD_DEBUG_PRINT(first, rest...)
17 #define KEYBOARD_60H 0x60 // keyboard microcontroller
18 #define KEYBOARD_64H 0x64 // onboard microcontroller
20 #define KEYBOARD_DELAY_80H 0x80 // written for timing
22 #define KEYBOARD_IRQ 0x1
25 // extract bits for status byte
26 #define STATUS_OUTPUT_BUFFER_FULL 0x01 // 1=full (data for system)
27 #define STATUS_INPUT_BUFFER_FULL 0x02 // 1=full (data for 8042)
28 #define STATUS_SYSTEM 0x04 // 1=self-test-passed
29 #define STATUS_COMMAND_DATA_AVAIL 0x08 // internal: 0=data on 60h, 0=cmd on 64h
30 #define STATUS_ENABLED 0x10 // 1=keyboard is enabled
31 #define STATUS_MOUSE_BUFFER_FULL 0x20 // 1= mouse output buffer full
32 #define STATUS_TIMEOUT 0x40 // 1=timeout of keybd
33 #define STATUS_PARITY 0x80 // 1=parity error
37 #define CMD_INTR 0x01 // 1=interrupts enabled
38 #define CMD_MOUSE_INTR 0x02 // 1=interrupts enabled for mouse
39 #define CMD_SYSTEM 0x04 // 1= self test passed
40 #define CMD_OVERRIDE 0x08 // FORCE 0 for PS2
41 #define CMD_DISABLE 0x10 // 1=disabled keyboard
42 #define CMD_MOUSE_DISABLE 0x20 // 1=disabled mouse
43 #define CMD_SCANCODE_XLATE 0x40 // 1=translate to set 1 scancodes
44 #define CMD_RESERVED 0x80 // should be zero
46 // The currently targetted keyboard
47 static struct vm_device *thekeyboard = NULL;
50 struct keyboard_internal {
52 // 0x60 is the port for the keyboard microcontroller
53 // writes are commands
54 // reads from it usually return scancodes
55 // however, it can also return other data
56 // depending on the state of the onboard microcontroller
58 // 0x64 is the port for the onboard microcontroller
59 // writes are commands
63 // state of the onboard microcontroller
64 // this is needed because sometimes 0x60 reads come
65 // from the onboard microcontroller
66 enum {// Normal mode measn we deliver keys
67 // to the vm and accept commands from it
69 // after receiving cmd 0x60
70 // keybaord uC cmd will subsequently arrive
72 // after recieving 0xa5
73 // password arrives on data port, null terminated
75 // after receiving 0xd1
76 // keyboard uC output will arrive
78 // after having reset sent to 0x60
79 // we immediately ack, and then
80 // push BAT success (0xaa) after the ack
86 uchar_t cmd_byte; // for keyboard uC - read/written
87 // via read/write cmd byte command
88 uchar_t status_byte; // for on-board uC - read via 64h
91 uchar_t input_queue; //
92 uint_t input_queue_len; //
94 uchar_t output_queue; //
95 uint_t output_queue_len; //
100 // push item onto outputqueue, optionally overwriting if there is no room
101 // returns 0 if successful
103 static int PushToOutputQueue(struct vm_device *dev, uchar_t value, uchar_t overwrite)
105 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
107 if ((state->output_queue_len == 0) || overwrite) {
109 state->output_queue = value;
110 state->output_queue_len = 1;
111 state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
115 KEYBOARD_DEBUG_PRINT("keyboard: PushToOutputQueue Failed - Queue Full\n");
122 // pull item from outputqueue
123 // returns 0 if successful
125 static int PullFromOutputQueue(struct vm_device *dev, uchar_t *value)
127 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
129 if (state->output_queue_len == 1) {
131 *value = state->output_queue;
132 state->output_queue_len = 0;
133 state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
137 KEYBOARD_DEBUG_PRINT("keyboard: PullFromOutputQueue Failed - Queue Empty\n");
145 // push item onto inputqueue, optionally overwriting if there is no room
146 // returns 0 if successful
148 static int PushToInputQueue(struct vm_device *dev, uchar_t value, uchar_t overwrite)
150 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
152 if ((state->input_queue_len == 0) || overwrite) {
154 state->input_queue = value;
155 state->input_queue_len = 1;
156 state->status_byte |= STATUS_INPUT_BUFFER_FULL;
160 KEYBOARD_DEBUG_PRINT("keyboard: PushToOutputQueue Failed - Queue Full\n");
166 // pull item from inputqueue
167 // returns 0 if successful
169 static int PullFromInputQueue(struct vm_device *dev, uchar_t *value)
171 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
173 if (state->input_queue_len == 1) {
175 *value = state->input_queue;
176 state->input_queue_len = 0;
177 state->status_byte &= ~STATUS_INPUT_BUFFER_FULL;
181 KEYBOARD_DEBUG_PRINT("keyboard: PullFromInputQueue Failed - Queue Empty\n");
189 static struct vm_device *demultiplex_injected_key(uchar_t status, uchar_t scancode)
191 // this currently does nothing
195 int keyboard_interrupt(uint_t irq, struct vm_device * dev);
197 void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
199 struct vm_device *dev = demultiplex_injected_key(status, scancode);
200 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
202 KEYBOARD_DEBUG_PRINT("keyboard: injected status 0x%x, and scancode 0x%x\n", status, scancode);
204 if ( (state->status_byte & STATUS_ENABLED) // onboard is enabled
205 && (!(state->cmd_byte & CMD_DISABLE)) ) { // keyboard is enabled
207 PushToOutputQueue(dev, scancode, 1);
209 if (state->cmd_byte & CMD_INTR) {
210 keyboard_interrupt(KEYBOARD_IRQ, dev);
216 int keyboard_reset_device(struct vm_device * dev)
218 struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
220 memset(data, 0, sizeof(struct keyboard_internal));
223 CMD_INTR // interrupts on
224 | CMD_MOUSE_INTR // mouse interupts on
225 | CMD_SYSTEM ; // self test passed
226 // PS2, keyboard+mouse enabled, generic translation
229 STATUS_SYSTEM // self-tests passed
230 | STATUS_ENABLED ; // keyboard ready
231 // buffers empty, no errors
233 KEYBOARD_DEBUG_PRINT("keyboard: reset device\n");
241 int keyboard_start_device(struct vm_device *dev)
243 KEYBOARD_DEBUG_PRINT("keyboard: start device\n");
248 int keyboard_stop_device(struct vm_device *dev)
250 KEYBOARD_DEBUG_PRINT("keyboard: stop device\n");
255 #if KEYBOARD_DEBUG_80H
256 int keyboard_write_delay(ushort_t port,
259 struct vm_device * dev)
263 KEYBOARD_DEBUG_PRINT("keyboard: write of 0x%x to 80h\n", *((uchar_t*)src));
267 KEYBOARD_DEBUG_PRINT("keyboard: write of >1 byte to 80h\n", *((uchar_t*)src));
273 int keyboard_read_delay(ushort_t port,
276 struct vm_device * dev)
280 *((uchar_t*)dest) = In_Byte(port);
282 KEYBOARD_DEBUG_PRINT("keyboard: read of 0x%x from 80h\n", *((uchar_t*)dest));
286 KEYBOARD_DEBUG_PRINT("keyboard: read of >1 byte from 80h\n");
297 int keyboard_write_command(ushort_t port,
300 struct vm_device * dev)
302 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
305 // Should always be single byte write
308 KEYBOARD_DEBUG_PRINT("keyboard: write of >1 bytes (%d) to 64h\n", length);
312 cmd = *((uchar_t*)src);
314 if (state->state != NORMAL) {
315 KEYBOARD_DEBUG_PRINT("keyboard: warning - receiving command on 64h but state != NORMAL\n");
318 KEYBOARD_DEBUG_PRINT("keyboard: command 0x%x on 64h\n", cmd);
322 case 0x20: // READ COMMAND BYTE (returned in 60h)
323 PushToOutputQueue(dev, state->cmd_byte, 1);
324 state->state = NORMAL; // the next read on 0x60 will get the right data
327 case 0x60: // WRITE COMMAND BYTE (read from 60h)
328 state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
331 // case 0x90-9f - write to output port (?)
333 case 0xa1: // Get version number
334 PushToOutputQueue(dev, 0, 1);
335 state->state = NORMAL;
338 case 0xa4: // is password installed? send result to 0x60
339 // we don't support passwords
340 PushToOutputQueue(dev, 0xf1, 1);
341 state->state = NORMAL;
344 case 0xa5: // new password will arrive on 0x60
345 state->state = TRANSMIT_PASSWD;
348 case 0xa6: // check passwd;
349 // since we do not support passwords, we will simply ignore this
350 // the implication is that any password check immediately succeeds
351 // with a blank password
352 state->state = NORMAL;
355 case 0xa7: // disable mouse
356 state->cmd_byte |= CMD_MOUSE_DISABLE;
357 state->state = NORMAL;
360 case 0xa8: // enable mouse
361 state->cmd_byte &= ~CMD_MOUSE_DISABLE;
362 state->state = NORMAL;
365 case 0xa9: // mouse interface test (always succeeds)
366 PushToOutputQueue(dev, 0, 1);
367 state->state = NORMAL;
370 case 0xaa: // controller self test (always succeeds)
371 PushToOutputQueue(dev, 0x55, 1);
372 state->state = NORMAL;
375 case 0xab: // keyboard interface test (always succeeds)
376 PushToOutputQueue(dev, 0, 1);
377 state->state = NORMAL;
380 case 0xad: // disable keyboard
381 state->cmd_byte |= CMD_DISABLE;
382 state->state = NORMAL;
385 case 0xae: // enable keyboard
386 state->cmd_byte &= ~CMD_DISABLE;
387 state->state = NORMAL;
390 case 0xaf: // get version
391 PushToOutputQueue(dev, 0x00, 1);
392 state->state = NORMAL;
396 // case c0 read input port ?
397 // case c1 copy input port lsn to status
398 // case c2 copy input port msn to status
400 // case d0 read output port
401 // case d1 write output port
402 case 0xd1: // Write next 0x60 byte to uC output port
403 state->state = WRITE_OUTPUT;
406 // case d2 write keyboard buffer (inject key)
407 // case d3 write mouse buffer (inject mouse)
408 // case d4 write mouse device (command to mouse?)
410 // case e0 read test port
413 // case f0..ff pulse output port ?
430 PrintDebug("FIXME: keyboard output pulse: %x\n", cmd);
431 // either set/unset the a20 line (bit 1)
432 // or reset the machine (bit 0 == 0)
436 KEYBOARD_DEBUG_PRINT("keyboard: ignoring command (unimplemented)\n");
437 state->state = NORMAL;
438 return -1; // JRL: We die here to prevent silent errors
446 int keyboard_read_status(ushort_t port,
449 struct vm_device * dev)
451 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
455 KEYBOARD_DEBUG_PRINT("keyboard: read status (64h): ");
457 *((uchar_t*)dest) = state->status_byte;
459 KEYBOARD_DEBUG_PRINT("0x%x\n", *((uchar_t*)dest));
463 KEYBOARD_DEBUG_PRINT("keyboard: >1 byte read for status (64h)\n");
468 int keyboard_write_output(ushort_t port,
471 struct vm_device * dev)
473 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
476 KEYBOARD_DEBUG_PRINT("keyboard: write of 60h with >1 byte\n");
480 uchar_t data = *((uchar_t*)src);
482 switch (state->state) {
483 case WRITING_CMD_BYTE:
484 state->cmd_byte = data;
485 state->state = NORMAL;
487 case TRANSMIT_PASSWD:
492 state->state = NORMAL;
496 PrintDebug("FIXME: keyboard write output: %x\n", data);
497 // either set/unset the a20 line (bit 1)
498 // or reset the machine (bit 0)
499 state->state = NORMAL;
505 // command is being sent to keyboard controller
508 PushToOutputQueue(dev, 0xfa, 1); // ack
509 state->state = RESET;
511 case 0xf5: // disable scanning
512 case 0xf4: // enable scanning
514 PushToOutputQueue(dev, 0xfa, 1);
515 // should do something here... PAD
516 state->state = NORMAL;
519 case 0xfd: // set key type make
520 case 0xfc: // set key typ make/break
521 case 0xfb: // set key type typematic
522 case 0xfa: // set all typematic make/break/typematic
523 case 0xf9: // set all make
524 case 0xf8: // set all make/break
525 case 0xf7: // set all typemaktic
526 case 0xf6: // set defaults
527 case 0xf3: // set typematic delay/rate
529 KEYBOARD_DEBUG_PRINT("keyboard: unhandled command 0x%x on output buffer (60h)\n", data);
531 return -1; // JRL: We die here to prevent silent errors
537 KEYBOARD_DEBUG_PRINT("keyboard: unknown state %x on command 0x%x on output buffer (60h)\n", state->state, data);
543 int keyboard_read_input(ushort_t port,
546 struct vm_device * dev)
548 struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
553 KEYBOARD_DEBUG_PRINT("keyboard: read from input (60h): ");
555 PullFromOutputQueue(dev, &data);
557 if (state->state == RESET) {
558 // We just delivered the ack for the reset
559 // now we will ready ourselves to deliver the BAT code (success)
560 PushToOutputQueue(dev, 0xaa, 1);
561 state->state = NORMAL;
564 KEYBOARD_DEBUG_PRINT("0x%x\n", data);
566 *((uchar_t*)dest) = data;
570 KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from input (60h)\n");
576 int keyboard_interrupt(uint_t irq, struct vm_device * dev)
578 KEYBOARD_DEBUG_PRINT("keyboard: interrupt\n");
580 dev->vm->vm_ops.raise_irq(dev->vm, irq);
587 int keyboard_init_device(struct vm_device * dev)
590 // struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
592 KEYBOARD_DEBUG_PRINT("keyboard: init_device\n");
594 // Would read state here
596 keyboard_reset_device(dev);
599 dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
600 dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
602 #if KEYBOARD_DEBUG_80H
603 dev_hook_io(dev, KEYBOARD_DELAY_80H, &keyboard_read_delay, &keyboard_write_delay);
608 // We do not hook the IRQ here. Instead, the underlying device driver
609 // is responsible to call us back
615 int keyboard_deinit_device(struct vm_device *dev)
618 dev_unhook_io(dev, KEYBOARD_60H);
619 dev_unhook_io(dev, KEYBOARD_64H);
620 #if KEYBOARD_DEBUG_80H
621 dev_unhook_io(dev, KEYBOARD_DELAY_80H);
623 keyboard_reset_device(dev);
631 static struct vm_device_ops dev_ops = {
632 .init = keyboard_init_device,
633 .deinit = keyboard_deinit_device,
634 .reset = keyboard_reset_device,
635 .start = keyboard_start_device,
636 .stop = keyboard_stop_device,
642 struct vm_device *create_keyboard() {
644 if (thekeyboard != NULL) {
645 KEYBOARD_DEBUG_PRINT("keyboard: creating >1 keyboard device. This will probably fail!\n");
648 struct keyboard_internal * keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
650 struct vm_device *device = create_device("KEYBOARD", &dev_ops, keyboard_state);
652 thekeyboard = device;