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.


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