Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


formatting change
[palacios.git] / palacios / src / devices / generic.c
1 /* (c) 2008, Peter Dinda <pdinda@northwestern.edu> */
2 /* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
3
4
5 #include <devices/generic.h>
6 #include <palacios/vmm.h>
7 #include <palacios/vmm_types.h>
8 #include <geekos/io.h>
9
10
11
12 #ifndef DEBUG_GENERIC
13 #undef PrintDebug
14 #define PrintDebug(fmt, args...)
15 #endif
16
17
18 #define PORT_HOOKS 1
19 #define MEM_HOOKS  0   // not yet implmented in device model
20 #define IRQ_HOOKS  0   // not yet implemented in device model
21
22 struct generic_internal {
23   generic_port_range_type    * port_ranges;
24   uint_t                     num_port_ranges;
25   generic_address_range_type * address_ranges;
26   uint_t                     num_address_ranges;
27   generic_irq_range_type     * irq_ranges;
28   uint_t                     num_irq_ranges;
29 };
30
31
32
33 int generic_reset_device(struct vm_device * dev)
34 {
35   PrintDebug("generic: reset device\n");
36  
37   return 0;
38
39 }
40
41
42
43
44
45 int generic_start_device(struct vm_device * dev)
46 {
47   PrintDebug("generic: start device\n");
48   return 0;
49 }
50
51
52 int generic_stop_device(struct vm_device * dev)
53 {
54   PrintDebug("generic: stop device\n");
55   return 0;
56 }
57
58
59
60
61 int generic_write_port_passthrough(ushort_t port,
62                                    void * src, 
63                                    uint_t length,
64                                    struct vm_device * dev)
65 {
66   uint_t i;
67
68   PrintDebug("generic: writing 0x");
69
70   for (i = 0; i < length; i++) { 
71     PrintDebug("%x", ((uchar_t*)src)[i]);
72   }
73   
74   PrintDebug(" to port 0x%x ... ", port);
75
76
77   switch (length) {
78   case 1:
79     Out_Byte(port, ((uchar_t*)src)[0]);
80     break;
81   case 2:
82     Out_Word(port, ((ushort_t*)src)[0]);
83     break;
84   case 4:
85     Out_DWord(port, ((uint_t*)src)[0]);
86     break;
87   default:
88     for (i = 0; i < length; i++) { 
89       Out_Byte(port, ((uchar_t*)src)[i]);
90     }
91   } //switch length
92
93
94   PrintDebug(" done\n");
95   
96   return length;
97 }
98
99 int generic_read_port_passthrough(ushort_t port,
100                                   void * src, 
101                                   uint_t length,
102                                   struct vm_device * dev)
103 {
104   uint_t i;
105
106   PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
107
108
109     switch (length) {
110     case 1:
111       ((uchar_t*)src)[0] = In_Byte(port);
112       break;
113     case 2:
114       ((ushort_t*)src)[0] = In_Word(port);
115       break;
116     case 4:
117       ((uint_t*)src)[0] = In_DWord(port);
118       break;
119     default:
120       for (i = 0; i < length; i++) { 
121         ((uchar_t*)src)[i] = In_Byte(port);
122       }
123     }//switch length
124
125   PrintDebug(" done ... read 0x");
126
127   for (i = 0; i < length; i++) { 
128     PrintDebug("%x", ((uchar_t*)src)[i]);
129   }
130
131   PrintDebug("\n");
132
133   return length;
134 }
135
136 int generic_write_port_ignore(ushort_t port,
137                               void * src, 
138                               uint_t length,
139                               struct vm_device * dev)
140 {
141   uint_t i;
142
143   PrintDebug("generic: writing 0x");
144
145   for (i = 0; i < length; i++) { 
146     PrintDebug("%x", ((uchar_t*)src)[i]);
147   }
148   
149   PrintDebug(" to port 0x%x ... ", port);
150
151   PrintDebug(" ignored\n");
152  
153   return length;
154 }
155
156 int generic_read_port_ignore(ushort_t port,
157                              void * src, 
158                              uint_t length,
159                              struct vm_device * dev)
160 {
161
162   PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
163
164   memset((char*)src, 0, length);
165   PrintDebug(" ignored (return zeroed buffer)\n");
166
167   return length;
168 }
169
170
171
172 int generic_interrupt(uint_t irq, struct vm_device * dev) {
173   PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
174
175   dev->vm->vm_ops.raise_irq(dev->vm, irq);
176
177   return 0;
178 }
179
180
181 int generic_init_device(struct vm_device * dev) {
182   struct generic_internal * state = (struct generic_internal *)(dev->private_data);
183   uint_t i, j;
184
185   PrintDebug("generic: init_device\n");
186
187   // Would read state here
188
189   generic_reset_device(dev);
190
191   for (i = 0; i < state->num_port_ranges; i++) { 
192
193     PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n", 
194                state->port_ranges[i][0], state->port_ranges[i][1], 
195                (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
196
197     if (PORT_HOOKS) { // This is a runtime conditional on a #define
198       for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
199         if (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) { 
200
201           if (dev_hook_io(dev, j, &generic_read_port_passthrough, &generic_write_port_passthrough)) { 
202             PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
203           }
204
205         } else if (state->port_ranges[i][2] == GENERIC_PRINT_AND_IGNORE) { 
206
207           if (dev_hook_io(dev, j, &generic_read_port_ignore, &generic_write_port_ignore)) { 
208             PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
209           }
210
211         } 
212       }
213     } else {
214       PrintDebug("generic: hooking ports not supported\n");
215     }
216
217   }
218
219   for (i = 0; i < state->num_address_ranges; i++) { 
220
221     PrintDebug("generic: hooking addresses 0x%x to 0x%x\n", 
222                state->address_ranges[i][0], state->address_ranges[i][1]); 
223
224     if (MEM_HOOKS) { // This is a runtime conditional on a #define
225       if (dev_hook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
226         PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
227                    state->address_ranges[i][0], state->address_ranges[i][1]); 
228       }
229     } else {
230       PrintDebug("generic: hooking addresses not supported\n");
231     }
232   }
233
234   for (i = 0; i < state->num_irq_ranges; i++) { 
235
236     PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
237                state->irq_ranges[i][0], state->irq_ranges[i][1]);
238
239     if (IRQ_HOOKS) { // This is a runtime conditional on a #define
240       for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
241         if (dev_hook_irq(dev, j, &generic_interrupt)) { 
242           PrintDebug("generic: can't hook irq  0x%x (already hooked?)\n", j);
243         }
244       }
245     } else {
246       PrintDebug("generic: hooking irqs not supported\n");
247     }
248
249   }
250
251   return 0;
252 }
253
254 int generic_deinit_device(struct vm_device * dev) {
255   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
256   uint_t i, j;
257
258   PrintDebug("generic: deinit_device\n");
259
260
261   for (i = 0; i < state->num_irq_ranges; i++) { 
262     
263     PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n", 
264                state->irq_ranges[i][0], state->irq_ranges[i][1]);
265
266     if (IRQ_HOOKS) { // This is a runtime conditional on a #define
267       for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
268
269         if (dev_unhook_irq(dev, j)) {
270           PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
271         }
272
273       }
274     } else {
275       PrintDebug("generic: unhooking irqs not supported\n");
276     }
277   }
278
279   for (i = 0; i < state->num_address_ranges; i++) { 
280
281     PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
282                state->address_ranges[i][0], state->address_ranges[i][1]); 
283
284     if (MEM_HOOKS) {
285       if (dev_unhook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
286
287         PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
288                    state->address_ranges[i][0], state->address_ranges[i][1]); 
289
290       }
291     } else {
292       PrintDebug("generic: unhooking addresses not supported\n");
293     }
294   }
295
296   for (i = 0; i < state->num_port_ranges; i++) { 
297     PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
298                state->port_ranges[i][0], state->port_ranges[i][1]);
299
300     if (PORT_HOOKS) {
301       for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
302         if (dev_unhook_io(dev, j)) {
303           PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", j);
304         }
305       }
306     } else {
307       PrintDebug("generic: unhooking ports not supported\n");
308     }
309
310   }
311
312   generic_reset_device(dev);
313   return 0;
314 }
315
316
317
318
319
320 static struct vm_device_ops dev_ops = { 
321   .init = generic_init_device, 
322   .deinit = generic_deinit_device,
323   .reset = generic_reset_device,
324   .start = generic_start_device,
325   .stop = generic_stop_device,
326 };
327
328
329
330
331 struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
332                                  generic_address_range_type address_ranges[],
333                                  generic_irq_range_type     irq_ranges[])
334 {
335   struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
336   int i;
337   uint_t num_port_ranges;
338   uint_t num_address_ranges;
339   uint_t num_irq_ranges;
340
341
342   num_port_ranges = 0;
343
344   if (port_ranges != NULL) { 
345     i = 0;
346
347     while ((port_ranges[i] != NULL) && 
348            ( !( (port_ranges[i][0] == 0) && 
349                 (port_ranges[i][1] == 0) && 
350                 (port_ranges[i][2] == 0)) ) ) 
351       {
352         num_port_ranges++; 
353         i++; 
354       }
355   }
356
357   
358   num_address_ranges = 0;
359
360   if (address_ranges != NULL) { 
361     i = 0;
362
363     while ((address_ranges[i] != NULL)  && 
364            ( !( (address_ranges[i][0] == 0) && 
365                 (address_ranges[i][1] == 0) && 
366                 (address_ranges[i][2] == 0)) ) ) 
367       { 
368         num_address_ranges++; 
369         i++; 
370       }
371   }
372
373   num_irq_ranges = 0;
374
375   if (irq_ranges != NULL) { 
376     i = 0;
377
378     while ((irq_ranges[i] != NULL) && 
379            ( !( (irq_ranges[i][0] == 0) && 
380                 (irq_ranges[i][1] == 0) && 
381                 (irq_ranges[i][2] == 0)) ) ) 
382       { 
383         num_irq_ranges++; 
384         i++; 
385       }
386   }
387     
388
389   generic_state->num_port_ranges = num_port_ranges;
390
391   if (num_port_ranges > 0) { 
392  
393    generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_port_ranges);
394    memcpy(generic_state->port_ranges, port_ranges, 
395           (sizeof(generic_port_range_type) * num_port_ranges));
396    
397   } else {
398     generic_state->port_ranges = NULL;
399   }
400
401
402   generic_state->num_address_ranges = num_address_ranges;
403
404   if (num_address_ranges > 0) { 
405
406     generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_address_ranges);
407     memcpy(generic_state->address_ranges, address_ranges, 
408            (sizeof(generic_address_range_type) * num_address_ranges));
409
410   } else {
411     generic_state->address_ranges = NULL;
412   }
413
414
415   generic_state->num_irq_ranges = num_irq_ranges;
416
417   if (num_irq_ranges > 0) { 
418
419     generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_irq_ranges);
420     memcpy(generic_state->irq_ranges, irq_ranges, 
421            (sizeof(generic_irq_range_type) * num_port_ranges));
422
423   } else {
424     generic_state->irq_ranges = NULL;
425   }
426
427   struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
428
429   return device;
430 }