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
Peter Dinda [Thu, 17 Jul 2008 23:05:54 +0000 (23:05 +0000)]
Keyboard: added mouse handling (still does not work)
          temporarily respond to mouse reset with NACK
          which is apparently how one detects that the mouse isn't there

palacios/src/devices/generic.c
palacios/src/devices/keyboard.c

index 4f3ae7a..11cad40 100644 (file)
@@ -316,14 +316,32 @@ static struct vm_device_ops dev_ops = {
 
 
 struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
-                                uint_t                     num_port_ranges,
                                 generic_address_range_type address_ranges[],
-                                uint_t                     num_address_ranges,
-                                generic_irq_range_type     irq_ranges[],
-                                uint_t                     num_irq_ranges)
+                                generic_irq_range_type     irq_ranges[])
 {
   struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
+  int i;
+  uint_t num_port_ranges, num_address_ranges, num_irq_ranges;
 
+  num_port_ranges=0;
+  if (port_ranges!=NULL) { 
+    i=0;
+    while (port_ranges[i]!=NULL && port_ranges[i][0]!=0 && port_ranges[i][1]!=0 && port_ranges[i][2]!=0) { num_port_ranges++; i++; }
+  }
+
+  
+  num_address_ranges=0;
+  if (address_ranges!=NULL) { 
+    i=0;
+    while (address_ranges[i]!=NULL  && address_ranges[i][0]!=0 && address_ranges[i][1]!=0 && address_ranges[i][2]!=0) { num_address_ranges++; i++; }
+  }
+
+  num_irq_ranges=0;
+  if (irq_ranges!=NULL) { 
+    i=0;
+    while (irq_ranges[i]!=NULL && irq_ranges[i][0]!=0 && irq_ranges[i][1]!=0 && irq_ranges[i][2]!=0) { num_irq_ranges++; i++; }
+  }
+    
 
   generic_state->num_port_ranges = num_port_ranges;
 
index 48c50d9..4173bda 100644 (file)
@@ -5,7 +5,7 @@
 
 #define KEYBOARD_DEBUG 1
 
-#define KEYBOARD_DEBUG_80H   1
+#define KEYBOARD_DEBUG_80H   0
 
 #if KEYBOARD_DEBUG
 #define KEYBOARD_DEBUG_PRINT(first, rest...) PrintDebug(first, ##rest)
@@ -20,6 +20,7 @@
 #define KEYBOARD_DELAY_80H    0x80  // written for timing
 
 #define KEYBOARD_IRQ          0x1
+#define MOUSE_IRQ             0xc   
 
 
 // extract bits for status byte
 #define INPUT_KBD_INHIBIT   0x80  // 1=inhibit keyboard ?
 
 
+// for queue operations
 #define QUEUE               0
 #define OVERWRITE           1
+
+// for queue operations - whether it's data or cmd waiting on 60h
 #define DATA                0
 #define COMMAND             1
 
+// for queue operations - whether this is keyboard or mouse data on 60h
+#define KEYBOARD            0
+#define MOUSE               1
+
 
 // The currently targetted keyboard
 static struct vm_device *thekeyboard = NULL;
 
+//#define QUEUE_SIZE          32
+
 
 struct keyboard_internal {
   // 
@@ -120,11 +130,46 @@ struct keyboard_internal {
         // after having a d4 sent to 64
        // we wait for a new output byte on 60
        // then send it to the mouse
-       WRITING_MOUSE_CMD,
+       IN_MOUSE,
   } state;
-       
 
 
+  enum {
+    // after receiving a mouse command 0f 0xff
+    // we return the ack and then the next thing will be the 
+    // bat code (aa - success)
+    RESET1,
+    // followed by the device id (00 - mouse)
+    RESET2, 
+    // Then it goes into stream mode
+    STREAM1,  //
+    STREAM2,  //
+    STREAM3,  // for each of the following bytes in mouse_packet
+    // this is used for setting sample rate
+    SAMPLE1,  
+    // this is used for getting device id
+    DEVICE1, 
+    // just like the stream moes
+    REMOTE1,
+    REMOTE2,
+    REMOTE3,
+    // For getting status info
+    STATUS1,
+    STATUS2,
+    STATUS3, 
+    // set resolution
+    SETRES1,
+  } mouse_state;
+
+
+  uchar_t wrap;             
+  uchar_t mouse_packet[3];  // byte 1: y over, xover, y sign, x sign, 1, middle, right, left
+                            // byte 2: x movement
+                            // byte 3: y movement
+
+  uchar_t mouse_needs_ack;  //
+  uchar_t mouse_done_after_ack; 
+
   uchar_t cmd_byte;         //  for keyboard uC - read/written 
                             //     via read/write cmd byte command
   uchar_t status_byte;      //  for on-board uC - read via 64h
@@ -136,9 +181,15 @@ struct keyboard_internal {
   // Data for 8042
   uchar_t input_queue;      //  
   uint_t  input_queue_len;  //  
+  //uint_t  input_queue_read;
+  //uint_t  input_queue_write;
   // Data for system
   uchar_t output_queue;     //  
   uint_t  output_queue_len; //  
+  //uint_t  output_queue_read;
+  //uint_t  output_queue_write;
+
+
 };
 
 
@@ -146,23 +197,31 @@ struct keyboard_internal {
 // push item onto outputqueue, optionally overwriting if there is no room
 // returns 0 if successful
 //
-static int PushToOutputQueue(struct vm_device *dev, uchar_t value, uchar_t overwrite, uchar_t cmd) 
+static int PushToOutputQueue(struct vm_device *dev, uchar_t value, uchar_t overwrite, uchar_t cmd, uchar_t mouse) 
 {
   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
   
   if ((state->output_queue_len == 0) || overwrite) { 
-
+    
     state->output_queue = value;
     state->output_queue_len = 1;
-    state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
     
     if (cmd) {
       state->status_byte |= STATUS_COMMAND_DATA_AVAIL;
     } else {
       state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
     }
+    
+    if (mouse) { 
+      state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
+    } 
 
+    {
+      state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
+    }
+    
     return 0;
+
   } else {
     KEYBOARD_DEBUG_PRINT("keyboard: PushToOutputQueue Failed - Queue Full\n");
     return -1;
@@ -178,16 +237,24 @@ static int PullFromOutputQueue(struct vm_device *dev, uchar_t *value)
 {
   struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
 
-  if (state->output_queue_len == 1) { 
+  if (1 || state->output_queue_len == 1) { 
 
     *value = state->output_queue;
     state->output_queue_len = 0;
-    state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
-
+    
+    if (state->status_byte & STATUS_OUTPUT_BUFFER_FULL) { 
+      state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
+    } 
+    
+    if (state->status_byte & STATUS_MOUSE_BUFFER_FULL) { 
+      state->status_byte &= ~STATUS_MOUSE_BUFFER_FULL;
+    }
+    
     if (state->status_byte & STATUS_COMMAND_DATA_AVAIL) { 
       state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
     } // reset to data
-
+    
+    
     return 0;
   } else {
     KEYBOARD_DEBUG_PRINT("keyboard: PullFromOutputQueue Failed - Queue Empty\n");
@@ -248,6 +315,12 @@ static struct vm_device *demultiplex_injected_key(uchar_t status, uchar_t scanco
   return thekeyboard;
 }
 
+static struct vm_device *demultiplex_injected_mouse(uchar_t mouse_packet[3])
+{
+  // this currently does nothing
+  return thekeyboard;
+}
+
 int keyboard_interrupt(uint_t irq, struct vm_device * dev);
 
 void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
@@ -260,7 +333,7 @@ void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
   if ( (state->status_byte & STATUS_ENABLED)      // onboard is enabled
        && (!(state->cmd_byte & CMD_DISABLE)) )  {   // keyboard is enabled
 
-    PushToOutputQueue(dev, scancode, OVERWRITE, DATA);
+    PushToOutputQueue(dev, scancode, OVERWRITE, DATA, KEYBOARD);
 
     if (state->cmd_byte & CMD_INTR) { 
       keyboard_interrupt(KEYBOARD_IRQ, dev);
@@ -269,12 +342,43 @@ void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
   }
 }
 
+
+void deliver_mouse_to_vmm(uchar_t data[3])
+{
+  struct vm_device *dev = demultiplex_injected_mouse(data);
+  struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+
+  KEYBOARD_DEBUG_PRINT("keyboard: injected mouse packet 0x %x %x %x\n",data[0],data[1],data[2]);
+  
+  memcpy(state->mouse_packet,data,3);
+  
+  state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
+  
+    
+  switch (state->mouse_state) { 
+  case STREAM1:
+  case STREAM2:
+  case STREAM3:
+    if (!(state->cmd_byte & CMD_MOUSE_DISABLE)) { 
+      keyboard_interrupt(MOUSE_IRQ,dev);
+    }
+    break;
+  default:
+    break;
+  }
+
+}
+
+
 int keyboard_reset_device(struct vm_device * dev)
 {
   struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
   
   memset(data, 0, sizeof(struct keyboard_internal));
 
+  data->state = NORMAL;
+  data->mouse_state=STREAM1;
+
   data->cmd_byte =   
       CMD_INTR        // interrupts on
     | CMD_MOUSE_INTR  // mouse interupts on
@@ -292,6 +396,8 @@ int keyboard_reset_device(struct vm_device * dev)
     INPUT_RAM ;            // we have some
                            // also display=color, jumper 0, keyboard enabled 
 
+  
+
   KEYBOARD_DEBUG_PRINT("keyboard: reset device\n");
  
   return 0;
@@ -314,6 +420,284 @@ int keyboard_stop_device(struct vm_device *dev)
 }
 
 
+int mouse_read_input(struct vm_device *dev)
+{
+  struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+
+  if (state->mouse_needs_ack) { 
+    state->mouse_needs_ack=0;
+    // the ack has been stuffed previously
+    if (state->mouse_done_after_ack) { 
+      return 1;
+    } else {
+      return 0;
+    }
+  }
+
+  switch (state->mouse_state) { 
+  case RESET1: // requesting the BAT code
+    PushToOutputQueue(dev,0xaa,OVERWRITE,DATA,MOUSE) ;  // BAT successful
+    KEYBOARD_DEBUG_PRINT(" mouse sent BAT code (sucesssful) ");
+    state->mouse_state=RESET2;
+    return 0;  // not done with mouse processing yet
+    break;
+  case RESET2: // requesting the device id
+    PushToOutputQueue(dev,0x00,OVERWRITE,DATA,MOUSE) ;  // normal mouse type
+    KEYBOARD_DEBUG_PRINT(" mouse sent device id ");
+    state->mouse_state=STREAM1;
+    return 1;  // done with mouse processing 
+    break;
+  case STREAM1: // send data
+    PushToOutputQueue(dev,state->mouse_packet[0],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent stream data1 ");
+    state->mouse_state=STREAM2;
+    return 0;
+    break;
+  case STREAM2: // send data
+    PushToOutputQueue(dev,state->mouse_packet[1],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent stream data2 ");
+    state->mouse_state=STREAM3;
+    return 0;
+    break;
+  case STREAM3: // send data
+    PushToOutputQueue(dev,state->mouse_packet[2],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent stream data3 ");
+    state->mouse_state=STREAM1;
+    return 1; // now done
+    break;
+  case REMOTE1: // send data
+    PushToOutputQueue(dev,state->mouse_packet[0],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent remote data1 ");
+    state->mouse_state=REMOTE2;
+    return 0;
+    break;
+  case REMOTE2: // send data
+    PushToOutputQueue(dev,state->mouse_packet[1],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent remote data2 ");
+    state->mouse_state=REMOTE3;
+    return 0;
+    break;
+  case REMOTE3: // send data
+    PushToOutputQueue(dev,state->mouse_packet[2],OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent remote data3 ");
+    state->mouse_state=REMOTE1;
+    return 1; // now done
+    break;
+  case STATUS1: // send data
+    PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent status data1 ");
+    state->mouse_state=STATUS2;
+    return 0;
+    break;
+  case STATUS2: // send data
+    PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent status data2 ");
+    state->mouse_state=STATUS3;
+    return 0;
+    break;
+  case STATUS3: // send data
+    PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent status data3 ");
+    state->mouse_state=STREAM1;
+    return 1; // now done
+    break;
+  case DEVICE1: // send device id
+    PushToOutputQueue(dev,0x0,OVERWRITE,DATA,MOUSE); 
+    KEYBOARD_DEBUG_PRINT(" mouse sent device id ");
+    state->mouse_state=STREAM1;
+    return 1; // now done
+    break;
+  default:
+    KEYBOARD_DEBUG_PRINT(" mouse has no data ");
+    return 1; // done
+    break;
+  }
+}
+
+int mouse_write_output(struct vm_device *dev, uchar_t data)
+{
+  struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+
+  switch (state->mouse_state) { 
+  case STREAM1:
+  case STREAM2:
+  case STREAM3:
+  case REMOTE1:
+  case REMOTE2:
+  case REMOTE3:
+    switch (data) {
+
+    case 0xff: //reset
+      PushToOutputQueue(dev,0xfe,OVERWRITE,DATA,MOUSE) ;   // no mouse!
+      KEYBOARD_DEBUG_PRINT(" mouse reset begins (no mouse) ");
+      return 1;  // not done;
+      break;
+
+      /*
+    case 0xff: //reset
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      KEYBOARD_DEBUG_PRINT(" mouse reset begins ");
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      state->mouse_state=RESET1;
+      return 0;  // not done;
+      break;
+      */
+    case 0xfe: //resend
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      KEYBOARD_DEBUG_PRINT(" mouse resend begins ");
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=0;
+      state->mouse_state=STREAM1;
+      return 0;  // not done
+      break;
+      
+    case 0xf6: // set defaults
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      KEYBOARD_DEBUG_PRINT(" mouse set defaults ");
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+      
+    case 0xf5: // disable data reporting 
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse disable data reporting ");
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+      
+    case 0xf4: // enable data reporting 
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse enable data reporting ");
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+      
+    case 0xf3: // set sample rate
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set sample rate begins ");
+      state->mouse_state=SAMPLE1;
+      return 0; // not done
+      break;
+      
+    case 0xf2: // get device id
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse get device id begins ");
+      state->mouse_state=DEVICE1;
+      return 0; // not done
+      break;
+      
+    case 0xf0: // set remote mode
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set remote mode  ");
+      state->mouse_state=REMOTE1;
+      return 0; // not done
+      break;
+
+    case 0xee: // set wrap mode
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set wrap mode (ignored)  ");
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+
+    case 0xec: // reset wrap mode
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse reset wrap mode (ignored)  ");
+      state->mouse_state=STREAM1;
+      return 0; // done
+      break;
+
+    case 0xeb: // read data
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse switch to wrap mode (ignored)  ");
+      state->mouse_state=REMOTE1;
+      return 0; // not done
+      break;
+      
+    case 0xea: // set stream mode
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set stream mode  ");
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+
+    case 0xe9: // status request
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse status request begins  ");
+      state->mouse_state=STATUS1;
+      return 0; // notdone
+      break;
+
+    case 0xe8: // set resolution
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=0;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set resolution begins  ");
+      state->mouse_state=SETRES1;
+      return 0; // notdone
+      break;
+
+    case 0xe7: // set scaling 2:1
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set scaling 2:1 ");
+      state->mouse_state=STREAM1;
+      return 0; // not done
+      break;
+
+    case 0xe6: // set scaling 1:1
+      PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ; 
+      state->mouse_done_after_ack=1;
+      state->mouse_needs_ack=1;
+      KEYBOARD_DEBUG_PRINT(" mouse set scaling 1:1 ");
+      state->mouse_state=STREAM1;
+      return 0; // done
+      break;
+      
+    default:
+      KEYBOARD_DEBUG_PRINT(" receiving unknown mouse command (0x%x) in acceptable state ",data);
+      return 1; // done
+      break;
+
+    }
+    
+  default:
+    KEYBOARD_DEBUG_PRINT(" receiving mouse output in unhandled state (0x%x) ",state->mouse_state);
+    break;
+    return 1; // done?
+    break;
+  }
+
+  KEYBOARD_DEBUG_PRINT(" HUH? ");
+  return 1; // done
+}
+
+
+
 #if KEYBOARD_DEBUG_80H
 int keyboard_write_delay(ushort_t port,
                         void * src, 
@@ -382,7 +766,7 @@ int keyboard_write_command(ushort_t port,
   switch (cmd) { 
 
   case 0x20:  // READ COMMAND BYTE (returned in 60h)
-    PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND,KEYBOARD);
     state->state = NORMAL;  // the next read on 0x60 will get the right data
     KEYBOARD_DEBUG_PRINT("keyboard: command byte 0x%x returned\n",state->cmd_byte);
     break;
@@ -395,14 +779,14 @@ int keyboard_write_command(ushort_t port,
   // case 0x90-9f - write to output port  (?)
 
   case 0xa1: // Get version number
-    PushToOutputQueue(dev, 0, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, 0, OVERWRITE, COMMAND,KEYBOARD);
     state->state = NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: version number 0x0 returned\n");
     break;
 
   case 0xa4:  // is password installed?  send result to 0x60
     // we don't support passwords
-    PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND,KEYBOARD);
     KEYBOARD_DEBUG_PRINT("keyboard: password not installed\n");
     state->state = NORMAL;
     break;
@@ -433,19 +817,19 @@ int keyboard_write_command(ushort_t port,
     break;
 
   case 0xa9:  // mouse interface test  (always succeeds)
-    PushToOutputQueue(dev, 0, OVERWRITE,COMMAND);
+    PushToOutputQueue(dev, 0, OVERWRITE,COMMAND,KEYBOARD);
     KEYBOARD_DEBUG_PRINT("keyboard: mouse interface test succeeded\n");
     state->state = NORMAL;
     break;
 
   case 0xaa:  // controller self test (always succeeds)
-    PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND,KEYBOARD);
     KEYBOARD_DEBUG_PRINT("keyboard: controller self test succeeded\n");
     state->state = NORMAL;
     break;
 
   case 0xab:  // keyboard interface test (always succeeds)
-    PushToOutputQueue(dev, 0, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, 0, OVERWRITE, COMMAND,KEYBOARD);
     state->state = NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: keyboard interface test succeeded\n");
     break;
@@ -463,13 +847,13 @@ int keyboard_write_command(ushort_t port,
     break;
 
   case 0xaf:  // get version
-    PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND);
+    PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND,KEYBOARD);
     state->state = NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: version 0 returned \n");
     break;
 
   case 0xd0: // return microcontroller output on 60h
-    PushToOutputQueue(dev,state->output_byte,OVERWRITE,COMMAND);
+    PushToOutputQueue(dev,state->output_byte,OVERWRITE,COMMAND,KEYBOARD);
     state->state = NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: output byte 0x%x returned\n",state->output_byte);
     break;
@@ -490,12 +874,12 @@ int keyboard_write_command(ushort_t port,
     break;
 
   case 0xd4: // write mouse device (command to mouse?)
-    state->state = WRITING_MOUSE_CMD;
+    state->state = IN_MOUSE;
     KEYBOARD_DEBUG_PRINT("keyboard: prepare to inject mouse command\n");
     break;
 
   case 0xc0: //  read input port 
-    PushToOutputQueue(dev,state->input_byte,OVERWRITE,COMMAND);
+    PushToOutputQueue(dev,state->input_byte,OVERWRITE,COMMAND,KEYBOARD);
     state->state=NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: input byte 0x%x returned\n",state->input_byte);
     break;
@@ -515,10 +899,11 @@ int keyboard_write_command(ushort_t port,
     break;
     
   case 0xe0: // read test port
-    PushToOutputQueue(dev,state->output_byte>>6,OVERWRITE,COMMAND);
+    PushToOutputQueue(dev,state->output_byte>>6,OVERWRITE,COMMAND,KEYBOARD);
     state->state=NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: read 0x%x from test port\n",state->output_byte>>6);
     break;
+
    
   case 0xf0:   // pulse output port
   case 0xf1:   // this should pulse 0..3 of cmd_byte on output port 
@@ -536,6 +921,7 @@ int keyboard_write_command(ushort_t port,
   case 0xfd:
   case 0xfe:
   case 0xff:
+  
     KEYBOARD_DEBUG_PRINT("keyboard: ignoring pulse of 0x%x (low=pulsed) on output port\n",cmd&0xf);
     state->state=NORMAL;
     break;
@@ -602,7 +988,7 @@ int keyboard_write_output(ushort_t port,
     KEYBOARD_DEBUG_PRINT("keyboard: wrote new output byte 0x%x\n",state->output_byte);
     break;
   case INJECTING_KEY:
-    PushToOutputQueue(dev,data,OVERWRITE,DATA);  // probably should be a call to deliver_key_to_vmm()
+    PushToOutputQueue(dev,data,OVERWRITE,COMMAND,KEYBOARD);  // probably should be a call to deliver_key_to_vmm()
     state->state = NORMAL;
     KEYBOARD_DEBUG_PRINT("keyboard: injected key 0x%x\n",data);
     break;
@@ -610,9 +996,12 @@ int keyboard_write_output(ushort_t port,
     KEYBOARD_DEBUG_PRINT("keyboard: ignoring injected mouse event 0x%x\n",data);
     state->state = NORMAL;
     break;
-  case WRITING_MOUSE_CMD:
-    KEYBOARD_DEBUG_PRINT("keyboard: ignoring injected mouse command 0x%x\n",data);
-    state->state = NORMAL;
+  case IN_MOUSE:
+    KEYBOARD_DEBUG_PRINT("keyboard: mouse action: ");
+    if (mouse_write_output(dev,data)) { 
+      state->state=NORMAL;
+    }
+    KEYBOARD_DEBUG_PRINT("\n");
     break;
   case TRANSMIT_PASSWD:
     if (data) {
@@ -629,14 +1018,14 @@ int keyboard_write_output(ushort_t port,
       // command is being sent to keyboard controller
       switch (data) { 
       case 0xff: // reset
-       PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND); // ack
+       PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND,KEYBOARD); // ack
        state->state = RESET;
        KEYBOARD_DEBUG_PRINT("keyboard: reset complete and acked\n",data);
        break;
       case 0xf5: // disable scanning
       case 0xf4: // enable scanning
        // ack
-       PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND);
+       PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND,KEYBOARD);
        // should do something here... PAD
        state->state = NORMAL;
        KEYBOARD_DEBUG_PRINT("keyboard: %s scanning done and acked\n",data==0xf5 ? "disable" : "enable", data);
@@ -655,6 +1044,7 @@ int keyboard_write_output(ushort_t port,
        break;
       default:
        KEYBOARD_DEBUG_PRINT("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
+       state->status_byte |= 0x1;
        break;
       }
       break;
@@ -675,15 +1065,23 @@ int keyboard_read_input(ushort_t port,
 
   if (length == 1) { 
     uchar_t data;
+    int done_mouse;
 
     KEYBOARD_DEBUG_PRINT("keyboard: read from input (60h): ");
 
+    if (state->state==IN_MOUSE) { 
+      done_mouse=mouse_read_input(dev);
+      if (done_mouse) { 
+       state->state=NORMAL;
+      }
+    } 
+      
     PullFromOutputQueue(dev, &data);
-
+      
     if (state->state == RESET) { 
       // We just delivered the ack for the reset
       // now we will ready ourselves to deliver the BAT code (success)
-      PushToOutputQueue(dev, 0xaa, OVERWRITE,COMMAND);
+      PushToOutputQueue(dev, 0xaa, OVERWRITE,COMMAND,KEYBOARD);
       state->state = NORMAL;
       KEYBOARD_DEBUG_PRINT(" (in reset, pushing BAT test code 0xaa) ");
     }
@@ -691,7 +1089,7 @@ int keyboard_read_input(ushort_t port,
     KEYBOARD_DEBUG_PRINT("0x%x\n", data);
 
     *((uchar_t*)dest) = data;
-
+    
     return 1;
   } else {
     KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from input (60h)\n");
@@ -702,7 +1100,7 @@ int keyboard_read_input(ushort_t port,
 
 int keyboard_interrupt(uint_t irq, struct vm_device * dev) 
 {
-  KEYBOARD_DEBUG_PRINT("keyboard: interrupt\n");
+  KEYBOARD_DEBUG_PRINT("keyboard: interrupt 0x%x\n",irq);
 
   dev->vm->vm_ops.raise_irq(dev->vm, irq);