1 #include <devices/generic.h>
3 #include <palacios/vmm.h>
4 #include <palacios/vmm_types.h>
8 #define GENERIC_DEBUG 1
11 #define GENERIC_DEBUG_PRINT(first, rest...) do { SerialPrint(first, ## rest ); } while (0)
13 #define GENERIC_DEBUG_PRINT(first, rest...)
18 #define MEM_HOOKS 0 // not yet implmented in device model
19 #define IRQ_HOOKS 0 // not yet implemented in device model
21 extern struct vmm_os_hooks *os_hooks;
23 extern void SerialPrint(const char *format, ...);
27 struct generic_internal {
28 generic_port_range_type *port_ranges;
29 uint_t num_port_ranges;
30 generic_address_range_type *address_ranges;
31 uint_t num_address_ranges;
32 generic_irq_range_type *irq_ranges;
33 uint_t num_irq_ranges;
43 int generic_reset_device(struct vm_device * dev)
45 GENERIC_DEBUG_PRINT("generic: reset device\n");
55 int generic_start_device(struct vm_device *dev)
57 GENERIC_DEBUG_PRINT("generic: start device\n");
62 int generic_stop_device(struct vm_device *dev)
64 GENERIC_DEBUG_PRINT("generic: stop device\n");
71 int generic_write_port(ushort_t port,
74 struct vm_device * dev)
78 GENERIC_DEBUG_PRINT("generic: writing 0x");
79 for (i=0;i<length;i++) {
80 GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
82 GENERIC_DEBUG_PRINT(" to port 0x%x ... ",port);
83 for (i=0;i<length;i++) {
84 Out_Byte(port,((uchar_t*)src)[i]);
86 GENERIC_DEBUG_PRINT(" done\n");
91 int generic_read_port(ushort_t port,
94 struct vm_device * dev)
98 GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...",length,port);
99 for (i=0;i<length;i++) {
100 ((uchar_t*)src)[i] =In_Byte(port);
102 GENERIC_DEBUG_PRINT(" done ... read 0x");
103 for (i=0;i<length;i++) {
104 GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
106 GENERIC_DEBUG_PRINT("\n");
113 int generic_interrupt(uint_t irq,
114 struct vm_device * dev)
116 PrintDebug("generic: interrupt 0x%x - injecting into VM\n",irq);
118 dev->vm->vm_ops.raise_irq(dev->vm,irq);
125 int generic_init_device(struct vm_device * dev)
127 struct generic_internal *state = (struct generic_internal *) dev->private_data;
130 GENERIC_DEBUG_PRINT("generic: init_device\n");
132 // Would read state here
134 generic_reset_device(dev);
136 for (i=0;i<state->num_port_ranges;i++) {
137 GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
139 for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) {
140 if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) {
141 GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n",j);
145 GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
150 for (i=0;i<state->num_address_ranges;i++) {
151 GENERIC_DEBUG_PRINT("generic: hooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]);
153 if (dev_hook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
154 GENERIC_DEBUG_PRINT("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
155 state->address_ranges[i][0],state->address_ranges[i][1]);
158 GENERIC_DEBUG_PRINT("generic: hooking addresses not supported\n");
163 for (i=0;i<state->num_irq_ranges;i++) {
164 GENERIC_DEBUG_PRINT("generic: hooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
166 for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) {
167 if (dev_hook_irq(dev, j, &generic_interrupt)) {
168 GENERIC_DEBUG_PRINT("generic: can't hook irq 0x%x (already hooked?)\n",j);
172 GENERIC_DEBUG_PRINT("generic: hooking irqs not supported\n");
179 int generic_deinit_device(struct vm_device *dev)
181 struct generic_internal *state = (struct generic_internal *) dev->private_data;
184 GENERIC_DEBUG_PRINT("generic: deinit_device\n");
186 for (i=0;i<state->num_irq_ranges;i++) {
187 GENERIC_DEBUG_PRINT("generic: unhooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
189 for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) {
190 if (dev_unhook_irq(dev, j)) {
191 GENERIC_DEBUG_PRINT("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
195 GENERIC_DEBUG_PRINT("generic: unhooking irqs not supported\n");
200 for (i=0;i<state->num_address_ranges;i++) {
201 GENERIC_DEBUG_PRINT("generic: unhooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]);
203 if (dev_unhook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
204 GENERIC_DEBUG_PRINT("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
205 state->address_ranges[i][0],state->address_ranges[i][1]);
208 GENERIC_DEBUG_PRINT("generic: unhooking addresses not supported\n");
212 for (i=0;i<state->num_port_ranges;i++) {
213 GENERIC_DEBUG_PRINT("generic: unhooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
215 for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) {
216 if (dev_unhook_io(dev, j)) {
217 GENERIC_DEBUG_PRINT("generic: can't unhook port 0x%x (already unhooked?)\n",j);
221 GENERIC_DEBUG_PRINT("generic: unhooking ports not supported\n");
226 generic_reset_device(dev);
234 static struct vm_device_ops dev_ops = {
235 .init = generic_init_device,
236 .deinit = generic_deinit_device,
237 .reset = generic_reset_device,
238 .start = generic_start_device,
239 .stop = generic_stop_device,
245 struct vm_device *create_generic(generic_port_range_type port_ranges[],
246 uint_t num_port_ranges,
247 generic_address_range_type address_ranges[],
248 uint_t num_address_ranges,
249 generic_irq_range_type irq_ranges[],
250 uint_t num_irq_ranges)
252 struct generic_internal * generic_state = os_hooks->malloc(sizeof(struct generic_internal));
255 generic_state->num_port_ranges=num_port_ranges;
256 if (num_port_ranges>0) {
257 generic_state->port_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_port_ranges);
258 memcpy(generic_state->port_ranges,port_ranges,sizeof(generic_port_range_type)*num_port_ranges);
260 generic_state->port_ranges=NULL;
263 generic_state->num_address_ranges=num_address_ranges;
264 if (num_address_ranges>0) {
265 generic_state->address_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_address_ranges);
266 memcpy(generic_state->address_ranges,address_ranges,sizeof(generic_address_range_type)*num_address_ranges);
268 generic_state->address_ranges=NULL;
270 generic_state->num_irq_ranges=num_irq_ranges;
271 if (num_irq_ranges>0) {
272 generic_state->irq_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_irq_ranges);
273 memcpy(generic_state->irq_ranges,irq_ranges,sizeof(generic_irq_range_type)*num_port_ranges);
275 generic_state->irq_ranges=NULL;
279 struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);