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.


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