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