1 #include <devices/generic.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmm_types.h>
7 #define GENERIC_DEBUG 1
10 #define GENERIC_DEBUG_PRINT(first, rest...) PrintDebug(first, ##rest)
12 #define GENERIC_DEBUG_PRINT(first, rest...)
17 #define MEM_HOOKS 0 // not yet implmented in device model
18 #define IRQ_HOOKS 0 // not yet implemented in device model
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;
36 int generic_reset_device(struct vm_device * dev)
38 GENERIC_DEBUG_PRINT("generic: reset device\n");
48 int generic_start_device(struct vm_device *dev)
50 GENERIC_DEBUG_PRINT("generic: start device\n");
55 int generic_stop_device(struct vm_device *dev)
57 GENERIC_DEBUG_PRINT("generic: stop device\n");
64 int generic_write_port(ushort_t port,
67 struct vm_device * dev)
71 GENERIC_DEBUG_PRINT("generic: writing 0x");
72 for (i=0;i<length;i++) {
73 GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
75 GENERIC_DEBUG_PRINT(" to port 0x%x ... ",port);
76 for (i=0;i<length;i++) {
77 Out_Byte(port,((uchar_t*)src)[i]);
79 GENERIC_DEBUG_PRINT(" done\n");
84 int generic_read_port(ushort_t port,
87 struct vm_device * dev)
91 GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...",length,port);
92 for (i=0;i<length;i++) {
93 ((uchar_t*)src)[i] =In_Byte(port);
95 GENERIC_DEBUG_PRINT(" done ... read 0x");
96 for (i=0;i<length;i++) {
97 GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
99 GENERIC_DEBUG_PRINT("\n");
106 int generic_interrupt(uint_t irq,
107 struct vm_device * dev)
109 PrintDebug("generic: interrupt 0x%x - injecting into VM\n",irq);
111 dev->vm->vm_ops.raise_irq(dev->vm,irq);
118 int generic_init_device(struct vm_device * dev)
120 struct generic_internal *state = (struct generic_internal *) dev->private_data;
123 GENERIC_DEBUG_PRINT("generic: init_device\n");
125 // Would read state here
127 generic_reset_device(dev);
129 for (i=0;i<state->num_port_ranges;i++) {
130 GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
132 for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) {
133 if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) {
134 GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n",j);
138 GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
143 for (i=0;i<state->num_address_ranges;i++) {
144 GENERIC_DEBUG_PRINT("generic: hooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]);
146 if (dev_hook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
147 GENERIC_DEBUG_PRINT("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
148 state->address_ranges[i][0],state->address_ranges[i][1]);
151 GENERIC_DEBUG_PRINT("generic: hooking addresses not supported\n");
156 for (i=0;i<state->num_irq_ranges;i++) {
157 GENERIC_DEBUG_PRINT("generic: hooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
159 for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) {
160 if (dev_hook_irq(dev, j, &generic_interrupt)) {
161 GENERIC_DEBUG_PRINT("generic: can't hook irq 0x%x (already hooked?)\n",j);
165 GENERIC_DEBUG_PRINT("generic: hooking irqs not supported\n");
172 int generic_deinit_device(struct vm_device *dev)
174 struct generic_internal *state = (struct generic_internal *) dev->private_data;
177 GENERIC_DEBUG_PRINT("generic: deinit_device\n");
179 for (i=0;i<state->num_irq_ranges;i++) {
180 GENERIC_DEBUG_PRINT("generic: unhooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
182 for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) {
183 if (dev_unhook_irq(dev, j)) {
184 GENERIC_DEBUG_PRINT("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
188 GENERIC_DEBUG_PRINT("generic: unhooking irqs not supported\n");
193 for (i=0;i<state->num_address_ranges;i++) {
194 GENERIC_DEBUG_PRINT("generic: unhooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]);
196 if (dev_unhook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
197 GENERIC_DEBUG_PRINT("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
198 state->address_ranges[i][0],state->address_ranges[i][1]);
201 GENERIC_DEBUG_PRINT("generic: unhooking addresses not supported\n");
205 for (i=0;i<state->num_port_ranges;i++) {
206 GENERIC_DEBUG_PRINT("generic: unhooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
208 for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) {
209 if (dev_unhook_io(dev, j)) {
210 GENERIC_DEBUG_PRINT("generic: can't unhook port 0x%x (already unhooked?)\n",j);
214 GENERIC_DEBUG_PRINT("generic: unhooking ports not supported\n");
219 generic_reset_device(dev);
227 static struct vm_device_ops dev_ops = {
228 .init = generic_init_device,
229 .deinit = generic_deinit_device,
230 .reset = generic_reset_device,
231 .start = generic_start_device,
232 .stop = generic_stop_device,
238 struct vm_device *create_generic(generic_port_range_type port_ranges[],
239 uint_t num_port_ranges,
240 generic_address_range_type address_ranges[],
241 uint_t num_address_ranges,
242 generic_irq_range_type irq_ranges[],
243 uint_t num_irq_ranges)
245 struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
248 generic_state->num_port_ranges=num_port_ranges;
249 if (num_port_ranges>0) {
250 generic_state->port_ranges = V3_Malloc(sizeof(generic_address_range_type)*num_port_ranges);
251 memcpy(generic_state->port_ranges,port_ranges,sizeof(generic_port_range_type)*num_port_ranges);
253 generic_state->port_ranges=NULL;
256 generic_state->num_address_ranges=num_address_ranges;
257 if (num_address_ranges>0) {
258 generic_state->address_ranges = V3_Malloc(sizeof(generic_address_range_type)*num_address_ranges);
259 memcpy(generic_state->address_ranges,address_ranges,sizeof(generic_address_range_type)*num_address_ranges);
261 generic_state->address_ranges=NULL;
263 generic_state->num_irq_ranges=num_irq_ranges;
264 if (num_irq_ranges>0) {
265 generic_state->irq_ranges = V3_Malloc(sizeof(generic_address_range_type)*num_irq_ranges);
266 memcpy(generic_state->irq_ranges,irq_ranges,sizeof(generic_irq_range_type)*num_port_ranges);
268 generic_state->irq_ranges=NULL;
272 struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);