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.


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