Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fixes to get it to work in linux,
[palacios.git] / palacios / src / devices / keyboard.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <devices/keyboard.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_types.h>
23
24
25 #ifndef DEBUG_KEYBOARD
26 #undef PrintDebug
27 #define PrintDebug(fmt, args...)
28 #endif
29
30 #define KEYBOARD_DEBUG_80H   0
31
32
33
34 #define KEYBOARD_60H          0x60  // keyboard microcontroller
35 #define KEYBOARD_64H          0x64  // onboard microcontroller
36
37 #define KEYBOARD_DELAY_80H    0x80  // written for timing
38
39 #define KEYBOARD_IRQ          0x1
40 #define MOUSE_IRQ             0xc   
41
42
43 // extract bits for status byte
44 #define STATUS_OUTPUT_BUFFER_FULL   0x01  // 1=full (data for system)
45 #define STATUS_INPUT_BUFFER_FULL    0x02  // 1=full (data for 8042)
46 #define STATUS_SYSTEM               0x04  // 1=self-test-passed
47 #define STATUS_COMMAND_DATA_AVAIL   0x08  // internal: 0=data on 60h, 0=cmd on 64h
48 #define STATUS_ENABLED              0x10  // 1=keyboard is enabled
49 #define STATUS_MOUSE_BUFFER_FULL    0x20  // 1= mouse output buffer full
50 #define STATUS_TIMEOUT              0x40  // 1=timeout of keybd
51 #define STATUS_PARITY               0x80  // 1=parity error
52
53 // bits for cmd byte
54
55 #define CMD_INTR                0x01  // 1=interrupts enabled
56 #define CMD_MOUSE_INTR          0x02  // 1=interrupts enabled for mouse
57 #define CMD_SYSTEM              0x04  // 1= self test passed
58 #define CMD_OVERRIDE            0x08  // FORCE 0 for  PS2
59 #define CMD_DISABLE             0x10  // 1=disabled keyboard
60 #define CMD_MOUSE_DISABLE       0x20  // 1=disabled mouse
61 #define CMD_SCANCODE_XLATE      0x40  // 1=translate to set 1 scancodes
62 #define CMD_RESERVED            0x80  // should be zero
63
64 // bits for the output port 
65
66
67 #define OUTPUT_RESET        0x01  // System reset on 0
68 #define OUTPUT_A20          0x02  // A20 gate (1= A20 is gated)
69 #define OUTPUT_RES1         0x04  // reserved
70 #define OUTPUT_RES2         0x08  // reserved
71 #define OUTPUT_OUTPUT_FULL  0x10  // output buffer full
72 #define OUTPUT_INPUT_EMPTY  0x20  // input buffer empty
73 #define OUTPUT_KBD_CLOCK    0x40  // keyboard clock (?)
74 #define OUTPUT_KBD_DATA     0x80  // keyboard data
75
76 // bits for the input port
77
78 #define INPUT_RES0          0x01  // reserved
79 #define INPUT_RES1          0x02  // reserved
80 #define INPUT_RES2          0x04  // reserved
81 #define INPUT_RES3          0x08  // reserved
82 #define INPUT_RAM           0x10  // set to 1 if RAM exists?
83 #define INPUT_JUMPER        0x20  // manufacturing jumper?
84 #define INPUT_DISPLAY       0x40  // 0=color, 1=mono
85 #define INPUT_KBD_INHIBIT   0x80  // 1=inhibit keyboard ?
86
87
88 // for queue operations
89 #define QUEUE               0
90 #define OVERWRITE           1
91
92 // for queue operations - whether it's data or cmd waiting on 60h
93 #define DATA                0
94 #define COMMAND             1
95
96 // for queue operations - whether this is keyboard or mouse data on 60h
97 #define KEYBOARD            0
98 #define MOUSE               1
99
100
101
102 //#define QUEUE_SIZE          32
103
104
105 struct keyboard_internal {
106     // 
107     // 0x60 is the port for the keyboard microcontroller
108     //   writes are commands
109     //   reads from it usually return scancodes
110     //   however, it can also return other data 
111     //   depending on the state of the onboard microcontroller
112     //
113     // 0x64 is the port for the onboard microcontroller
114     //   writes are commands
115     //   reads are status
116     //
117
118     // state of the onboard microcontroller
119     // this is needed because sometimes 0x60 reads come
120     // from the onboard microcontroller
121     enum {// Normal mode measn we deliver keys
122         // to the vm and accept commands from it
123         NORMAL,
124         // after receiving cmd 0x60
125         // keybaord uC cmd will subsequently arrive
126         WRITING_CMD_BYTE,  
127         // after recieving 0xa5
128         // password arrives on data port, null terminated
129         TRANSMIT_PASSWD,
130         // after having reset sent to 0x60
131         // we immediately ack, and then
132         // push BAT success (0xaa) after the ack
133         RESET,
134         // after having a d1 sent to 64
135         // we wait for a new output byte on 60
136         WRITING_OUTPUT_PORT,
137         // after having a d2 sent to 64
138         // we wait for a new output byte on 60
139         // then make it available as a keystroke
140         INJECTING_KEY,
141         // after having a d3 sent to 64
142         // we wait for a new output byte on 60
143         // then make it available as a mouse event
144         INJECTING_MOUSE,
145         // after having a d4 sent to 64
146         // we wait for a new output byte on 60
147         // then send it to the mouse
148         IN_MOUSE,
149         // After the Keyboard LEDs are enabled
150         // we wait for the output byte on 64?
151         SET_LEDS,
152         // After the Keyboard SET_RATE is called
153         // we wait for the output byte on 64?
154         SET_RATE,
155         // The keyboard requests an ID which 
156         // generates 3 bytes of output...
157         KBD_ID1,
158         KBD_ID2,
159         
160         
161     } state;
162
163
164     enum {
165         // after receiving a mouse command 0f 0xff
166         // we return the ack and then the next thing will be the 
167         // bat code (aa - success)
168         RESET1,
169         // followed by the device id (00 - mouse)
170         RESET2, 
171         // Then it goes into stream mode
172         STREAM1,  //
173         STREAM2,  //
174         STREAM3,  // for each of the following bytes in mouse_packet
175         // this is used for setting sample rate
176         SAMPLE1,  
177         // this is used for getting device id
178         DEVICE1, 
179         // just like the stream moes
180         REMOTE1,
181         REMOTE2,
182         REMOTE3,
183         // For getting status info
184         STATUS1,
185         STATUS2,
186         STATUS3, 
187         // set resolution
188         SETRES1,
189     } mouse_state;
190
191
192     uchar_t wrap;             
193     uchar_t mouse_packet[3];  // byte 1: y over, xover, y sign, x sign, 1, middle, right, left
194     // byte 2: x movement
195     // byte 3: y movement
196
197     uchar_t mouse_needs_ack;  //
198     uchar_t mouse_done_after_ack; 
199
200     uchar_t cmd_byte;         //  for keyboard uC - read/written 
201     //     via read/write cmd byte command
202     uchar_t status_byte;      //  for on-board uC - read via 64h
203
204     uchar_t output_byte;      //  output port of onboard uC (e.g. A20)
205
206     uchar_t input_byte;       //  input port of onboard uC
207
208     // Data for 8042
209     uchar_t input_queue;      //  
210     uint_t  input_queue_len;  //  
211     //uint_t  input_queue_read;
212     //uint_t  input_queue_write;
213     // Data for system
214     uchar_t output_queue;     //  
215     uint_t  output_queue_len; //  
216     //uint_t  output_queue_read;
217     //uint_t  output_queue_write;
218
219
220 };
221
222
223 static int keyboard_interrupt(struct vm_device * dev, uint_t irq) {
224     PrintDebug("keyboard: interrupt 0x%x\n", irq);
225
226     v3_raise_irq(dev->vm, irq);
227
228     return 0;
229
230 }
231
232
233
234 // 
235 // push item onto outputqueue, optionally overwriting if there is no room
236 // returns 0 if successful
237 //
238 static int PushToOutputQueue(struct vm_device * dev, uchar_t value, uchar_t overwrite, uchar_t cmd, uchar_t mouse) 
239 {
240     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
241   
242     if ((state->output_queue_len == 0) || overwrite) { 
243     
244         state->output_queue = value;
245         state->output_queue_len = 1;
246     
247         if (cmd) {
248             state->status_byte |= STATUS_COMMAND_DATA_AVAIL;
249         } else {
250             state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
251         }
252     
253         if (mouse) { 
254             state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
255         } 
256
257         {
258             state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
259         }
260     
261         if (state->cmd_byte & CMD_INTR) { 
262             keyboard_interrupt(dev, KEYBOARD_IRQ);
263         }
264
265         return 0;
266
267     } else {
268         PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
269         return -1;
270     }
271 }
272
273 #if 1
274 // 
275 // pull item from outputqueue 
276 // returns 0 if successful
277 //
278 static int PullFromOutputQueue(struct vm_device * dev, uchar_t * value) 
279 {
280     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
281
282     if (1 || (state->output_queue_len == 1)) { 
283
284         *value = state->output_queue;
285         state->output_queue_len = 0;
286     
287         if (state->status_byte & STATUS_OUTPUT_BUFFER_FULL) { 
288             state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
289         } 
290     
291         if (state->status_byte & STATUS_MOUSE_BUFFER_FULL) { 
292             state->status_byte &= ~STATUS_MOUSE_BUFFER_FULL;
293         }
294     
295         if (state->status_byte & STATUS_COMMAND_DATA_AVAIL) { 
296             state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
297         } // reset to data
298     
299     
300         return 0;
301     } else {
302         PrintError("keyboard: PullFromOutputQueue Failed - Queue Empty\n");
303         return -1;
304     }
305 }
306 #endif
307
308 #if 0
309 // 
310 // push item onto inputqueue, optionally overwriting if there is no room
311 // returns 0 if successful
312 //
313 static int PushToInputQueue(struct vm_device * dev, uchar_t value, uchar_t overwrite) 
314 {
315     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
316
317     if ((state->input_queue_len == 0) || overwrite) { 
318
319         state->input_queue = value;
320         state->input_queue_len = 1;
321         state->status_byte |= STATUS_INPUT_BUFFER_FULL;
322
323         return 0;
324     } else {
325         PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
326         return -1;
327     }
328 }
329
330 // 
331 // pull item from inputqueue 
332 // returns 0 if successful
333 //
334 static int PullFromInputQueue(struct vm_device *dev, uchar_t *value) 
335 {
336     struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
337
338     if (state->input_queue_len == 1) { 
339
340         *value = state->input_queue;
341         state->input_queue_len = 0;
342         state->status_byte &= ~STATUS_INPUT_BUFFER_FULL;
343
344         return 0;
345     } else {
346         PrintError("keyboard: PullFromInputQueue Failed - Queue Empty\n");
347         return -1;
348     }
349 }
350
351 #endif
352
353
354
355
356
357
358
359 static int key_event_handler(struct guest_info * info, 
360                              struct v3_keyboard_event * evt, 
361                              void * private_data) {
362     struct vm_device * dev = (struct vm_device *)private_data;
363     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
364
365     PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code);
366   
367     if ( (state->status_byte & STATUS_ENABLED)      // onboard is enabled
368          && (!(state->cmd_byte & CMD_DISABLE)) )  {   // keyboard is enabled
369     
370         PushToOutputQueue(dev, evt->scan_code, OVERWRITE, DATA, KEYBOARD);
371     
372         if (state->cmd_byte & CMD_INTR) { 
373             keyboard_interrupt(dev, KEYBOARD_IRQ);
374         }
375     }
376   
377     return 0;
378 }
379
380
381 static int mouse_event_handler(struct guest_info * info, 
382                                struct v3_mouse_event * evt, 
383                                void * private_data) {
384     struct vm_device * dev = (struct vm_device *)private_data;
385     struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
386
387     PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n",
388                evt->data[0], evt->data[1], evt->data[2]);
389   
390     memcpy(state->mouse_packet, evt->data, 3);
391   
392     state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
393   
394     
395     switch (state->mouse_state) { 
396         case STREAM1:
397         case STREAM2:
398         case STREAM3:
399             if (!(state->cmd_byte & CMD_MOUSE_DISABLE)) { 
400                 keyboard_interrupt(dev, MOUSE_IRQ);
401             }
402             break;
403         default:
404             return -1;
405             break;
406     }
407
408     return 0;
409 }
410
411
412 static int keyboard_reset_device(struct vm_device * dev)
413 {
414     struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
415   
416     memset(data, 0, sizeof(struct keyboard_internal));
417
418     data->state = NORMAL;
419     data->mouse_state = STREAM1;
420
421     data->cmd_byte =  
422         CMD_INTR          // interrupts on
423         | CMD_MOUSE_INTR  // mouse interupts on
424         | CMD_SYSTEM ;    // self test passed
425     // PS2, keyboard+mouse enabled, generic translation    
426   
427     data->status_byte = 
428         STATUS_SYSTEM       // self-tests passed
429         | STATUS_ENABLED ;  // keyboard ready
430     // buffers empty, no errors
431
432     data->output_byte = 0;  //  ?
433
434     data->input_byte = INPUT_RAM;  // we have some
435     // also display=color, jumper 0, keyboard enabled 
436
437   
438
439     PrintDebug("keyboard: reset device\n");
440  
441     return 0;
442
443 }
444
445
446
447 static int keyboard_start_device(struct vm_device *dev)
448 {
449     PrintDebug("keyboard: start device\n");
450     return 0;
451 }
452
453
454 static int keyboard_stop_device(struct vm_device *dev)
455 {
456     PrintDebug("keyboard: stop device\n");
457     return 0;
458 }
459
460
461 static int mouse_read_input(struct vm_device *dev)
462 {
463     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
464
465     if (state->mouse_needs_ack) { 
466         state->mouse_needs_ack = 0;
467
468         // the ack has been stuffed previously
469         if (state->mouse_done_after_ack) { 
470             return 1;
471         } else {
472             return 0;
473         }
474     }
475
476     switch (state->mouse_state) { 
477
478         case RESET1: // requesting the BAT code
479             PushToOutputQueue(dev, 0xaa, OVERWRITE, DATA, MOUSE) ;  // BAT successful
480             PrintDebug(" mouse sent BAT code (sucesssful) ");
481             state->mouse_state = RESET2;
482
483             return 0;  // not done with mouse processing yet
484             break;
485
486         case RESET2: // requesting the device id
487             PushToOutputQueue(dev, 0x00, OVERWRITE, DATA, MOUSE) ;  // normal mouse type
488             PrintDebug(" mouse sent device id ");
489             state->mouse_state = STREAM1;
490
491             return 1;  // done with mouse processing 
492             break;
493
494         case STREAM1: // send data
495             PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE); 
496             PrintDebug(" mouse sent stream data1 ");
497             state->mouse_state = STREAM2;
498
499             return 0;
500             break;
501
502         case STREAM2: // send data
503             PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE); 
504             PrintDebug(" mouse sent stream data2 ");
505             state->mouse_state = STREAM3;
506
507             return 0;
508             break;
509
510         case STREAM3: // send data
511             PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE); 
512             PrintDebug(" mouse sent stream data3 ");
513             state->mouse_state = STREAM1;
514
515             return 1; // now done
516             break;
517
518         case REMOTE1: // send data
519             PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE); 
520             PrintDebug(" mouse sent remote data1 ");
521             state->mouse_state = REMOTE2;
522
523             return 0;
524             break;
525
526         case REMOTE2: // send data
527             PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE); 
528             PrintDebug(" mouse sent remote data2 ");
529             state->mouse_state = REMOTE3;
530
531             return 0;
532             break;
533
534         case REMOTE3: // send data
535             PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE); 
536             PrintDebug(" mouse sent remote data3 ");
537             state->mouse_state = REMOTE1;
538
539             return 1; // now done
540             break;
541
542         case STATUS1: // send data
543             PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE); 
544             PrintDebug(" mouse sent status data1 ");
545             state->mouse_state = STATUS2;
546
547             return 0;
548             break;
549
550         case STATUS2: // send data
551             PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE); 
552             PrintDebug(" mouse sent status data2 ");
553             state->mouse_state = STATUS3;
554
555             return 0;
556             break;
557
558         case STATUS3: // send data
559             PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE); 
560             PrintDebug(" mouse sent status data3 ");
561             state->mouse_state = STREAM1;
562
563             return 1; // now done
564             break;
565
566         case DEVICE1: // send device id
567             PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE); 
568             PrintDebug(" mouse sent device id ");
569             state->mouse_state = STREAM1;
570
571             return 1; // now done
572             break;
573
574         default:
575             PrintDebug(" mouse has no data ");
576             return 1; // done
577             break;
578     }
579 }
580
581 static int mouse_write_output(struct vm_device * dev, uchar_t data)
582 {
583     struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
584
585     switch (state->mouse_state) { 
586         case STREAM1:
587         case STREAM2:
588         case STREAM3:
589         case REMOTE1:
590         case REMOTE2:
591         case REMOTE3:
592             switch (data) {
593
594                 case 0xff: //reset
595                     PushToOutputQueue(dev, 0xfe, OVERWRITE, DATA, MOUSE) ;   // no mouse!
596                     PrintDebug(" mouse reset begins (no mouse) ");
597
598                     return 1;  // not done;
599                     break;
600
601                     /*
602                       case 0xff: //reset
603                       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
604                       PrintDebug(" mouse reset begins ");
605                       state->mouse_done_after_ack=0;
606                       state->mouse_needs_ack=1;
607                       state->mouse_state=RESET1;
608                       return 0;  // not done;
609                       break;
610                     */
611                 case 0xfe: //resend
612                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
613                     PrintDebug(" mouse resend begins ");
614                     state->mouse_done_after_ack = 0;
615                     state->mouse_needs_ack = 0;
616                     state->mouse_state = STREAM1;
617                     return 0;  // not done
618                     break;
619       
620                 case 0xf6: // set defaults
621                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
622                     PrintDebug(" mouse set defaults ");
623                     state->mouse_done_after_ack = 1;
624                     state->mouse_needs_ack = 1;
625                     state->mouse_state = STREAM1;
626                     return 0; // not done
627                     break;
628       
629                 case 0xf5: // disable data reporting 
630                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
631                     state->mouse_done_after_ack = 1;
632                     state->mouse_needs_ack = 1;
633                     PrintDebug(" mouse disable data reporting ");
634                     state->mouse_state = STREAM1;
635                     return 0; // not done
636                     break;
637       
638                 case 0xf4: // enable data reporting 
639                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
640                     state->mouse_done_after_ack = 1;
641                     state->mouse_needs_ack = 1;
642                     PrintDebug(" mouse enable data reporting ");
643                     state->mouse_state = STREAM1;
644                     return 0; // not done
645                     break;
646       
647                 case 0xf3: // set sample rate
648                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
649                     state->mouse_done_after_ack = 0;
650                     state->mouse_needs_ack = 1;
651                     PrintDebug(" mouse set sample rate begins ");
652                     state->mouse_state = SAMPLE1;
653                     return 0; // not done
654                     break;
655       
656                 case 0xf2: // get device id
657                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
658                     state->mouse_done_after_ack = 0;
659                     state->mouse_needs_ack = 1;
660                     PrintDebug(" mouse get device id begins ");
661                     state->mouse_state = DEVICE1;
662                     return 0; // not done
663                     break;
664       
665                 case 0xf0: // set remote mode
666                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
667                     state->mouse_done_after_ack = 1;
668                     state->mouse_needs_ack = 1;
669                     PrintDebug(" mouse set remote mode  ");
670                     state->mouse_state = REMOTE1;
671                     return 0; // not done
672                     break;
673
674                 case 0xee: // set wrap mode
675                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
676                     state->mouse_done_after_ack = 1;
677                     state->mouse_needs_ack = 1;
678                     PrintDebug(" mouse set wrap mode (ignored)  ");
679                     state->mouse_state = STREAM1;
680                     return 0; // not done
681                     break;
682
683                 case 0xec: // reset wrap mode
684                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
685                     state->mouse_done_after_ack = 1;
686                     state->mouse_needs_ack = 1;
687                     PrintDebug(" mouse reset wrap mode (ignored)  ");
688                     state->mouse_state = STREAM1;
689                     return 0; // done
690                     break;
691
692                 case 0xeb: // read data
693                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
694                     state->mouse_done_after_ack = 0;
695                     state->mouse_needs_ack = 1;
696                     PrintDebug(" mouse switch to wrap mode (ignored)  ");
697                     state->mouse_state = REMOTE1;
698                     return 0; // not done
699                     break;
700       
701                 case 0xea: // set stream mode
702                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
703                     state->mouse_done_after_ack = 1;
704                     state->mouse_needs_ack = 1;
705                     PrintDebug(" mouse set stream mode  ");
706                     state->mouse_state = STREAM1;
707                     return 0; // not done
708                     break;
709
710                 case 0xe9: // status request
711                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
712                     state->mouse_done_after_ack = 0;
713                     state->mouse_needs_ack = 1;
714                     PrintDebug(" mouse status request begins  ");
715                     state->mouse_state = STATUS1;
716                     return 0; // notdone
717                     break;
718
719                 case 0xe8: // set resolution
720                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
721                     state->mouse_done_after_ack = 0;
722                     state->mouse_needs_ack = 1;
723                     PrintDebug(" mouse set resolution begins  ");
724                     state->mouse_state = SETRES1;
725                     return 0; // notdone
726                     break;
727
728                 case 0xe7: // set scaling 2:1
729                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
730                     state->mouse_done_after_ack = 1;
731                     state->mouse_needs_ack = 1;
732                     PrintDebug(" mouse set scaling 2:1 ");
733                     state->mouse_state = STREAM1;
734                     return 0; // not done
735                     break;
736
737                 case 0xe6: // set scaling 1:1
738                     PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ; 
739                     state->mouse_done_after_ack = 1;
740                     state->mouse_needs_ack = 1;
741                     PrintDebug(" mouse set scaling 1:1 ");
742                     state->mouse_state = STREAM1;
743                     return 0; // done
744                     break;
745       
746                 default:
747                     PrintDebug(" receiving unknown mouse command (0x%x) in acceptable state ", data);
748                     return 1; // done
749                     break;
750
751             }
752     
753         default:
754             PrintDebug(" receiving mouse output in unhandled state (0x%x) ", state->mouse_state);
755             break;
756             return 1; // done?
757             break;
758     }
759
760     PrintDebug(" HUH? ");
761     return 1; // done
762 }
763
764
765
766 #if KEYBOARD_DEBUG_80H
767 static int keyboard_write_delay(ushort_t port,
768                                 void * src, 
769                                 uint_t length,
770                                 struct vm_device * dev)
771 {
772
773     if (length == 1) { 
774         PrintDebug("keyboard: write of 0x%x to 80h\n", *((uchar_t*)src));
775
776         return 1;
777     } else {
778         PrintDebug("keyboard: write of >1 byte to 80h\n", *((uchar_t*)src));
779
780         return length;
781     }
782 }
783
784 static int keyboard_read_delay(ushort_t port,
785                                void * dest, 
786                                uint_t length,
787                                struct vm_device * dev)
788 {
789
790     if (length == 1) { 
791         *((uchar_t*)dest) = v3_inb(port);
792
793         PrintDebug("keyboard: read of 0x%x from 80h\n", *((uchar_t*)dest));
794
795         return 1;
796     } else {
797         PrintDebug("keyboard: read of >1 byte from 80h\n");
798
799         return length;
800     }
801 }
802 #endif
803     
804   
805
806
807
808 static int keyboard_write_command(ushort_t port,
809                                   void * src, 
810                                   uint_t length,
811                                   struct vm_device * dev)
812 {
813     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
814     uchar_t cmd;
815
816     // Should always be single byte write
817
818     if (length != 1) { 
819         PrintError("keyboard: write of >1 bytes (%d) to 64h\n", length);
820         return -1;
821     }
822
823     cmd = *((uchar_t*)src); 
824
825     if (state->state != NORMAL) { 
826         PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n");
827     }
828   
829     PrintDebug("keyboard: command 0x%x on 64h\n", cmd);
830
831     switch (cmd) { 
832
833         case 0x20:  // READ COMMAND BYTE (returned in 60h)
834             PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND,KEYBOARD);
835             state->state = NORMAL;  // the next read on 0x60 will get the right data
836             PrintDebug("keyboard: command byte 0x%x returned\n", state->cmd_byte);
837             break;
838
839         case 0x60:  // WRITE COMMAND BYTE (read from 60h)
840             state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
841             PrintDebug("keyboard: prepare to write command byte\n");
842             break;
843
844             // case 0x90-9f - write to output port  (?)
845
846         case 0xa1: // Get version number
847             PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
848             state->state = NORMAL;
849             PrintDebug("keyboard: version number 0x0 returned\n");
850             break;
851
852         case 0xa4:  // is password installed?  send result to 0x60
853             // we don't support passwords
854             PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND, KEYBOARD);
855             PrintDebug("keyboard: password not installed\n");
856             state->state = NORMAL;
857             break;
858
859         case 0xa5:  // new password will arrive on 0x60
860             state->state = TRANSMIT_PASSWD;
861             PrintDebug("keyboard: pepare to transmit password\n");
862             break;
863
864         case 0xa6:  // check passwd;
865             // since we do not support passwords, we will simply ignore this
866             // the implication is that any password check immediately succeeds 
867             // with a blank password
868             state->state = NORMAL;
869             PrintDebug("keyboard: password check succeeded\n");
870             break;
871
872         case 0xa7:  // disable mouse
873             state->cmd_byte |= CMD_MOUSE_DISABLE;
874             state->state = NORMAL;
875             PrintDebug("keyboard: mouse disabled\n");
876             break;
877
878         case 0xa8:  // enable mouse
879             state->cmd_byte &= ~CMD_MOUSE_DISABLE;
880             state->state = NORMAL;
881             PrintDebug("keyboard: mouse enabled\n");
882             break;
883
884         case 0xa9:  // mouse interface test  (always succeeds)
885             PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
886             PrintDebug("keyboard: mouse interface test succeeded\n");
887             state->state = NORMAL;
888             break;
889
890         case 0xaa:  // controller self test (always succeeds)
891             PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND, KEYBOARD);
892             PrintDebug("keyboard: controller self test succeeded\n");
893             state->state = NORMAL;
894             break;
895
896         case 0xab:  // keyboard interface test (always succeeds)
897             PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
898             state->state = NORMAL;
899             PrintDebug("keyboard: keyboard interface test succeeded\n");
900             break;
901
902         case 0xad:  // disable keyboard
903             state->cmd_byte |= CMD_DISABLE;
904             state->state = NORMAL;
905             PrintDebug("keyboard: keyboard disabled\n");
906             break;
907
908         case 0xae:  // enable keyboard
909             state->cmd_byte &= ~CMD_DISABLE;
910             state->state = NORMAL;
911             PrintDebug("keyboard: keyboard enabled\n");
912             break;
913
914         case 0xaf:  // get version
915             PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND, KEYBOARD);
916             state->state = NORMAL;
917             PrintDebug("keyboard: version 0 returned \n");
918             break;
919
920         case 0xd0: // return microcontroller output on 60h
921             PushToOutputQueue(dev, state->output_byte, OVERWRITE, COMMAND, KEYBOARD);
922             state->state = NORMAL;
923             PrintDebug("keyboard: output byte 0x%x returned\n", state->output_byte);
924             break;
925
926         case 0xd1: // request to write next byte on 60h to the microcontroller output port
927             state->state = WRITING_OUTPUT_PORT;
928             PrintDebug("keyboard: prepare to write output byte\n");
929             break;
930
931         case 0xd2:  //  write keyboard buffer (inject key)
932             state->state = INJECTING_KEY;
933             PrintDebug("keyboard: prepare to inject key\n");
934             break;
935
936         case 0xd3: //  write mouse buffer (inject mouse)
937             state->state = INJECTING_MOUSE;
938             PrintDebug("keyboard: prepare to inject mouse\n");
939             break;
940
941         case 0xd4: // write mouse device (command to mouse?)
942             state->state = IN_MOUSE;
943             PrintDebug("keyboard: prepare to inject mouse command\n");
944             break;
945
946         case 0xc0: //  read input port 
947             PushToOutputQueue(dev, state->input_byte, OVERWRITE, COMMAND, KEYBOARD);
948             state->state = NORMAL;
949             PrintDebug("keyboard: input byte 0x%x returned\n", state->input_byte);
950             break;
951
952         case 0xc1:  //copy input port lsn to status msn
953             state->status_byte &= 0x0f;
954             state->status_byte |= (state->input_byte & 0xf) << 4;
955             state->state = NORMAL;
956             PrintDebug("keyboard: copied input byte lsn to status msn\n");
957             break;
958
959         case 0xc2: // copy input port msn to status msn
960             state->status_byte &= 0x0f;
961             state->status_byte |= (state->input_byte & 0xf0);
962             state->state = NORMAL;
963             PrintDebug("keyboard: copied input byte msn to status msn\n");
964             break;
965     
966         case 0xe0: // read test port
967             PushToOutputQueue(dev, state->output_byte >> 6, OVERWRITE, COMMAND, KEYBOARD);
968             state->state = NORMAL;
969             PrintDebug("keyboard: read 0x%x from test port\n", state->output_byte >> 6);
970             break;
971
972    
973         case 0xf0:   // pulse output port
974         case 0xf1:   // this should pulse 0..3 of cmd_byte on output port 
975         case 0xf2:   // instead of what is currently in output_byte (I think)
976         case 0xf3:   // main effect is taht if bit zero is zero
977         case 0xf4:   // should cause reset
978         case 0xf5:   // I doubt anything more recent than a 286 running 
979         case 0xf6:   // OS2 with the penalty box will care
980         case 0xf7:
981         case 0xf8:
982         case 0xf9:
983         case 0xfa:
984         case 0xfb:
985         case 0xfc:
986         case 0xfd:
987         case 0xfe:
988         case 0xff:
989   
990             PrintDebug("keyboard: ignoring pulse of 0x%x (low=pulsed) on output port\n", (cmd & 0xf));
991             state->state = NORMAL;
992             break;
993    
994
995             // case ac  diagonstic - returns 16 bytes from keyboard microcontroler on 60h
996         default:
997             PrintDebug("keyboard: ignoring command (unimplemented)\n");
998             state->state = NORMAL;
999             break;
1000     }
1001
1002     return 1;
1003
1004 }
1005
1006 static int keyboard_read_status(ushort_t port,
1007                                 void * dest, 
1008                                 uint_t length,
1009                                 struct vm_device * dev)
1010 {
1011     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
1012
1013     if (length == 1) { 
1014
1015         PrintDebug("keyboard: read status (64h): ");
1016
1017         *((uchar_t*)dest) = state->status_byte;
1018
1019         PrintDebug("0x%x\n", *((uchar_t*)dest));
1020
1021         return 1;
1022     } else {
1023         PrintError("keyboard: >1 byte read for status (64h)\n");
1024         return -1;
1025     }
1026 }
1027
1028 static int keyboard_write_output(ushort_t port,
1029                                  void * src, 
1030                                  uint_t length,
1031                                  struct vm_device * dev)
1032 {
1033     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
1034
1035     if (length != 1) { 
1036         PrintError("keyboard: write of 60h with >1 byte\n");
1037         return -1;
1038     }
1039
1040     uchar_t data = *((uchar_t*)src);
1041   
1042     PrintDebug("keyboard: output 0x%x on 60h\n", data);
1043
1044     switch (state->state) {
1045         case WRITING_CMD_BYTE:
1046             state->cmd_byte = data;
1047             state->state = NORMAL;
1048             PrintDebug("keyboard: wrote new command byte 0x%x\n", state->cmd_byte);
1049             break;
1050         case WRITING_OUTPUT_PORT:
1051             state->output_byte = data;
1052             state->state = NORMAL;
1053             PrintDebug("keyboard: wrote new output byte 0x%x\n", state->output_byte);
1054             break;
1055         case INJECTING_KEY:
1056             PushToOutputQueue(dev, data, OVERWRITE, COMMAND, KEYBOARD);  // probably should be a call to deliver_key_to_vmm()
1057             state->state = NORMAL;
1058             PrintDebug("keyboard: injected key 0x%x\n", data);
1059             break;
1060         case INJECTING_MOUSE:
1061             PushToOutputQueue(dev, data, OVERWRITE, DATA, MOUSE);
1062             //      PrintDebug("keyboard: ignoring injected mouse event 0x%x\n", data);
1063             PrintDebug("keyboard: injected mouse event 0x%x\n", data);
1064             state->state = NORMAL;
1065             break;
1066         case IN_MOUSE:
1067             PrintDebug("keyboard: mouse action: ");
1068             if (mouse_write_output(dev, data)) { 
1069                 state->state = NORMAL;
1070             }
1071             PrintDebug("\n");
1072             break;
1073         case TRANSMIT_PASSWD:
1074             if (data) {
1075                 //ignore passwd
1076                 PrintDebug("keyboard: ignoring password character 0x%x\n",data);
1077             } else {
1078                 // end of password
1079                 state->state = NORMAL;
1080                 PrintDebug("keyboard: done with password\n");
1081             }
1082             break;
1083         case SET_LEDS:
1084             PrintDebug("Keyboard: LEDs being set...\n");
1085             PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1086             state->state = NORMAL;
1087             break;
1088         case SET_RATE:
1089             PrintDebug("Keyboard: Rate being set...\n");
1090             PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1091             state->state = NORMAL;
1092             break;
1093         default:
1094         case NORMAL:
1095             {
1096                 // command is being sent to keyboard controller
1097                 switch (data) { 
1098                     case 0xff: // reset
1099                         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD); // ack
1100                         state->state = RESET;
1101                         PrintDebug("keyboard: reset complete and acked\n");
1102                         break;
1103                     case 0xf5: // disable scanning
1104                     case 0xf4: // enable scanning
1105                         // ack
1106                         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1107                         // should do something here... PAD
1108                         state->state = NORMAL;
1109                         PrintDebug("keyboard: %s scanning done and acked\n", (data == 0xf5) ? "disable" : "enable");
1110                         break;
1111                     case 0xf3:
1112                         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1113                         state->state = SET_RATE;
1114                         break;
1115                     case 0xf2: // get keyboard ID
1116                         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1117                         state->state = KBD_ID1;
1118                         PrintDebug("Keyboard: Requesting Keyboard ID\n");
1119
1120                         //PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD);
1121                         //state->state = KBD_ID2;
1122                         break;
1123                     case 0xed: // enable keyboard LEDs
1124                         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
1125                         state->state = SET_LEDS;
1126                         break;
1127                     case 0xfe: // resend
1128                     case 0xfd: // set key type make
1129                     case 0xfc: // set key typ make/break
1130                     case 0xfb: // set key type typematic
1131                     case 0xfa: // set all typematic make/break/typematic
1132                     case 0xf9: // set all make
1133                     case 0xf8: // set all make/break
1134                     case 0xf7: // set all typemaktic
1135                     case 0xf6: // set defaults
1136                         PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data);
1137                         return -1;
1138                         break;
1139                     default:
1140                         PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
1141                         state->status_byte |= 0x1;
1142                         return -1;
1143                         break;
1144                 }
1145                 break;
1146             }
1147
1148     }
1149   
1150     return 1;
1151 }
1152
1153 static int keyboard_read_input(ushort_t port,
1154                                void * dest, 
1155                                uint_t length,
1156                                struct vm_device * dev)
1157 {
1158     struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
1159
1160     if (length == 1) { 
1161         uchar_t data;
1162         int done_mouse;
1163
1164         PrintDebug("keyboard: read from input (60h): ");
1165
1166         if (state->state == IN_MOUSE) { 
1167             done_mouse = mouse_read_input(dev);
1168             if (done_mouse) { 
1169                 state->state = NORMAL;
1170             }
1171         } 
1172       
1173         PullFromOutputQueue(dev, &data);
1174       
1175         if (state->state == RESET) { 
1176             // We just delivered the ack for the reset
1177             // now we will ready ourselves to deliver the BAT code (success)
1178             PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD);
1179             state->state = NORMAL;
1180             PrintDebug(" (in reset, pushing BAT test code 0xaa) ");
1181         } else if (state->state == KBD_ID1) {
1182             PushToOutputQueue(dev, 0xab, OVERWRITE, COMMAND, KEYBOARD);
1183             state->state = KBD_ID2;
1184             PrintDebug(" (in kbd id request, pushing 1st ID val) ");
1185         } else if (state->state == KBD_ID2) {
1186             PushToOutputQueue(dev, 0x83, OVERWRITE, COMMAND, KEYBOARD);
1187             state->state = NORMAL;
1188             PrintDebug(" (in kbd id request, pushing 2nd ID val) ");
1189         }
1190
1191         PrintDebug("0x%x\n", data);
1192
1193         *((uchar_t*)dest) = data;
1194     
1195         return 1;
1196     } else {
1197         PrintError("keyboard: unknown size read from input (60h)\n");
1198         return -1;
1199     }
1200 }
1201
1202
1203
1204
1205
1206 static int keyboard_init_device(struct vm_device * dev) 
1207 {
1208  
1209     //  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
1210
1211     PrintDebug("keyboard: init_device\n");
1212
1213     // Would read state here
1214
1215     keyboard_reset_device(dev);
1216
1217     // hook ports
1218     v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
1219     v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
1220
1221     v3_hook_host_event(dev->vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), dev);
1222     v3_hook_host_event(dev->vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), dev);
1223
1224
1225 #if KEYBOARD_DEBUG_80H
1226     v3_dev_hook_io(dev, KEYBOARD_DELAY_80H, &keyboard_read_delay, &keyboard_write_delay);
1227 #endif
1228
1229   
1230     //
1231     // We do not hook the IRQ here.  Instead, the underlying device driver
1232     // is responsible to call us back
1233     // 
1234
1235     return 0;
1236 }
1237
1238 static int keyboard_deinit_device(struct vm_device *dev)
1239 {
1240
1241     v3_dev_unhook_io(dev, KEYBOARD_60H);
1242     v3_dev_unhook_io(dev, KEYBOARD_64H);
1243 #if KEYBOARD_DEBUG_80H
1244     v3_dev_unhook_io(dev, KEYBOARD_DELAY_80H);
1245 #endif
1246     keyboard_reset_device(dev);
1247     return 0;
1248 }
1249
1250
1251
1252
1253
1254 static struct vm_device_ops dev_ops = { 
1255     .init = keyboard_init_device, 
1256     .deinit = keyboard_deinit_device,
1257     .reset = keyboard_reset_device,
1258     .start = keyboard_start_device,
1259     .stop = keyboard_stop_device,
1260 };
1261
1262
1263
1264
1265 struct vm_device * v3_create_keyboard() {
1266     struct keyboard_internal * keyboard_state = NULL;
1267
1268     keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
1269
1270     struct vm_device *device = v3_create_device("KEYBOARD", &dev_ops, keyboard_state);
1271
1272
1273     return device;
1274 }