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 now properly handles outwords and outdwords
[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 #define GENERIC_DEBUG 1
8
9 #if GENERIC_DEBUG
10 #define GENERIC_DEBUG_PRINT(first, rest...) PrintDebug(first, ##rest) 
11 #else
12 #define GENERIC_DEBUG_PRINT(first, rest...)
13 #endif
14
15
16 #define PORT_HOOKS 1
17 #define MEM_HOOKS  0   // not yet implmented in device model
18 #define IRQ_HOOKS  0   // not yet implemented in device model
19
20 struct generic_internal {
21   generic_port_range_type    *port_ranges;
22   uint_t                     num_port_ranges;
23   generic_address_range_type *address_ranges;
24   uint_t                     num_address_ranges;
25   generic_irq_range_type     *irq_ranges;
26   uint_t                     num_irq_ranges;
27 };
28
29
30   
31     
32
33
34
35
36 int generic_reset_device(struct vm_device * dev)
37 {
38   GENERIC_DEBUG_PRINT("generic: reset device\n");
39  
40   return 0;
41
42 }
43
44
45
46
47
48 int generic_start_device(struct vm_device *dev)
49 {
50   GENERIC_DEBUG_PRINT("generic: start device\n");
51   return 0;
52 }
53
54
55 int generic_stop_device(struct vm_device *dev)
56 {
57   GENERIC_DEBUG_PRINT("generic: stop device\n");
58   return 0;
59 }
60
61
62
63
64 int generic_write_port(ushort_t port,
65                        void * src, 
66                        uint_t length,
67                        struct vm_device * dev)
68 {
69   uint_t i;
70
71   GENERIC_DEBUG_PRINT("generic: writing 0x");
72
73   for (i = 0; i < length; i++) { 
74     GENERIC_DEBUG_PRINT("%x", ((uchar_t*)src)[i]);
75   }
76   
77   GENERIC_DEBUG_PRINT(" to port 0x%x ... ", port);
78
79   switch (length) {
80   case 1:
81     Out_Byte(port,((uchar_t*)src)[0]);
82     break;
83   case 2:
84     Out_Word(port,((ushort_t*)src)[0]);
85     break;
86   case 4:
87     Out_DWord(port,((uint_t*)src)[0]);
88     break;
89   default:
90     for (i = 0; i < length; i++) { 
91       Out_Byte(port, ((uchar_t*)src)[i]);
92     }
93   }
94
95   GENERIC_DEBUG_PRINT(" done\n");
96   
97   return length;
98 }
99
100 int generic_read_port(ushort_t port,
101                       void * src, 
102                       uint_t length,
103                       struct vm_device * dev)
104 {
105   uint_t i;
106
107   GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...", length, port);
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   }
124
125   GENERIC_DEBUG_PRINT(" done ... read 0x");
126
127   for (i = 0; i < length; i++) { 
128     GENERIC_DEBUG_PRINT("%x", ((uchar_t*)src)[i]);
129   }
130
131   GENERIC_DEBUG_PRINT("\n");
132
133   return length;
134 }
135
136
137
138 int generic_interrupt(uint_t irq,
139                       struct vm_device * dev) 
140 {
141   PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
142
143   dev->vm->vm_ops.raise_irq(dev->vm, irq);
144
145   return 0;
146
147 }
148
149
150 int generic_init_device(struct vm_device * dev) 
151 {
152   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
153   uint_t i, j;
154
155   GENERIC_DEBUG_PRINT("generic: init_device\n");
156
157   // Would read state here
158
159   generic_reset_device(dev);
160
161   for (i = 0; i < state->num_port_ranges; i++) { 
162     GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n", state->port_ranges[i][0], state->port_ranges[i][1]);
163
164 #if PORT_HOOKS
165     for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
166       if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) { 
167         GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n", j);
168       }
169     }
170 #else
171     GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
172 #endif
173
174   }
175
176   for (i = 0; i < state->num_address_ranges; i++) { 
177     GENERIC_DEBUG_PRINT("generic: hooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
178
179 #if MEM_HOOKS
180     if (dev_hook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
181       GENERIC_DEBUG_PRINT("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
182                   state->address_ranges[i][0], state->address_ranges[i][1]); 
183     }
184 #else
185     GENERIC_DEBUG_PRINT("generic: hooking addresses not supported\n");
186 #endif
187
188   }
189
190   for (i = 0; i < state->num_irq_ranges; i++) { 
191     GENERIC_DEBUG_PRINT("generic: hooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
192
193 #if IRQ_HOOKS
194     for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
195       if (dev_hook_irq(dev, j, &generic_interrupt)) { 
196         GENERIC_DEBUG_PRINT("generic: can't hook irq  0x%x (already hooked?)\n", j);
197       }
198     }
199 #else
200     GENERIC_DEBUG_PRINT("generic: hooking irqs not supported\n");
201 #endif
202
203   }
204
205   return 0;
206 }
207
208 int generic_deinit_device(struct vm_device *dev)
209 {
210   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
211   uint_t i, j;
212
213   GENERIC_DEBUG_PRINT("generic: deinit_device\n");
214
215   for (i = 0; i < state->num_irq_ranges; i++) { 
216     GENERIC_DEBUG_PRINT("generic: unhooking irqs 0x%x to 0x%x\n", state->irq_ranges[i][0], state->irq_ranges[i][1]);
217
218 #if IRQ_HOOKS
219     for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
220       if (dev_unhook_irq(dev, j)) {
221         GENERIC_DEBUG_PRINT("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
222       }
223     }
224 #else
225     GENERIC_DEBUG_PRINT("generic: unhooking irqs not supported\n");
226 #endif
227
228   }
229
230   for (i = 0; i < state->num_address_ranges; i++) { 
231     GENERIC_DEBUG_PRINT("generic: unhooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
232
233 #if MEM_HOOKS
234     if (dev_unhook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
235       GENERIC_DEBUG_PRINT("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
236                   state->address_ranges[i][0], state->address_ranges[i][1]); 
237     }
238 #else
239     GENERIC_DEBUG_PRINT("generic: unhooking addresses not supported\n");
240 #endif
241
242   }
243
244   for (i = 0; i < state->num_port_ranges; i++) { 
245     GENERIC_DEBUG_PRINT("generic: unhooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
246
247 #if PORT_HOOKS
248     for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
249       if (dev_unhook_io(dev, j)) {
250         GENERIC_DEBUG_PRINT("generic: can't unhook port 0x%x (already unhooked?)\n", j);
251       }
252     }
253 #else
254     GENERIC_DEBUG_PRINT("generic: unhooking ports not supported\n");
255 #endif
256
257   }
258
259   generic_reset_device(dev);
260   return 0;
261 }
262
263
264
265
266
267 static struct vm_device_ops dev_ops = { 
268   .init = generic_init_device, 
269   .deinit = generic_deinit_device,
270   .reset = generic_reset_device,
271   .start = generic_start_device,
272   .stop = generic_stop_device,
273 };
274
275
276
277
278 struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
279                                  uint_t                     num_port_ranges,
280                                  generic_address_range_type address_ranges[],
281                                  uint_t                     num_address_ranges,
282                                  generic_irq_range_type     irq_ranges[],
283                                  uint_t                     num_irq_ranges)
284 {
285   struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
286
287
288   generic_state->num_port_ranges = num_port_ranges;
289
290   if (num_port_ranges > 0) { 
291     generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_port_ranges);
292     memcpy(generic_state->port_ranges, port_ranges, sizeof(generic_port_range_type) * num_port_ranges);
293   } else {
294     generic_state->port_ranges = NULL;
295   }
296
297
298   generic_state->num_address_ranges = num_address_ranges;
299
300   if (num_address_ranges > 0) { 
301     generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_address_ranges);
302     memcpy(generic_state->address_ranges, address_ranges, sizeof(generic_address_range_type) * num_address_ranges);
303   } else {
304     generic_state->address_ranges = NULL;
305   }
306
307
308   generic_state->num_irq_ranges = num_irq_ranges;
309
310   if (num_irq_ranges > 0) { 
311     generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_irq_ranges);
312     memcpy(generic_state->irq_ranges, irq_ranges, sizeof(generic_irq_range_type) * num_port_ranges);
313   } else {
314     generic_state->irq_ranges = NULL;
315   }
316
317
318   struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
319
320   return device;
321 }