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 generic device, some keyboard fixes (still in progress)
[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 #if KEYBOARD_DEBUG
9 #define KEYBOARD_DEBUG_PRINT(first, rest...) do { SerialPrint(first, ## rest ); } while (0) 
10 #else
11 #define KEYBOARD_DEBUG_PRINT(first, rest...)
12 #endif
13
14
15 extern struct vmm_os_hooks *os_hooks;
16
17 extern void SerialPrint(const char *format, ...);
18
19
20
21 #define KEYBOARD_DATA_REG          0x60
22 #define KEYBOARD_CONTROL_REG       0x64
23
24 #define KEYBOARD_IRQ    0x1
25
26
27
28 // The currently targetted keyboard
29 static struct vm_device *thekeyboard=NULL;
30
31
32 struct keyboard_internal {
33   // read* is what is seen when reads are done from the VM
34   uchar_t read_status;
35   uchar_t read_scancode;
36   // write* is where we put the writes from the VM
37   uchar_t write_status;
38   uchar_t write_scancode;
39
40   uchar_t status_byte;      //  for on-board uC
41
42   uchar_t input_queue;      //  input queue is for communication *to* the on-board uC
43   uint_t  input_queue_len;  //  num items queued
44   uchar_t output_queue;     //  output queue is for communcation *from* the on-board uC
45   uint_t  output_queue_len; //  num items queued 
46 };
47
48
49 static struct vm_device *demultiplex_injected_key(uchar_t status, uchar_t scancode)
50 {
51   // this currently does nothing
52   return thekeyboard;
53 }
54
55 int keyboard_interrupt(uint_t irq,struct vm_device * dev);
56
57 void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
58 {
59   struct vm_device *dev = demultiplex_injected_key(status,scancode);
60
61   struct keyboard_internal *state = (struct keyboard_internal *)dev->private_data;
62
63   KEYBOARD_DEBUG_PRINT("keyboard: injected status 0x%x, and scancode 0x%x\n", status,scancode);
64   
65   // This is wrong - the read status should be some combination of the 
66   // status/scancode within the VM, and that of the actual device
67   state->read_status=status;
68   state->read_scancode=scancode;
69
70   keyboard_interrupt(KEYBOARD_IRQ,dev);
71
72 }
73
74 int keyboard_reset_device(struct vm_device * dev)
75 {
76   struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
77   
78   memset(data,0,sizeof(struct keyboard_internal));
79   
80   KEYBOARD_DEBUG_PRINT("keyboard: reset device\n");
81  
82   return 0;
83
84 }
85
86
87
88
89
90 int keyboard_start_device(struct vm_device *dev)
91 {
92   KEYBOARD_DEBUG_PRINT("keyboard: start device\n");
93   return 0;
94 }
95
96
97 int keyboard_stop_device(struct vm_device *dev)
98 {
99   KEYBOARD_DEBUG_PRINT("keyboard: stop device\n");
100   return 0;
101 }
102
103
104
105
106 int keyboard_write_control_port(ushort_t port,
107                                 void * src, 
108                                 uint_t length,
109                                 struct vm_device * dev)
110 {
111   struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
112
113   if (length==1) { 
114     uchar_t data = *((uchar_t*)src); 
115     KEYBOARD_DEBUG_PRINT("keyboard: write of 0x%x to control port\n",data);
116     state->write_status=data;
117     return 1;
118   } else {
119     KEYBOARD_DEBUG_PRINT("keyboard: unknown size write to control port!\n");
120     return -1;
121   }
122 }
123
124 int keyboard_read_control_port(ushort_t port,
125                                void * dest, 
126                                uint_t length,
127                                struct vm_device * dev)
128 {
129   struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
130
131   if (length==1) { 
132     uchar_t data;
133     KEYBOARD_DEBUG_PRINT("keyboard: read from control port: ");
134     data=state->read_status;
135     KEYBOARD_DEBUG_PRINT("0x%x\n",data);
136     memcpy(dest,&data,length);
137     return 1;
138   } else {
139     KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from control port!\n");
140     return -1;
141   }
142 }
143
144 int keyboard_write_data_port(ushort_t port,
145                              void * src, 
146                              uint_t length,
147                              struct vm_device * dev)
148 {
149   struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
150
151   if (length==1) { 
152     uchar_t data = *((uchar_t*)src); 
153     KEYBOARD_DEBUG_PRINT("keyboard: write of 0x%x to data port\n",data);
154     state->write_scancode=data;
155     return 1;
156   } else {
157     KEYBOARD_DEBUG_PRINT("keyboard: unknown size write to data port!\n");
158     return -1;
159   }
160 }
161
162 int keyboard_read_data_port(ushort_t port,
163                             void * dest, 
164                             uint_t length,
165                             struct vm_device * dev)
166 {
167   struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
168
169   if (length==1) { 
170     uchar_t data;
171     KEYBOARD_DEBUG_PRINT("keyboard: read from data port: ");
172     data=state->read_scancode;
173     KEYBOARD_DEBUG_PRINT("0x%x\n",data);
174     memcpy(dest,&data,1);
175     return 1;
176   } else {
177     KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from data port!\n");
178     return -1;
179   }
180 }
181
182
183 int keyboard_interrupt(uint_t irq,
184                        struct vm_device * dev) 
185 {
186   KEYBOARD_DEBUG_PRINT("keyboard: interrupt\n");
187
188   dev->vm->vm_ops.raise_irq(dev->vm,irq,0);
189
190   return 0;
191
192 }
193
194
195 int keyboard_init_device(struct vm_device * dev) 
196 {
197  
198   //  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
199
200   KEYBOARD_DEBUG_PRINT("keyboard: init_device\n");
201
202   // Would read state here
203
204   keyboard_reset_device(dev);
205
206   // hook ports
207   dev_hook_io(dev, KEYBOARD_DATA_REG, &keyboard_read_data_port, &keyboard_write_data_port);
208   dev_hook_io(dev, KEYBOARD_CONTROL_REG, &keyboard_read_control_port, &keyboard_write_control_port);
209   
210   //
211   // We do not hook the IRQ here.  Instead, the underlying device driver
212   // is responsible to call us back
213   // 
214
215   return 0;
216 }
217
218 int keyboard_deinit_device(struct vm_device *dev)
219 {
220
221   dev_unhook_io(dev, KEYBOARD_DATA_REG);
222   dev_unhook_io(dev, KEYBOARD_CONTROL_REG);
223
224   keyboard_reset_device(dev);
225   return 0;
226 }
227
228
229
230
231
232 static struct vm_device_ops dev_ops = { 
233   .init = keyboard_init_device, 
234   .deinit = keyboard_deinit_device,
235   .reset = keyboard_reset_device,
236   .start = keyboard_start_device,
237   .stop = keyboard_stop_device,
238 };
239
240
241
242
243 struct vm_device *create_keyboard() {
244   
245   if (thekeyboard!=NULL) { 
246     KEYBOARD_DEBUG_PRINT("keyboard: creating >1 keyboard device.  This will probably fail!\n");
247   }
248   
249   struct keyboard_internal * keyboard_state = os_hooks->malloc(sizeof(struct keyboard_internal));
250
251   struct vm_device *device = create_device("KEYBOARD", &dev_ops, keyboard_state);
252
253   thekeyboard=device;
254   
255   return device;
256 }