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.


*** empty log message ***
[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   for (i = 0; i < length; i++) { 
80     Out_Byte(port, ((uchar_t*)src)[i]);
81   }
82
83   GENERIC_DEBUG_PRINT(" done\n");
84   
85   return length;
86 }
87
88 int generic_read_port(ushort_t port,
89                       void * src, 
90                       uint_t length,
91                       struct vm_device * dev)
92 {
93   uint_t i;
94
95   GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...", length, port);
96
97   for (i = 0; i < length; i++) { 
98     ((uchar_t*)src)[i] = In_Byte(port);
99   }
100
101   GENERIC_DEBUG_PRINT(" done ... read 0x");
102
103   for (i = 0; i < length; i++) { 
104     GENERIC_DEBUG_PRINT("%x", ((uchar_t*)src)[i]);
105   }
106
107   GENERIC_DEBUG_PRINT("\n");
108
109   return length;
110 }
111
112
113
114 int generic_interrupt(uint_t irq,
115                       struct vm_device * dev) 
116 {
117   PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
118
119   dev->vm->vm_ops.raise_irq(dev->vm, irq);
120
121   return 0;
122
123 }
124
125
126 int generic_init_device(struct vm_device * dev) 
127 {
128   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
129   uint_t i, j;
130
131   GENERIC_DEBUG_PRINT("generic: init_device\n");
132
133   // Would read state here
134
135   generic_reset_device(dev);
136
137   for (i = 0; i < state->num_port_ranges; i++) { 
138     GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n", state->port_ranges[i][0], state->port_ranges[i][1]);
139
140 #if PORT_HOOKS
141     for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
142       if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) { 
143         GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n", j);
144       }
145     }
146 #else
147     GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
148 #endif
149
150   }
151
152   for (i = 0; i < state->num_address_ranges; i++) { 
153     GENERIC_DEBUG_PRINT("generic: hooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
154
155 #if MEM_HOOKS
156     if (dev_hook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
157       GENERIC_DEBUG_PRINT("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
158                   state->address_ranges[i][0], state->address_ranges[i][1]); 
159     }
160 #else
161     GENERIC_DEBUG_PRINT("generic: hooking addresses not supported\n");
162 #endif
163
164   }
165
166   for (i = 0; i < state->num_irq_ranges; i++) { 
167     GENERIC_DEBUG_PRINT("generic: hooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
168
169 #if IRQ_HOOKS
170     for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
171       if (dev_hook_irq(dev, j, &generic_interrupt)) { 
172         GENERIC_DEBUG_PRINT("generic: can't hook irq  0x%x (already hooked?)\n", j);
173       }
174     }
175 #else
176     GENERIC_DEBUG_PRINT("generic: hooking irqs not supported\n");
177 #endif
178
179   }
180
181   return 0;
182 }
183
184 int generic_deinit_device(struct vm_device *dev)
185 {
186   struct generic_internal *state = (struct generic_internal *)(dev->private_data);
187   uint_t i, j;
188
189   GENERIC_DEBUG_PRINT("generic: deinit_device\n");
190
191   for (i = 0; i < state->num_irq_ranges; i++) { 
192     GENERIC_DEBUG_PRINT("generic: unhooking irqs 0x%x to 0x%x\n", state->irq_ranges[i][0], state->irq_ranges[i][1]);
193
194 #if IRQ_HOOKS
195     for (j = state->irq_ranges[i][0]; j <= state->irq_ranges[i][1]; j++) { 
196       if (dev_unhook_irq(dev, j)) {
197         GENERIC_DEBUG_PRINT("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
198       }
199     }
200 #else
201     GENERIC_DEBUG_PRINT("generic: unhooking irqs not supported\n");
202 #endif
203
204   }
205
206   for (i = 0; i < state->num_address_ranges; i++) { 
207     GENERIC_DEBUG_PRINT("generic: unhooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
208
209 #if MEM_HOOKS
210     if (dev_unhook_mem(dev, state->address_ranges[i][0], state->address_ranges[i][1])) {
211       GENERIC_DEBUG_PRINT("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
212                   state->address_ranges[i][0], state->address_ranges[i][1]); 
213     }
214 #else
215     GENERIC_DEBUG_PRINT("generic: unhooking addresses not supported\n");
216 #endif
217
218   }
219
220   for (i = 0; i < state->num_port_ranges; i++) { 
221     GENERIC_DEBUG_PRINT("generic: unhooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
222
223 #if PORT_HOOKS
224     for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) { 
225       if (dev_unhook_io(dev, j)) {
226         GENERIC_DEBUG_PRINT("generic: can't unhook port 0x%x (already unhooked?)\n", j);
227       }
228     }
229 #else
230     GENERIC_DEBUG_PRINT("generic: unhooking ports not supported\n");
231 #endif
232
233   }
234
235   generic_reset_device(dev);
236   return 0;
237 }
238
239
240
241
242
243 static struct vm_device_ops dev_ops = { 
244   .init = generic_init_device, 
245   .deinit = generic_deinit_device,
246   .reset = generic_reset_device,
247   .start = generic_start_device,
248   .stop = generic_stop_device,
249 };
250
251
252
253
254 struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
255                                  uint_t                     num_port_ranges,
256                                  generic_address_range_type address_ranges[],
257                                  uint_t                     num_address_ranges,
258                                  generic_irq_range_type     irq_ranges[],
259                                  uint_t                     num_irq_ranges)
260 {
261   struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
262
263
264   generic_state->num_port_ranges = num_port_ranges;
265
266   if (num_port_ranges > 0) { 
267     generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_port_ranges);
268     memcpy(generic_state->port_ranges, port_ranges, sizeof(generic_port_range_type) * num_port_ranges);
269   } else {
270     generic_state->port_ranges = NULL;
271   }
272
273
274   generic_state->num_address_ranges = num_address_ranges;
275
276   if (num_address_ranges > 0) { 
277     generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_address_ranges);
278     memcpy(generic_state->address_ranges, address_ranges, sizeof(generic_address_range_type) * num_address_ranges);
279   } else {
280     generic_state->address_ranges = NULL;
281   }
282
283
284   generic_state->num_irq_ranges = num_irq_ranges;
285
286   if (num_irq_ranges > 0) { 
287     generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type) * num_irq_ranges);
288     memcpy(generic_state->irq_ranges, irq_ranges, sizeof(generic_irq_range_type) * num_port_ranges);
289   } else {
290     generic_state->irq_ranges = NULL;
291   }
292
293
294   struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
295
296   return device;
297 }