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.


added new debugging directives
[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",data[0],data[1],data[2]);
350   
351   memcpy(state->mouse_packet,data,3);
352   
353   state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
354   
355     
356   switch (state->mouse_state) { 
357   case STREAM1:
358   case STREAM2:
359   case STREAM3:
360     if (!(state->cmd_byte & CMD_MOUSE_DISABLE)) { 
361       keyboard_interrupt(MOUSE_IRQ,dev);
362     }
363     break;
364   default:
365     break;
366   }
367
368 }
369
370
371 int keyboard_reset_device(struct vm_device * dev)
372 {
373   struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
374   
375   memset(data, 0, sizeof(struct keyboard_internal));
376
377   data->state = NORMAL;
378   data->mouse_state=STREAM1;
379
380   data->cmd_byte =   
381       CMD_INTR        // interrupts on
382     | CMD_MOUSE_INTR  // mouse interupts on
383     | CMD_SYSTEM ;    // self test passed
384                       // PS2, keyboard+mouse enabled, generic translation    
385   
386   data->status_byte = 
387       STATUS_SYSTEM     // self-tests passed
388     | STATUS_ENABLED ;  // keyboard ready
389                         // buffers empty, no errors
390
391   data->output_byte = 0;  //  ?
392
393   data->input_byte = 
394     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     // the ack has been stuffed previously
428     if (state->mouse_done_after_ack) { 
429       return 1;
430     } else {
431       return 0;
432     }
433   }
434
435   switch (state->mouse_state) { 
436   case RESET1: // requesting the BAT code
437     PushToOutputQueue(dev,0xaa,OVERWRITE,DATA,MOUSE) ;  // BAT successful
438     PrintDebug(" mouse sent BAT code (sucesssful) ");
439     state->mouse_state=RESET2;
440     return 0;  // not done with mouse processing yet
441     break;
442   case RESET2: // requesting the device id
443     PushToOutputQueue(dev,0x00,OVERWRITE,DATA,MOUSE) ;  // normal mouse type
444     PrintDebug(" mouse sent device id ");
445     state->mouse_state=STREAM1;
446     return 1;  // done with mouse processing 
447     break;
448   case STREAM1: // send data
449     PushToOutputQueue(dev,state->mouse_packet[0],OVERWRITE,DATA,MOUSE); 
450     PrintDebug(" mouse sent stream data1 ");
451     state->mouse_state=STREAM2;
452     return 0;
453     break;
454   case STREAM2: // send data
455     PushToOutputQueue(dev,state->mouse_packet[1],OVERWRITE,DATA,MOUSE); 
456     PrintDebug(" mouse sent stream data2 ");
457     state->mouse_state=STREAM3;
458     return 0;
459     break;
460   case STREAM3: // send data
461     PushToOutputQueue(dev,state->mouse_packet[2],OVERWRITE,DATA,MOUSE); 
462     PrintDebug(" mouse sent stream data3 ");
463     state->mouse_state=STREAM1;
464     return 1; // now done
465     break;
466   case REMOTE1: // send data
467     PushToOutputQueue(dev,state->mouse_packet[0],OVERWRITE,DATA,MOUSE); 
468     PrintDebug(" mouse sent remote data1 ");
469     state->mouse_state=REMOTE2;
470     return 0;
471     break;
472   case REMOTE2: // send data
473     PushToOutputQueue(dev,state->mouse_packet[1],OVERWRITE,DATA,MOUSE); 
474     PrintDebug(" mouse sent remote data2 ");
475     state->mouse_state=REMOTE3;
476     return 0;
477     break;
478   case REMOTE3: // send data
479     PushToOutputQueue(dev,state->mouse_packet[2],OVERWRITE,DATA,MOUSE); 
480     PrintDebug(" mouse sent remote data3 ");
481     state->mouse_state=REMOTE1;
482     return 1; // now done
483     break;
484   case STATUS1: // send data
485     PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
486     PrintDebug(" mouse sent status data1 ");
487     state->mouse_state=STATUS2;
488     return 0;
489     break;
490   case STATUS2: // send data
491     PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
492     PrintDebug(" mouse sent status data2 ");
493     state->mouse_state=STATUS3;
494     return 0;
495     break;
496   case STATUS3: // send data
497     PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
498     PrintDebug(" mouse sent status data3 ");
499     state->mouse_state=STREAM1;
500     return 1; // now done
501     break;
502   case DEVICE1: // send device id
503     PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
504     PrintDebug(" mouse sent device id ");
505     state->mouse_state=STREAM1;
506     return 1; // now done
507     break;
508   default:
509     PrintDebug(" mouse has no data ");
510     return 1; // done
511     break;
512   }
513 }
514
515 int mouse_write_output(struct vm_device *dev, uchar_t data)
516 {
517   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
518
519   switch (state->mouse_state) { 
520   case STREAM1:
521   case STREAM2:
522   case STREAM3:
523   case REMOTE1:
524   case REMOTE2:
525   case REMOTE3:
526     switch (data) {
527
528     case 0xff: //reset
529       PushToOutputQueue(dev,0xfe,OVERWRITE,DATA,MOUSE) ;   // no mouse!
530       PrintDebug(" mouse reset begins (no mouse) ");
531       return 1;  // not done;
532       break;
533
534       /*
535     case 0xff: //reset
536       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
537       PrintDebug(" mouse reset begins ");
538       state->mouse_done_after_ack=0;
539       state->mouse_needs_ack=1;
540       state->mouse_state=RESET1;
541       return 0;  // not done;
542       break;
543       */
544     case 0xfe: //resend
545       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
546       PrintDebug(" mouse resend begins ");
547       state->mouse_done_after_ack=0;
548       state->mouse_needs_ack=0;
549       state->mouse_state=STREAM1;
550       return 0;  // not done
551       break;
552       
553     case 0xf6: // set defaults
554       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
555       PrintDebug(" mouse set defaults ");
556       state->mouse_done_after_ack=1;
557       state->mouse_needs_ack=1;
558       state->mouse_state=STREAM1;
559       return 0; // not done
560       break;
561       
562     case 0xf5: // disable data reporting 
563       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
564       state->mouse_done_after_ack=1;
565       state->mouse_needs_ack=1;
566       PrintDebug(" mouse disable data reporting ");
567       state->mouse_state=STREAM1;
568       return 0; // not done
569       break;
570       
571     case 0xf4: // enable data reporting 
572       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
573       state->mouse_done_after_ack=1;
574       state->mouse_needs_ack=1;
575       PrintDebug(" mouse enable data reporting ");
576       state->mouse_state=STREAM1;
577       return 0; // not done
578       break;
579       
580     case 0xf3: // set sample rate
581       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
582       state->mouse_done_after_ack=0;
583       state->mouse_needs_ack=1;
584       PrintDebug(" mouse set sample rate begins ");
585       state->mouse_state=SAMPLE1;
586       return 0; // not done
587       break;
588       
589     case 0xf2: // get device id
590       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
591       state->mouse_done_after_ack=0;
592       state->mouse_needs_ack=1;
593       PrintDebug(" mouse get device id begins ");
594       state->mouse_state=DEVICE1;
595       return 0; // not done
596       break;
597       
598     case 0xf0: // set remote mode
599       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
600       state->mouse_done_after_ack=1;
601       state->mouse_needs_ack=1;
602       PrintDebug(" mouse set remote mode  ");
603       state->mouse_state=REMOTE1;
604       return 0; // not done
605       break;
606
607     case 0xee: // set wrap mode
608       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
609       state->mouse_done_after_ack=1;
610       state->mouse_needs_ack=1;
611       PrintDebug(" mouse set wrap mode (ignored)  ");
612       state->mouse_state=STREAM1;
613       return 0; // not done
614       break;
615
616     case 0xec: // reset wrap mode
617       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
618       state->mouse_done_after_ack=1;
619       state->mouse_needs_ack=1;
620       PrintDebug(" mouse reset wrap mode (ignored)  ");
621       state->mouse_state=STREAM1;
622       return 0; // done
623       break;
624
625     case 0xeb: // read data
626       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
627       state->mouse_done_after_ack=0;
628       state->mouse_needs_ack=1;
629       PrintDebug(" mouse switch to wrap mode (ignored)  ");
630       state->mouse_state=REMOTE1;
631       return 0; // not done
632       break;
633       
634     case 0xea: // set stream 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 stream mode  ");
639       state->mouse_state=STREAM1;
640       return 0; // not done
641       break;
642
643     case 0xe9: // status request
644       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
645       state->mouse_done_after_ack=0;
646       state->mouse_needs_ack=1;
647       PrintDebug(" mouse status request begins  ");
648       state->mouse_state=STATUS1;
649       return 0; // notdone
650       break;
651
652     case 0xe8: // set resolution
653       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
654       state->mouse_done_after_ack=0;
655       state->mouse_needs_ack=1;
656       PrintDebug(" mouse set resolution begins  ");
657       state->mouse_state=SETRES1;
658       return 0; // notdone
659       break;
660
661     case 0xe7: // set scaling 2:1
662       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
663       state->mouse_done_after_ack=1;
664       state->mouse_needs_ack=1;
665       PrintDebug(" mouse set scaling 2:1 ");
666       state->mouse_state=STREAM1;
667       return 0; // not done
668       break;
669
670     case 0xe6: // set scaling 1:1
671       PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
672       state->mouse_done_after_ack=1;
673       state->mouse_needs_ack=1;
674       PrintDebug(" mouse set scaling 1:1 ");
675       state->mouse_state=STREAM1;
676       return 0; // done
677       break;
678       
679     default:
680       PrintDebug(" receiving unknown mouse command (0x%x) in acceptable state ",data);
681       return 1; // done
682       break;
683
684     }
685     
686   default:
687     PrintDebug(" receiving mouse output in unhandled state (0x%x) ",state->mouse_state);
688     break;
689     return 1; // done?
690     break;
691   }
692
693   PrintDebug(" HUH? ");
694   return 1; // done
695 }
696
697
698
699 #if KEYBOARD_DEBUG_80H
700 int keyboard_write_delay(ushort_t port,
701                          void * src, 
702                          uint_t length,
703                          struct vm_device * dev)
704 {
705
706   if (length == 1) { 
707     PrintDebug("keyboard: write of 0x%x to 80h\n", *((uchar_t*)src));
708
709     return 1;
710   } else {
711     PrintDebug("keyboard: write of >1 byte to 80h\n", *((uchar_t*)src));
712
713     return length;
714   }
715 }
716
717 int keyboard_read_delay(ushort_t port,
718                         void * dest, 
719                         uint_t length,
720                         struct vm_device * dev)
721 {
722
723   if (length == 1) { 
724     *((uchar_t*)dest) = In_Byte(port);
725
726     PrintDebug("keyboard: read of 0x%x from 80h\n", *((uchar_t*)dest));
727
728     return 1;
729   } else {
730     PrintDebug("keyboard: read of >1 byte from 80h\n");
731
732     return length;
733   }
734 }
735 #endif
736     
737   
738
739
740
741 int keyboard_write_command(ushort_t port,
742                            void * src, 
743                            uint_t length,
744                            struct vm_device * dev)
745 {
746   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
747   uchar_t cmd;
748
749   // Should always be single byte write
750
751   if (length != 1) { 
752     PrintError("keyboard: write of >1 bytes (%d) to 64h\n", length);
753     return -1;
754   }
755
756   cmd = *((uchar_t*)src); 
757
758   if (state->state != NORMAL) { 
759     PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n");
760   }
761   
762   PrintDebug("keyboard: command 0x%x on 64h\n", cmd);
763
764   switch (cmd) { 
765
766   case 0x20:  // READ COMMAND BYTE (returned in 60h)
767     PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND,KEYBOARD);
768     state->state = NORMAL;  // the next read on 0x60 will get the right data
769     PrintDebug("keyboard: command byte 0x%x returned\n",state->cmd_byte);
770     break;
771
772   case 0x60:  // WRITE COMMAND BYTE (read from 60h)
773     state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
774     PrintDebug("keyboard: prepare to write command byte\n");
775     break;
776
777   // case 0x90-9f - write to output port  (?)
778
779   case 0xa1: // Get version number
780     PushToOutputQueue(dev, 0, OVERWRITE, COMMAND,KEYBOARD);
781     state->state = NORMAL;
782     PrintDebug("keyboard: version number 0x0 returned\n");
783     break;
784
785   case 0xa4:  // is password installed?  send result to 0x60
786     // we don't support passwords
787     PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND,KEYBOARD);
788     PrintDebug("keyboard: password not installed\n");
789     state->state = NORMAL;
790     break;
791
792   case 0xa5:  // new password will arrive on 0x60
793     state->state = TRANSMIT_PASSWD;
794     PrintDebug("keyboard: pepare to transmit password\n");
795     break;
796
797   case 0xa6:  // check passwd;
798     // since we do not support passwords, we will simply ignore this
799     // the implication is that any password check immediately succeeds 
800     // with a blank password
801     state->state = NORMAL;
802     PrintDebug("keyboard: password check succeeded\n");
803     break;
804
805   case 0xa7:  // disable mouse
806     state->cmd_byte |= CMD_MOUSE_DISABLE;
807     state->state = NORMAL;
808     PrintDebug("keyboard: mouse disabled\n");
809     break;
810
811   case 0xa8:  // enable mouse
812     state->cmd_byte &= ~CMD_MOUSE_DISABLE;
813     state->state = NORMAL;
814     PrintDebug("keyboard: mouse enabled\n");
815     break;
816
817   case 0xa9:  // mouse interface test  (always succeeds)
818     PushToOutputQueue(dev, 0, OVERWRITE,COMMAND,KEYBOARD);
819     PrintDebug("keyboard: mouse interface test succeeded\n");
820     state->state = NORMAL;
821     break;
822
823   case 0xaa:  // controller self test (always succeeds)
824     PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND,KEYBOARD);
825     PrintDebug("keyboard: controller self test succeeded\n");
826     state->state = NORMAL;
827     break;
828
829   case 0xab:  // keyboard interface test (always succeeds)
830     PushToOutputQueue(dev, 0, OVERWRITE, COMMAND,KEYBOARD);
831     state->state = NORMAL;
832     PrintDebug("keyboard: keyboard interface test succeeded\n");
833     break;
834
835   case 0xad:  // disable keyboard
836     state->cmd_byte |= CMD_DISABLE;
837     state->state = NORMAL;
838     PrintDebug("keyboard: keyboard disabled\n");
839     break;
840
841   case 0xae:  // enable keyboard
842     state->cmd_byte &= ~CMD_DISABLE;
843     state->state = NORMAL;
844     PrintDebug("keyboard: keyboard enabled\n");
845     break;
846
847   case 0xaf:  // get version
848     PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND,KEYBOARD);
849     state->state = NORMAL;
850     PrintDebug("keyboard: version 0 returned \n");
851     break;
852
853   case 0xd0: // return microcontroller output on 60h
854     PushToOutputQueue(dev,state->output_byte,OVERWRITE,COMMAND,KEYBOARD);
855     state->state = NORMAL;
856     PrintDebug("keyboard: output byte 0x%x returned\n",state->output_byte);
857     break;
858
859   case 0xd1: // request to write next byte on 60h to the microcontroller output port
860     state->state = WRITING_OUTPUT_PORT;
861     PrintDebug("keyboard: prepare to write output byte\n");
862     break;
863
864   case 0xd2:  //  write keyboard buffer (inject key)
865     state->state = INJECTING_KEY;
866     PrintDebug("keyboard: prepare to inject key\n");
867     break;
868
869   case 0xd3: //  write mouse buffer (inject mouse)
870     state->state = INJECTING_MOUSE;
871     PrintDebug("keyboard: prepare to inject mouse\n");
872     break;
873
874   case 0xd4: // write mouse device (command to mouse?)
875     state->state = IN_MOUSE;
876     PrintDebug("keyboard: prepare to inject mouse command\n");
877     break;
878
879   case 0xc0: //  read input port 
880     PushToOutputQueue(dev,state->input_byte,OVERWRITE,COMMAND,KEYBOARD);
881     state->state=NORMAL;
882     PrintDebug("keyboard: input byte 0x%x returned\n",state->input_byte);
883     break;
884
885   case 0xc1:  //copy input port lsn to status msn
886     state->status_byte &= 0x0f;
887     state->status_byte |= (state->input_byte & 0xf)<<4;
888     state->state=NORMAL;
889     PrintDebug("keyboard: copied input byte lsn to status msn\n");
890     break;
891
892   case 0xc2: // copy input port msn to status msn
893     state->status_byte &= 0x0f;
894     state->status_byte |= (state->input_byte & 0xf0);
895     state->state=NORMAL;
896     PrintDebug("keyboard: copied input byte msn to status msn\n");
897     break;
898     
899   case 0xe0: // read test port
900     PushToOutputQueue(dev,state->output_byte>>6,OVERWRITE,COMMAND,KEYBOARD);
901     state->state=NORMAL;
902     PrintDebug("keyboard: read 0x%x from test port\n",state->output_byte>>6);
903     break;
904
905    
906   case 0xf0:   // pulse output port
907   case 0xf1:   // this should pulse 0..3 of cmd_byte on output port 
908   case 0xf2:   // instead of what is currently in output_byte (I think)
909   case 0xf3:   // main effect is taht if bit zero is zero
910   case 0xf4:   // should cause reset
911   case 0xf5:   // I doubt anything more recent than a 286 running 
912   case 0xf6:   // OS2 with the penalty box will care
913   case 0xf7:
914   case 0xf8:
915   case 0xf9:
916   case 0xfa:
917   case 0xfb:
918   case 0xfc:
919   case 0xfd:
920   case 0xfe:
921   case 0xff:
922   
923     PrintDebug("keyboard: ignoring pulse of 0x%x (low=pulsed) on output port\n",cmd&0xf);
924     state->state=NORMAL;
925     break;
926    
927
928   // case ac  diagonstic - returns 16 bytes from keyboard microcontroler on 60h
929   default:
930     PrintDebug("keyboard: ignoring command (unimplemented)\n");
931     state->state = NORMAL;
932     break;
933   }
934
935   return 1;
936
937 }
938
939 int keyboard_read_status(ushort_t port,
940                          void * dest, 
941                          uint_t length,
942                          struct vm_device * dev)
943 {
944   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
945
946   if (length == 1) { 
947
948     PrintDebug("keyboard: read status (64h): ");
949
950     *((uchar_t*)dest) = state->status_byte;
951
952     PrintDebug("0x%x\n", *((uchar_t*)dest));
953
954     return 1;
955   } else {
956     PrintError("keyboard: >1 byte read for status (64h)\n");
957     return -1;
958   }
959 }
960
961 int keyboard_write_output(ushort_t port,
962                           void * src, 
963                           uint_t length,
964                           struct vm_device * dev)
965 {
966   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
967
968   if (length != 1) { 
969     PrintError("keyboard: write of 60h with >1 byte\n");
970     return -1;
971   }
972
973   uchar_t data = *((uchar_t*)src);
974   
975   PrintDebug("keyboard: output 0x%x on 60h\n", data);
976
977   switch (state->state) {
978   case WRITING_CMD_BYTE:
979     state->cmd_byte = data;
980     state->state = NORMAL;
981     PrintDebug("keyboard: wrote new command byte 0x%x\n",state->cmd_byte);
982     break;
983   case WRITING_OUTPUT_PORT:
984     state->output_byte = data;
985     state->state = NORMAL;
986     PrintDebug("keyboard: wrote new output byte 0x%x\n",state->output_byte);
987     break;
988   case INJECTING_KEY:
989     PushToOutputQueue(dev,data,OVERWRITE,COMMAND,KEYBOARD);  // probably should be a call to deliver_key_to_vmm()
990     state->state = NORMAL;
991     PrintDebug("keyboard: injected key 0x%x\n",data);
992     break;
993   case INJECTING_MOUSE:
994     PrintDebug("keyboard: ignoring injected mouse event 0x%x\n",data);
995     state->state = NORMAL;
996     break;
997   case IN_MOUSE:
998     PrintDebug("keyboard: mouse action: ");
999     if (mouse_write_output(dev,data)) { 
1000       state->state=NORMAL;
1001     }
1002     PrintDebug("\n");
1003     break;
1004   case TRANSMIT_PASSWD:
1005     if (data) {
1006       //ignore passwd
1007       PrintDebug("keyboard: ignoring password character 0x%x\n",data);
1008     } else {
1009       // end of password
1010       state->state = NORMAL;
1011       PrintDebug("keyboard: done with password\n");
1012     }
1013     break;
1014   case NORMAL:
1015     {
1016       // command is being sent to keyboard controller
1017       switch (data) { 
1018       case 0xff: // reset
1019         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND,KEYBOARD); // ack
1020         state->state = RESET;
1021         PrintDebug("keyboard: reset complete and acked\n",data);
1022         break;
1023       case 0xf5: // disable scanning
1024       case 0xf4: // enable scanning
1025         // ack
1026         PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND,KEYBOARD);
1027         // should do something here... PAD
1028         state->state = NORMAL;
1029         PrintDebug("keyboard: %s scanning done and acked\n",data==0xf5 ? "disable" : "enable", data);
1030         break;
1031       case 0xfe: // resend
1032       case 0xfd: // set key type make
1033       case 0xfc: // set key typ make/break
1034       case 0xfb: // set key type typematic
1035       case 0xfa: // set all typematic make/break/typematic
1036       case 0xf9: // set all make
1037       case 0xf8: // set all make/break
1038       case 0xf7: // set all typemaktic
1039       case 0xf6: // set defaults
1040       case 0xf3: // set typematic delay/rate
1041         PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data);
1042         break;
1043       default:
1044         PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
1045         state->status_byte |= 0x1;
1046         break;
1047       }
1048       break;
1049     }
1050   default:
1051     PrintDebug("keyboard: unknown state %x on command 0x%x on output buffer (60h)\n", state->state, data);
1052   }
1053   
1054   return 1;
1055 }
1056
1057 int keyboard_read_input(ushort_t port,
1058                         void * dest, 
1059                         uint_t length,
1060                         struct vm_device * dev)
1061 {
1062   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
1063
1064   if (length == 1) { 
1065     uchar_t data;
1066     int done_mouse;
1067
1068     PrintDebug("keyboard: read from input (60h): ");
1069
1070     if (state->state==IN_MOUSE) { 
1071       done_mouse=mouse_read_input(dev);
1072       if (done_mouse) { 
1073         state->state=NORMAL;
1074       }
1075     } 
1076       
1077     PullFromOutputQueue(dev, &data);
1078       
1079     if (state->state == RESET) { 
1080       // We just delivered the ack for the reset
1081       // now we will ready ourselves to deliver the BAT code (success)
1082       PushToOutputQueue(dev, 0xaa, OVERWRITE,COMMAND,KEYBOARD);
1083       state->state = NORMAL;
1084       PrintDebug(" (in reset, pushing BAT test code 0xaa) ");
1085     }
1086       
1087     PrintDebug("0x%x\n", data);
1088
1089     *((uchar_t*)dest) = data;
1090     
1091     return 1;
1092   } else {
1093     PrintError("keyboard: unknown size read from input (60h)\n");
1094     return -1;
1095   }
1096 }
1097
1098
1099 int keyboard_interrupt(uint_t irq, struct vm_device * dev) 
1100 {
1101   PrintDebug("keyboard: interrupt 0x%x\n",irq);
1102
1103   dev->vm->vm_ops.raise_irq(dev->vm, irq);
1104
1105   return 0;
1106
1107 }
1108
1109
1110 int keyboard_init_device(struct vm_device * dev) 
1111 {
1112  
1113   //  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
1114
1115   PrintDebug("keyboard: init_device\n");
1116
1117   // Would read state here
1118
1119   keyboard_reset_device(dev);
1120
1121   // hook ports
1122   dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
1123   dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
1124
1125 #if KEYBOARD_DEBUG_80H
1126   dev_hook_io(dev, KEYBOARD_DELAY_80H, &keyboard_read_delay, &keyboard_write_delay);
1127 #endif
1128
1129   
1130   //
1131   // We do not hook the IRQ here.  Instead, the underlying device driver
1132   // is responsible to call us back
1133   // 
1134
1135   return 0;
1136 }
1137
1138 int keyboard_deinit_device(struct vm_device *dev)
1139 {
1140
1141   dev_unhook_io(dev, KEYBOARD_60H);
1142   dev_unhook_io(dev, KEYBOARD_64H);
1143 #if KEYBOARD_DEBUG_80H
1144   dev_unhook_io(dev, KEYBOARD_DELAY_80H);
1145 #endif
1146   keyboard_reset_device(dev);
1147   return 0;
1148 }
1149
1150
1151
1152
1153
1154 static struct vm_device_ops dev_ops = { 
1155   .init = keyboard_init_device, 
1156   .deinit = keyboard_deinit_device,
1157   .reset = keyboard_reset_device,
1158   .start = keyboard_start_device,
1159   .stop = keyboard_stop_device,
1160 };
1161
1162
1163
1164
1165 struct vm_device *create_keyboard() {
1166   
1167   if (thekeyboard != NULL) { 
1168     PrintDebug("keyboard: creating >1 keyboard device.  This will probably fail!\n");
1169   }
1170   
1171   struct keyboard_internal * keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
1172
1173   struct vm_device *device = create_device("KEYBOARD", &dev_ops, keyboard_state);
1174
1175   thekeyboard = device;
1176   
1177   return device;
1178 }