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.


removed references to GeekOS and added some namespace changes,
[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
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
80     v3_outb(port,((uchar_t*)src)[0]);
81     break;
82   case 2:
83     v3_outw(port,((ushort_t*)src)[0]);
84     break;
85   case 4:
86     v3_outdw(port,((uint_t*)src)[0]);
87
88     break;
89   default:
90     for (i = 0; i < length; i++) { 
91       v3_outb(port, ((uchar_t*)src)[i]);
92     }
93   } //switch length
94
95
96   PrintDebug(" done\n");
97   
98   return length;
99 }
100
101 int generic_read_port_passthrough(ushort_t port,
102                                   void * src, 
103                                   uint_t length,
104                                   struct vm_device * dev)
105 {
106   uint_t i;
107
108   PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
109
110
111     switch (length) {
112     case 1:
113       ((uchar_t*)src)[0] = v3_inb(port);
114       break;
115     case 2:
116       ((ushort_t*)src)[0] = v3_inw(port);
117       break;
118     case 4:
119       ((uint_t*)src)[0] = v3_indw(port);
120       break;
121     default:
122       for (i = 0; i < length; i++) { 
123         ((uchar_t*)src)[i] = v3_inb(port);
124       }
125     }//switch length
126
127   PrintDebug(" done ... read 0x");
128
129   for (i = 0; i < length; i++) { 
130     PrintDebug("%x", ((uchar_t*)src)[i]);
131   }
132
133   PrintDebug("\n");
134
135   return length;
136 }
137
138 int generic_write_port_ignore(ushort_t port,
139                               void * src, 
140                               uint_t length,
141                               struct vm_device * dev)
142 {
143   uint_t i;
144
145   PrintDebug("generic: writing 0x");
146
147   for (i = 0; i < length; i++) { 
148     PrintDebug("%x", ((uchar_t*)src)[i]);
149   }
150   
151   PrintDebug(" to port 0x%x ... ", port);
152
153   PrintDebug(" ignored\n");
154  
155   return length;
156 }
157
158 int generic_read_port_ignore(ushort_t port,
159                              void * src, 
160                              uint_t length,
161                              struct vm_device * dev)
162 {
163
164   PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
165
166   memset((char*)src, 0, length);
167   PrintDebug(" ignored (return zeroed buffer)\n");
168
169   return length;
170 }
171
172
173
174 int generic_interrupt(uint_t irq, struct vm_device * dev) {
175   PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
176
177   dev->vm->vm_ops.raise_irq(dev->vm, irq);
178
179   return 0;
180 }
181
182
183 int generic_init_device(struct vm_device * dev) {
184   struct generic_internal * state = (struct generic_internal *)(dev->private_data);
185   uint_t i, j;
186
187   PrintDebug("generic: init_device\n");
188
189   // Would read state here
190
191   generic_reset_device(dev);
192
193   for (i = 0; i < state->num_port_ranges; i++) { 
194
195     PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n", 
196                state->port_ranges[i][0], state->port_ranges[i][1], 
197                (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
198
199     if (PORT_HOOKS) { // This is a runtime conditional on a #define
200       for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
201         if (state->port_ranges[i][2] == GENERIC_PRINT_AND_PASSTHROUGH) { 
202
203           if (dev_hook_io(dev, j, &generic_read_port_passthrough, &generic_write_port_passthrough)) { 
204             PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
205           }
206
207         } else if (state->port_ranges[i][2] == GENERIC_PRINT_AND_IGNORE) { 
208
209           if (dev_hook_io(dev, j, &generic_read_port_ignore, &generic_write_port_ignore)) { 
210             PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", j);
211           }
212
213         } 
214       }
215     } else {
216       PrintDebug("generic: hooking ports not supported\n");
217     }
218
219   }
220
221   for (i = 0; i < state->num_address_ranges; i++) { 
222
223     PrintDebug("generic: hooking addresses 0x%x to 0x%x\n", 
224                state->address_ranges[i][0], state->address_ranges[i][1]); 
225
226     if (MEM_HOOKS) { // This is a runtime conditional on a #define
227       if (dev_hook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
228         PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
229                    state->address_ranges[i][0], state->address_ranges[i][1]); 
230       }
231     } else {
232       PrintDebug("generic: hooking addresses not supported\n");
233     }
234   }
235
236   for (i = 0; i < state->num_irq_ranges; i++) { 
237
238     PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
239                state->irq_ranges[i][0], state->irq_ranges[i][1]);
240
241     if (IRQ_HOOKS) { // This is a runtime conditional on a #define
242       for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
243         if (dev_hook_irq(dev, j, &generic_interrupt)) { 
244           PrintDebug("generic: can't hook irq  0x%x (already hooked?)\n", j);
245         }
246       }
247     } else {
248       PrintDebug("generic: hooking irqs not supported\n");
249     }
250
251   }
252
253   return 0;
254 }
255
256 int generic_deinit_device(struct vm_device * dev) {
257   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
258   uint_t i, j;
259
260   PrintDebug("generic: deinit_device\n");
261
262
263   for (i = 0; i < state->num_irq_ranges; i++) { 
264     
265     PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n", 
266                state->irq_ranges[i][0], state->irq_ranges[i][1]);
267
268     if (IRQ_HOOKS) { // This is a runtime conditional on a #define
269       for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
270
271         if (dev_unhook_irq(dev, j)) {
272           PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
273         }
274
275       }
276     } else {
277       PrintDebug("generic: unhooking irqs not supported\n");
278     }
279   }
280
281   for (i = 0; i < state->num_address_ranges; i++) { 
282
283     PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
284                state->address_ranges[i][0], state->address_ranges[i][1]); 
285
286     if (MEM_HOOKS) {
287       if (dev_unhook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
288
289         PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
290                    state->address_ranges[i][0], state->address_ranges[i][1]); 
291
292       }
293     } else {
294       PrintDebug("generic: unhooking addresses not supported\n");
295     }
296   }
297
298   for (i = 0; i < state->num_port_ranges; i++) { 
299     PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
300                state->port_ranges[i][0], state->port_ranges[i][1]);
301
302     if (PORT_HOOKS) {
303       for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
304         if (dev_unhook_io(dev, j)) {
305           PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", j);
306         }
307       }
308     } else {
309       PrintDebug("generic: unhooking ports not supported\n");
310     }
311
312   }
313
314   generic_reset_device(dev);
315   return 0;
316 }
317
318
319
320
321
322 static struct vm_device_ops dev_ops = { 
323   .init = generic_init_device, 
324   .deinit = generic_deinit_device,
325   .reset = generic_reset_device,
326   .start = generic_start_device,
327   .stop = generic_stop_device,
328 };
329
330
331
332
333 struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
334                                  generic_address_range_type address_ranges[],
335                                  generic_irq_range_type     irq_ranges[])
336 {
337   struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
338   int i;
339   uint_t num_port_ranges;
340   uint_t num_address_ranges;
341   uint_t num_irq_ranges;
342
343
344   num_port_ranges = 0;
345
346   if (port_ranges != NULL) { 
347     i = 0;
348
349     while ((port_ranges[i] != NULL) && 
350            ( !( (port_ranges[i][0] == 0) && 
351                 (port_ranges[i][1] == 0) && 
352                 (port_ranges[i][2] == 0)) ) ) 
353       {
354         num_port_ranges++; 
355         i++; 
356       }
357   }
358
359   
360   num_address_ranges = 0;
361
362   if (address_ranges != NULL) { 
363     i = 0;
364
365     while ((address_ranges[i] != NULL)  && 
366            ( !( (address_ranges[i][0] == 0) && 
367                 (address_ranges[i][1] == 0) && 
368                 (address_ranges[i][2] == 0)) ) ) 
369       { 
370         num_address_ranges++; 
371         i++; 
372       }
373   }
374
375   num_irq_ranges = 0;
376
377   if (irq_ranges != NULL) { 
378     i = 0;
379
380     while ((irq_ranges[i] != NULL) && 
381            ( !( (irq_ranges[i][0] == 0) && 
382                 (irq_ranges[i][1] == 0) && 
383                 (irq_ranges[i][2] == 0)) ) ) 
384       { 
385         num_irq_ranges++; 
386         i++; 
387       }
388   }
389     
390
391   generic_state->num_port_ranges = num_port_ranges;
392
393   if (num_port_ranges > 0) { 
394  
395    generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_port_ranges);
396    memcpy(generic_state->port_ranges, port_ranges, 
397           (sizeof(generic_port_range_type) * num_port_ranges));
398    
399   } else {
400     generic_state->port_ranges = NULL;
401   }
402
403
404   generic_state->num_address_ranges = num_address_ranges;
405
406   if (num_address_ranges > 0) { 
407
408     generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_address_ranges);
409     memcpy(generic_state->address_ranges, address_ranges, 
410            (sizeof(generic_address_range_type) * num_address_ranges));
411
412   } else {
413     generic_state->address_ranges = NULL;
414   }
415
416
417   generic_state->num_irq_ranges = num_irq_ranges;
418
419   if (num_irq_ranges > 0) { 
420
421     generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_irq_ranges);
422     memcpy(generic_state->irq_ranges, irq_ranges, 
423            (sizeof(generic_irq_range_type) * num_port_ranges));
424
425   } else {
426     generic_state->irq_ranges = NULL;
427   }
428
429   struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
430
431   return device;
432 }