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.


modified pci io hooks to not use the dev_io hooks, which are too constrictive
[palacios.git] / palacios / src / devices / pci.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
12  * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu>
13  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author:  Lei Xia <lxia@northwestern.edu>
17  *          Chang Seok Bae <jhuell@gmail.com>
18  *          Jack Lange <jarusl@cs.northwestern.edu>
19  *
20  * This is free software.  You are permitted to use,
21  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22  */ 
23  
24  
25
26 #include <palacios/vmm.h>
27 #include <palacios/vmm_types.h>
28 #include <palacios/vmm_io.h>
29 #include <palacios/vmm_intr.h>
30 #include <palacios/vmm_rbtree.h>
31
32 #include <devices/pci.h>
33 #include <devices/pci_types.h>
34
35 #ifndef CONFIG_DEBUG_PCI
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40
41 #define CONFIG_ADDR_PORT    0x0cf8
42 #define CONFIG_DATA_PORT    0x0cfc
43
44 #define PCI_DEV_IO_PORT_BASE 0xc000
45
46 #define PCI_BUS_COUNT 1
47
48 // This must always be a multiple of 8
49 #define MAX_BUS_DEVICES 32
50
51 struct pci_addr_reg {
52     union {
53         uint32_t val;
54         struct {
55             uint_t rsvd       : 2;
56             uint_t reg_num    : 6;
57             uint_t fn_num     : 3;
58             uint_t dev_num    : 5;
59             uint_t bus_num    : 8;
60             uint_t rsvd2      : 7;
61             uint_t enable     : 1;
62         } __attribute__((packed));
63     } __attribute__((packed));
64 } __attribute__((packed));
65
66
67
68
69
70 struct pci_bus {
71     int bus_num;
72
73     // Red Black tree containing all attached devices
74     struct rb_root devices;
75
76     // Bitmap of the allocated device numbers
77     uint8_t dev_map[MAX_BUS_DEVICES / 8];
78
79
80     int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev);
81     int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev);
82     struct vm_device * irq_bridge_dev;
83 };
84
85
86
87 struct pci_internal {
88     // Configuration address register
89     struct pci_addr_reg addr_reg;
90
91     // Base IO Port which PCI devices will register with...
92     uint16_t dev_io_base; 
93
94     // Attached Busses
95     struct pci_bus bus_list[PCI_BUS_COUNT];
96 };
97
98
99
100
101
102 #ifdef CONFIG_DEBUG_PCI
103
104 static void pci_dump_state(struct pci_internal * pci_state) {
105     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
106     struct pci_device * tmp_dev = NULL;
107     
108     PrintDebug("===PCI: Dumping state Begin ==========\n");
109     
110     do {
111         tmp_dev = rb_entry(node, struct pci_device, dev_tree_node);
112
113         PrintDebug("PCI Device Number: %d (%s):\n", tmp_dev->dev_num,  tmp_dev->name);
114         PrintDebug("irq = %d\n", tmp_dev->config_header.intr_line);
115         PrintDebug("Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id);
116         PrintDebug("Device ID: 0x%x\n", tmp_dev->config_header.device_id);
117
118     } while ((node = v3_rb_next(node)));
119     
120     PrintDebug("====PCI: Dumping state End==========\n");
121 }
122
123 #endif
124
125
126
127
128 // Scan the dev_map bitmap for the first '0' bit
129 static int get_free_dev_num(struct pci_bus * bus) {
130     int i, j;
131
132     for (i = 0; i < sizeof(bus->dev_map); i++) {
133         PrintDebug("i=%d\n", i);
134         if (bus->dev_map[i] != 0xff) {
135             // availability
136             for (j = 0; j < 8; j++) {
137                 PrintDebug("\tj=%d\n", j);
138                 if (!(bus->dev_map[i] & (0x1 << j))) {
139                     return ((i * 8) + j);
140                 }
141             }
142         }
143     }
144
145     return -1;
146 }
147
148 static void allocate_dev_num(struct pci_bus * bus, int dev_num) {
149     int major = (dev_num / 8);
150     int minor = dev_num % 8;
151
152     bus->dev_map[major] |= (0x1 << minor);
153 }
154
155
156
157 static inline 
158 struct pci_device * __add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
159
160   struct rb_node ** p = &(bus->devices.rb_node);
161   struct rb_node * parent = NULL;
162   struct pci_device * tmp_dev = NULL;
163
164   while (*p) {
165     parent = *p;
166     tmp_dev = rb_entry(parent, struct pci_device, dev_tree_node);
167
168     if (dev->devfn < tmp_dev->devfn) {
169       p = &(*p)->rb_left;
170     } else if (dev->devfn > tmp_dev->devfn) {
171       p = &(*p)->rb_right;
172     } else {
173       return tmp_dev;
174     }
175   }
176
177   rb_link_node(&(dev->dev_tree_node), parent, p);
178
179   return NULL;
180 }
181
182
183 static inline 
184 struct pci_device * add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
185
186   struct pci_device * ret = NULL;
187
188   if ((ret = __add_device_to_bus(bus, dev))) {
189     return ret;
190   }
191
192   v3_rb_insert_color(&(dev->dev_tree_node), &(bus->devices));
193
194   allocate_dev_num(bus, dev->dev_num);
195
196   return NULL;
197 }
198
199
200 static struct pci_device * get_device(struct pci_bus * bus, uint8_t dev_num, uint8_t fn_num) {
201     struct rb_node * n = bus->devices.rb_node;
202     struct pci_device * dev = NULL;
203     uint8_t devfn = ((dev_num & 0x1f) << 3) | (fn_num & 0x7);
204
205     while (n) {
206         dev = rb_entry(n, struct pci_device, dev_tree_node);
207         
208         if (devfn < dev->devfn) {
209             n = n->rb_left;
210         } else if (devfn > dev->devfn) {
211             n = n->rb_right;
212         } else {
213             return dev;
214         }
215     }
216     
217     return NULL;
218 }
219
220
221
222
223
224
225
226 static int addr_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
227     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
228     int reg_offset = port & 0x3;
229     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
230
231     PrintDebug("Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length);
232
233     if (length == 4) {
234         if (reg_offset != 0) {
235             PrintError("Invalid Address Port Read\n");
236             return -1;
237         }
238         *(uint32_t *)dst = *(uint32_t *)reg_addr;
239     } else if (length == 2) {
240         if (reg_offset > 2) {
241             PrintError("Invalid Address Port Read\n");
242             return -1;
243         }
244         *(uint16_t *)dst = *(uint16_t *)reg_addr;
245     } else if (length == 1) {
246         *(uint8_t *)dst = *(uint8_t *)reg_addr;
247     } else {
248         PrintError("Invalid read length (%d) for PCI address register\n", length);
249         return -1;
250     }
251     
252
253     return length;
254 }
255
256
257 static int addr_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
258     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
259     int reg_offset = port & 0x3; 
260     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
261
262
263     if (length == 4) {
264         if (reg_offset != 0) {
265             PrintError("Invalid Address Port Write\n");
266             return -1;
267         }
268
269         PrintDebug("Writing PCI 4 bytes Val=%x\n",  *(uint32_t *)src);
270
271         *(uint32_t *)reg_addr = *(uint32_t *)src;
272     } else if (length == 2) {
273         if (reg_offset > 2) {
274             PrintError("Invalid Address Port Write\n");
275             return -1;
276         }
277
278         PrintDebug("Writing PCI 2 byte Val=%x\n",  *(uint16_t *)src);
279
280         *(uint16_t *)reg_addr = *(uint16_t *)src;
281     } else if (length == 1) {
282         PrintDebug("Writing PCI 1 byte Val=%x\n",  *(uint8_t *)src);
283         *(uint8_t *)reg_addr = *(uint8_t *)src;
284     } else {
285         PrintError("Invalid write length (%d) for PCI address register\n", length);
286         return -1;
287     }
288
289     PrintDebug("Writing PCI Address Port(%x): %x\n", port, pci_state->addr_reg.val);
290
291     return length;
292 }
293
294
295 static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
296     struct pci_internal * pci_state =  (struct pci_internal *)(vmdev->private_data);
297     struct pci_device * pci_dev = NULL;
298     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
299     int i;
300
301     if (pci_state->addr_reg.bus_num != 0) {
302         int i = 0;
303         for (i = 0; i < length; i++) {
304             *((uint8_t *)dst + i) = 0xff;
305         }
306
307         return length;
308     }
309
310     PrintDebug("Reading PCI Data register. bus = %d, dev = %d, reg = %d (%x), cfg_reg = %x\n", 
311                pci_state->addr_reg.bus_num, 
312                pci_state->addr_reg.dev_num, 
313                reg_num, reg_num, 
314                pci_state->addr_reg.val);
315
316     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
317     
318     if (pci_dev == NULL) {
319         for (i = 0; i < length; i++) {
320             *(uint8_t *)((uint8_t *)dst + i) = 0xff;
321         }
322
323         return length;
324     }
325
326     for (i = 0; i < length; i++) {
327         *(uint8_t *)((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
328     }
329
330     PrintDebug("\tVal=%x, len=%d\n", *(uint32_t *)dst, length);
331
332     return length;
333 }
334
335
336 static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
337     if (header_type == 0x00) {
338         switch (reg_num) {
339             case 0x00:
340             case 0x01:
341             case 0x02:
342             case 0x03:
343             case 0x08:
344             case 0x09:
345             case 0x0a:
346             case 0x0b:
347             case 0x0e:
348             case 0x3d:
349                 return 0;
350                            
351            default:
352                return 1;
353  
354         }
355     } else if (header_type == 0x80) {
356         switch (reg_num) {
357             case 0x00:
358             case 0x01:
359             case 0x02:
360             case 0x03:
361             case 0x08:
362             case 0x09:
363             case 0x0a:
364             case 0x0b:
365             case 0x0e:
366             case 0x3d:
367                 return 0;
368                            
369            default:
370                return 1;
371  
372         }
373     } else {
374         // PCI to PCI Bridge = 0x01
375         // CardBus Bridge = 0x02
376
377         // huh?
378         PrintError("Invalid PCI Header type (0x%.2x)\n", header_type);
379
380         return -1;
381     }
382 }
383
384
385 static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
386     struct v3_pci_bar * bar = &(pci->bar[bar_num]);
387
388     PrintDebug("Updating BAR Register  (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x)\n", 
389                pci->name, bar_num, bar->val, new_val);
390
391     switch (bar->type) {
392         case PCI_BAR_IO: {
393             int i = 0;
394
395             PrintDebug("\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n",
396                        bar->num_ports, PCI_IO_BASE(bar->val), PCI_IO_BASE(new_val),
397                        bar->num_ports);
398                 
399             // only do this if pci device is enabled....
400             if (!(pci->config_header.status & 0x1)) {
401                 PrintError("PCI Device IO space not enabled\n");
402             }
403
404             for (i = 0; i < bar->num_ports; i++) {
405
406                 PrintDebug("Rehooking PCI IO port (old port=%u) (new port=%u)\n",  
407                            PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
408
409                 v3_unhook_io_port(pci->vm_dev->vm, PCI_IO_BASE(bar->val) + i);
410
411                 if (v3_hook_io_port(pci->vm_dev->vm, PCI_IO_BASE(new_val) + i, 
412                                     bar->io_read, bar->io_write, 
413                                     bar->private_data) == -1) {
414
415                     PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
416                                PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
417                     return -1;
418                 }
419             }
420
421             bar->val = new_val;
422
423             break;
424         }
425         case PCI_BAR_MEM32: {
426             v3_unhook_mem(pci->vm_dev->vm, (addr_t)(bar->val));
427             
428             if (bar->mem_read) {
429                 v3_hook_full_mem(pci->vm_dev->vm, PCI_MEM32_BASE(new_val), 
430                                  PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB),
431                                  bar->mem_read, bar->mem_write, pci->vm_dev);
432             } else {
433                 PrintError("Write hooks not supported for PCI\n");
434                 return -1;
435             }
436
437             bar->val = new_val;
438
439             break;
440         }
441         case PCI_BAR_NONE: {
442             PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
443                        pci->name, bar_num, new_val);
444             break;
445         }
446         default:
447             PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num);
448             return -1;
449     }
450
451     return 0;
452 }
453
454
455 static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
456     struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
457     struct pci_device * pci_dev = NULL;
458     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
459     int i;
460
461
462     if (pci_state->addr_reg.bus_num != 0) {
463         return length;
464     }
465
466     PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
467                pci_state->addr_reg.bus_num, 
468                pci_state->addr_reg.dev_num, 
469                pci_state->addr_reg.fn_num,
470                reg_num, reg_num, 
471                pci_state->addr_reg.val,
472                *(uint32_t *)src, length);
473
474
475     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
476     
477     if (pci_dev == NULL) {
478         PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
479                    pci_state->addr_reg.dev_num); 
480         return -1;
481     }
482     
483
484     for (i = 0; i < length; i++) {
485         uint_t cur_reg = reg_num + i;
486         int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
487         
488         if (writable == -1) {
489             PrintError("Invalid PCI configuration space\n");
490             return -1;
491         }
492
493         if (writable) {
494             pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
495
496             if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
497                 // BAR Register Update
498                 int bar_reg = ((cur_reg & ~0x3) - 0x10) / 4;
499                 
500                 pci_dev->bar_update_flag = 1;
501                 pci_dev->bar[bar_reg].updated = 1;
502                 
503                 // PrintDebug("Updating BAR register %d\n", bar_reg);
504
505             } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
506                 // Extension ROM update
507
508                 pci_dev->ext_rom_update_flag = 1;
509             } else if (cur_reg == 0x04) {
510                 // COMMAND update            
511                 uint8_t command = *((uint8_t *)src + i);
512                 
513                 PrintError("command update for %s old=%x new=%x\n",
514                            pci_dev->name, 
515                            pci_dev->config_space[cur_reg],command);
516
517                 pci_dev->config_space[cur_reg] = command;             
518
519                 if (pci_dev->cmd_update) {
520                     pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
521                 }
522                 
523             } else if (cur_reg == 0x0f) {
524                 // BIST update
525                 pci_dev->config_header.BIST = 0x00;
526             }
527         } else {
528             PrintError("PCI Write to read only register %d\n", cur_reg);
529         }
530     }
531
532     if (pci_dev->config_update) {
533         pci_dev->config_update(pci_dev, reg_num, length);
534     }
535
536     // Scan for BAR updated
537     if (pci_dev->bar_update_flag) {
538         for (i = 0; i < 6; i++) {
539             if (pci_dev->bar[i].updated) {
540                 int bar_offset = 0x10 + 4 * i;
541
542                 *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
543                 // check special flags....
544
545                 // bar_update
546                 if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
547                     PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
548                     return -1;
549                 }
550
551                 pci_dev->bar[i].updated = 0;
552             }
553         }
554         pci_dev->bar_update_flag = 0;
555     }
556
557     if ((pci_dev->ext_rom_update_flag) && (pci_dev->ext_rom_update)) {
558         pci_dev->ext_rom_update(pci_dev);
559         pci_dev->ext_rom_update_flag = 0;
560     }
561
562
563     return length;
564 }
565
566
567
568 static int pci_reset_device(struct vm_device * dev) {
569     PrintDebug("pci: reset device\n");    
570     return 0;
571 }
572
573
574 static int pci_start_device(struct vm_device * dev) {
575     PrintDebug("pci: start device\n");
576     return 0;
577 }
578
579
580 static int pci_stop_device(struct vm_device * dev) {
581     PrintDebug("pci: stop device\n");  
582     return 0;
583 }
584
585
586
587 static int pci_free(struct vm_device * dev) {
588     int i = 0;
589     
590     for (i = 0; i < 4; i++){
591         v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i);
592         v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i);
593     }
594     
595     return 0;
596 }
597
598
599
600 static void init_pci_busses(struct pci_internal * pci_state) {
601     int i;
602
603     for (i = 0; i < PCI_BUS_COUNT; i++) {
604         pci_state->bus_list[i].bus_num = i;
605         pci_state->bus_list[i].devices.rb_node = NULL;
606         memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map));
607     }
608 }
609
610
611
612
613 static struct v3_device_ops dev_ops = {
614     .free = pci_free,
615     .reset = pci_reset_device,
616     .start = pci_start_device,
617     .stop = pci_stop_device,
618 };
619
620
621
622
623 static int pci_init(struct guest_info * vm, void * cfg_data) {
624     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
625     int i = 0;
626     
627     PrintDebug("PCI internal at %p\n",(void *)pci_state);
628     
629     struct vm_device * dev = v3_allocate_device("PCI", &dev_ops, pci_state);
630     
631     if (v3_attach_device(vm, dev) == -1) {
632         PrintError("Could not attach device %s\n", "PCI");
633         return -1;
634     }
635
636     
637     pci_state->addr_reg.val = 0; 
638     pci_state->dev_io_base = PCI_DEV_IO_PORT_BASE;
639
640     init_pci_busses(pci_state);
641     
642     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
643     
644     for (i = 0; i < 4; i++) {
645         v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
646         v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
647     }
648
649     return 0;
650 }
651
652
653 device_register("PCI", pci_init)
654
655
656 static inline int init_bars(struct pci_device * pci_dev) {
657     int i = 0;
658
659     for (i = 0; i < 6; i++) {
660         int bar_offset = 0x10 + (4 * i);
661
662         if (pci_dev->bar[i].type == PCI_BAR_IO) {
663             int j = 0;
664             pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
665
666             if (pci_dev->bar[i].default_base_port != 0xffff) {
667                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
668             } else {
669                 pci_dev->bar[i].val = 0;
670             }
671
672             pci_dev->bar[i].val |= 0x00000001;
673
674             for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
675                 // hook IO
676                 if (pci_dev->bar[i].default_base_port != 0xffff) {
677                     if (v3_hook_io_port(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_port + j,
678                                         pci_dev->bar[i].io_read, pci_dev->bar[i].io_write, 
679                                         pci_dev->bar[i].private_data) == -1) {
680                         PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
681                         return -1;
682                     }
683                 }
684             }
685
686             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
687
688         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
689             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
690             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
691
692             if (pci_dev->bar[i].default_base_addr != 0xffffffff) {
693                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
694             } else {
695                 pci_dev->bar[i].val = 0;
696             }
697
698             // hook memory
699             if (pci_dev->bar[i].mem_read) {
700                 // full hook
701                 v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
702                                  pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
703                                  pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
704             } else if (pci_dev->bar[i].mem_write) {
705                 // write hook
706                 PrintError("Write hooks not supported for PCI devices\n");
707                 return -1;
708                 /*
709                   v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
710                   pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
711                   pci_dev->bar[i].mem_write, pci_dev->vm_dev);
712                 */
713             } else {
714                 // set the prefetchable flag...
715                 pci_dev->bar[i].val |= 0x00000008;
716             }
717
718
719             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
720
721         } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
722             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
723             return -1;
724         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
725             pci_dev->bar[i].val = 0x00000000;
726             pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
727             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
728         } else {
729             PrintError("Invalid BAR type for bar #%d\n", i);
730             return -1;
731         }
732     }
733
734     return 0;
735 }
736
737
738 int v3_pci_set_irq_bridge(struct  vm_device * pci_bus, int bus_num, 
739                           int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev),
740                           int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev),
741                           struct vm_device * bridge_dev) {
742     struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
743
744
745     pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq;
746     pci_state->bus_list[bus_num].lower_pci_irq = lower_pci_irq;
747     pci_state->bus_list[bus_num].irq_bridge_dev = bridge_dev;
748
749     return 0;
750 }
751
752 int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
753    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
754    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
755
756    return bus->raise_pci_irq(bus->irq_bridge_dev, dev);
757 }
758
759 int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
760    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
761    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
762
763    return bus->lower_pci_irq(bus->irq_bridge_dev, dev);
764 }
765
766 // if dev_num == -1, auto assign 
767 struct pci_device * v3_pci_register_device(struct vm_device * pci,
768                                            pci_device_type_t dev_type, 
769                                            int bus_num,
770                                            int dev_num,
771                                            int fn_num,
772                                            const char * name,
773                                            struct v3_pci_bar * bars,
774                                            int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
775                                            int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
776                                            int (*ext_rom_update)(struct pci_device * pci_dev),
777                                            struct vm_device * dev) {
778
779     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
780     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
781     struct pci_device * pci_dev = NULL;
782     int i;
783
784     if (dev_num > MAX_BUS_DEVICES) {
785         PrintError("Requested Invalid device number (%d)\n", dev_num);
786         return NULL;
787     }
788
789     if (dev_num == PCI_AUTO_DEV_NUM) {
790         PrintDebug("Searching for free device number\n");
791         if ((dev_num = get_free_dev_num(bus)) == -1) {
792             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
793             return NULL;
794         }
795     }
796     
797     PrintDebug("Checking for PCI Device\n");
798
799     if (get_device(bus, dev_num, fn_num) != NULL) {
800         PrintError("PCI Device already registered at slot %d on bus %d\n", 
801                    dev_num, bus->bus_num);
802         return NULL;
803     }
804
805     
806     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
807
808     if (pci_dev == NULL) {
809         PrintError("Could not allocate pci device\n");
810         return NULL;
811     }
812
813     memset(pci_dev, 0, sizeof(struct pci_device));
814
815     
816     switch (dev_type) {
817         case PCI_STD_DEVICE:
818             pci_dev->config_header.header_type = 0x00;
819             break;
820         case PCI_MULTIFUNCTION:
821             pci_dev->config_header.header_type = 0x80;
822             break;
823         default:
824             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
825             return NULL;
826     }
827
828     pci_dev->bus_num = bus_num;
829     pci_dev->dev_num = dev_num;
830     pci_dev->fn_num = fn_num;
831
832     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
833     pci_dev->vm_dev = dev;
834
835     // register update callbacks
836     pci_dev->config_update = config_update;
837     pci_dev->cmd_update = cmd_update;
838     pci_dev->ext_rom_update = ext_rom_update;
839
840
841     //copy bars
842     for (i = 0; i < 6; i ++) {
843         pci_dev->bar[i].type = bars[i].type;
844         pci_dev->bar[i].private_data = bars[i].private_data;
845
846         if (pci_dev->bar[i].type == PCI_BAR_IO) {
847             pci_dev->bar[i].num_ports = bars[i].num_ports;
848
849             // This is a horrible HACK becaues the BIOS is supposed to set the PCI base ports 
850             // And if the BIOS doesn't, Linux just happily overlaps device port assignments
851             if (bars[i].default_base_port != (uint16_t)-1) {
852                 pci_dev->bar[i].default_base_port = bars[i].default_base_port;
853             } else {
854                 pci_dev->bar[i].default_base_port = pci_state->dev_io_base;
855                 pci_state->dev_io_base += ( 0x100 * ((bars[i].num_ports / 0x100) + 1) );
856             }
857
858             pci_dev->bar[i].io_read = bars[i].io_read;
859             pci_dev->bar[i].io_write = bars[i].io_write;
860         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
861             pci_dev->bar[i].num_pages = bars[i].num_pages;
862             pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
863             pci_dev->bar[i].mem_read = bars[i].mem_read;
864             pci_dev->bar[i].mem_write = bars[i].mem_write;
865         } else {
866             pci_dev->bar[i].num_pages = 0;
867             pci_dev->bar[i].default_base_addr = 0;
868             pci_dev->bar[i].mem_read = NULL;
869             pci_dev->bar[i].mem_write = NULL;
870         }
871     }
872
873     if (init_bars(pci_dev) == -1) {
874         PrintError("could not initialize bar registers\n");
875         return NULL;
876     }
877
878     // add the device
879     add_device_to_bus(bus, pci_dev);
880
881 #ifdef CONFIG_DEBUG_PCI
882     pci_dump_state(pci_state);
883 #endif
884
885     return pci_dev;
886 }