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.


added symbiotic virtio device
[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 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 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     PrintError("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             PrintError("\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                 PrintError("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_dev_unhook_io(pci->vm_dev, PCI_IO_BASE(bar->val) + i);
410
411                 if (v3_dev_hook_io(pci->vm_dev, PCI_IO_BASE(new_val) + i, 
412                                    bar->io_read, bar->io_write) == -1) {
413
414                     PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
415                                PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
416                     return -1;
417                 }
418             }
419
420             bar->val = new_val;
421
422             break;
423         }
424         case PCI_BAR_MEM32: {
425             v3_unhook_mem(pci->vm_dev->vm, (addr_t)(bar->val));
426             
427             if (bar->mem_read) {
428                 v3_hook_full_mem(pci->vm_dev->vm, PCI_MEM32_BASE(new_val), 
429                                  PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB),
430                                  bar->mem_read, bar->mem_write, pci->vm_dev);
431             } else {
432                 PrintError("Write hooks not supported for PCI\n");
433                 return -1;
434             }
435
436             bar->val = new_val;
437
438             break;
439         }
440         case PCI_BAR_NONE: {
441             PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
442                        pci->name, bar_num, new_val);
443             break;
444         }
445         default:
446             PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num);
447             return -1;
448     }
449
450     return 0;
451 }
452
453
454 static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
455     struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
456     struct pci_device * pci_dev = NULL;
457     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
458     int i;
459
460
461     if (pci_state->addr_reg.bus_num != 0) {
462         return length;
463     }
464
465     PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
466                pci_state->addr_reg.bus_num, 
467                pci_state->addr_reg.dev_num, 
468                pci_state->addr_reg.fn_num,
469                reg_num, reg_num, 
470                pci_state->addr_reg.val,
471                *(uint32_t *)src, length);
472
473
474     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
475     
476     if (pci_dev == NULL) {
477         PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
478                    pci_state->addr_reg.dev_num); 
479         return -1;
480     }
481     
482
483     for (i = 0; i < length; i++) {
484         uint_t cur_reg = reg_num + i;
485         int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
486         
487         if (writable == -1) {
488             PrintError("Invalid PCI configuration space\n");
489             return -1;
490         }
491
492         if (writable) {
493             pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
494
495             if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
496                 // BAR Register Update
497                 int bar_reg = ((cur_reg & ~0x3) - 0x10) / 4;
498                 
499                 pci_dev->bar_update_flag = 1;
500                 pci_dev->bar[bar_reg].updated = 1;
501                 
502                 // PrintDebug("Updating BAR register %d\n", bar_reg);
503
504             } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
505                 // Extension ROM update
506
507                 pci_dev->ext_rom_update_flag = 1;
508             } else if (cur_reg == 0x04) {
509                 // COMMAND update            
510                 uint8_t command = *((uint8_t *)src + i);
511                 
512                 PrintError("command update for %s old=%x new=%x\n",
513                            pci_dev->name, 
514                            pci_dev->config_space[cur_reg],command);
515
516                 pci_dev->config_space[cur_reg] = command;             
517
518                 if (pci_dev->cmd_update) {
519                     pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
520                 }
521                 
522             } else if (cur_reg == 0x0f) {
523                 // BIST update
524                 pci_dev->config_header.BIST = 0x00;
525             }
526         } else {
527             PrintError("PCI Write to read only register %d\n", cur_reg);
528         }
529     }
530
531     if (pci_dev->config_update) {
532         pci_dev->config_update(pci_dev, reg_num, length);
533     }
534
535     // Scan for BAR updated
536     if (pci_dev->bar_update_flag) {
537         for (i = 0; i < 6; i++) {
538             if (pci_dev->bar[i].updated) {
539                 int bar_offset = 0x10 + 4 * i;
540
541                 *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
542                 // check special flags....
543
544                 // bar_update
545                 if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
546                     PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
547                     return -1;
548                 }
549
550                 pci_dev->bar[i].updated = 0;
551             }
552         }
553         pci_dev->bar_update_flag = 0;
554     }
555
556     if ((pci_dev->ext_rom_update_flag) && (pci_dev->ext_rom_update)) {
557         pci_dev->ext_rom_update(pci_dev);
558         pci_dev->ext_rom_update_flag = 0;
559     }
560
561
562     return length;
563 }
564
565
566
567 static int pci_reset_device(struct vm_device * dev) {
568     PrintDebug("pci: reset device\n");    
569     return 0;
570 }
571
572
573 static int pci_start_device(struct vm_device * dev) {
574     PrintDebug("pci: start device\n");
575     return 0;
576 }
577
578
579 static int pci_stop_device(struct vm_device * dev) {
580     PrintDebug("pci: stop device\n");  
581     return 0;
582 }
583
584
585
586 static int pci_free(struct vm_device * dev) {
587     int i = 0;
588     
589     for (i = 0; i < 4; i++){
590         v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i);
591         v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i);
592     }
593     
594     return 0;
595 }
596
597
598
599 static void init_pci_busses(struct pci_internal * pci_state) {
600     int i;
601
602     for (i = 0; i < PCI_BUS_COUNT; i++) {
603         pci_state->bus_list[i].bus_num = i;
604         pci_state->bus_list[i].devices.rb_node = NULL;
605         memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map));
606     }
607 }
608
609
610
611
612 static struct v3_device_ops dev_ops = {
613     .free = pci_free,
614     .reset = pci_reset_device,
615     .start = pci_start_device,
616     .stop = pci_stop_device,
617 };
618
619
620
621
622 static int pci_init(struct guest_info * vm, void * cfg_data) {
623     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
624     int i = 0;
625     
626     PrintDebug("PCI internal at %p\n",(void *)pci_state);
627     
628     struct vm_device * dev = v3_allocate_device("PCI", &dev_ops, pci_state);
629     
630     if (v3_attach_device(vm, dev) == -1) {
631         PrintError("Could not attach device %s\n", "PCI");
632         return -1;
633     }
634
635     
636     pci_state->addr_reg.val = 0; 
637     pci_state->dev_io_base = PCI_DEV_IO_PORT_BASE;
638
639     init_pci_busses(pci_state);
640     
641     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
642     
643     for (i = 0; i < 4; i++) {
644         v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
645         v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
646     }
647
648     return 0;
649 }
650
651
652 device_register("PCI", pci_init)
653
654
655 static inline int init_bars(struct pci_device * pci_dev) {
656     int i = 0;
657
658     for (i = 0; i < 6; i++) {
659         int bar_offset = 0x10 + (4 * i);
660
661         if (pci_dev->bar[i].type == PCI_BAR_IO) {
662             int j = 0;
663             pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
664
665             if (pci_dev->bar[i].default_base_port != 0xffff) {
666                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
667             } else {
668                 pci_dev->bar[i].val = 0;
669             }
670
671             pci_dev->bar[i].val |= 0x00000001;
672
673             for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
674                 // hook IO
675                 if (pci_dev->bar[i].default_base_port != 0xffff) {
676                     if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
677                                        pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
678                         PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
679                         return -1;
680                     }
681                 }
682             }
683
684             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
685
686         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
687             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
688             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
689
690             if (pci_dev->bar[i].default_base_addr != 0xffffffff) {
691                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
692             } else {
693                 pci_dev->bar[i].val = 0;
694             }
695
696             // hook memory
697             if (pci_dev->bar[i].mem_read) {
698                 // full hook
699                 v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
700                                  pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
701                                  pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
702             } else if (pci_dev->bar[i].mem_write) {
703                 // write hook
704                 PrintError("Write hooks not supported for PCI devices\n");
705                 return -1;
706                 /*
707                   v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
708                   pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
709                   pci_dev->bar[i].mem_write, pci_dev->vm_dev);
710                 */
711             } else {
712                 // set the prefetchable flag...
713                 pci_dev->bar[i].val |= 0x00000008;
714             }
715
716
717             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
718
719         } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
720             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
721             return -1;
722         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
723             pci_dev->bar[i].val = 0x00000000;
724             pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
725             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
726         } else {
727             PrintError("Invalid BAR type for bar #%d\n", i);
728             return -1;
729         }
730     }
731
732     return 0;
733 }
734
735
736 int v3_pci_set_irq_bridge(struct  vm_device * pci_bus, int bus_num, 
737                           int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev),
738                           int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev),
739                           struct vm_device * bridge_dev) {
740     struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
741
742
743     pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq;
744     pci_state->bus_list[bus_num].lower_pci_irq = lower_pci_irq;
745     pci_state->bus_list[bus_num].irq_bridge_dev = bridge_dev;
746
747     return 0;
748 }
749
750 int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
751    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
752    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
753
754    return bus->raise_pci_irq(bus->irq_bridge_dev, dev);
755 }
756
757 int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
758    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
759    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
760
761    return bus->lower_pci_irq(bus->irq_bridge_dev, dev);
762 }
763
764 // if dev_num == -1, auto assign 
765 struct pci_device * v3_pci_register_device(struct vm_device * pci,
766                                            pci_device_type_t dev_type, 
767                                            int bus_num,
768                                            int dev_num,
769                                            int fn_num,
770                                            const char * name,
771                                            struct v3_pci_bar * bars,
772                                            int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
773                                            int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
774                                            int (*ext_rom_update)(struct pci_device * pci_dev),
775                                            struct vm_device * dev) {
776
777     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
778     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
779     struct pci_device * pci_dev = NULL;
780     int i;
781
782     if (dev_num > MAX_BUS_DEVICES) {
783         PrintError("Requested Invalid device number (%d)\n", dev_num);
784         return NULL;
785     }
786
787     if (dev_num == PCI_AUTO_DEV_NUM) {
788         PrintDebug("Searching for free device number\n");
789         if ((dev_num = get_free_dev_num(bus)) == -1) {
790             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
791             return NULL;
792         }
793     }
794     
795     PrintDebug("Checking for PCI Device\n");
796
797     if (get_device(bus, dev_num, fn_num) != NULL) {
798         PrintError("PCI Device already registered at slot %d on bus %d\n", 
799                    dev_num, bus->bus_num);
800         return NULL;
801     }
802
803     
804     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
805
806     if (pci_dev == NULL) {
807         PrintError("Could not allocate pci device\n");
808         return NULL;
809     }
810
811     memset(pci_dev, 0, sizeof(struct pci_device));
812
813     
814     switch (dev_type) {
815         case PCI_STD_DEVICE:
816             pci_dev->config_header.header_type = 0x00;
817             break;
818         case PCI_MULTIFUNCTION:
819             pci_dev->config_header.header_type = 0x80;
820             break;
821         default:
822             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
823             return NULL;
824     }
825
826     pci_dev->bus_num = bus_num;
827     pci_dev->dev_num = dev_num;
828     pci_dev->fn_num = fn_num;
829
830     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
831     pci_dev->vm_dev = dev;
832
833     // register update callbacks
834     pci_dev->config_update = config_update;
835     pci_dev->cmd_update = cmd_update;
836     pci_dev->ext_rom_update = ext_rom_update;
837
838
839     //copy bars
840     for (i = 0; i < 6; i ++) {
841         pci_dev->bar[i].type = bars[i].type;
842
843         if (pci_dev->bar[i].type == PCI_BAR_IO) {
844             pci_dev->bar[i].num_ports = bars[i].num_ports;
845
846             // This is a horrible HACK becaues the BIOS is supposed to set the PCI base ports 
847             // And if the BIOS doesn't, Linux just happily overlaps device port assignments
848             if (bars[i].default_base_port != (uint16_t)-1) {
849                 pci_dev->bar[i].default_base_port = bars[i].default_base_port;
850             } else {
851                 pci_dev->bar[i].default_base_port = pci_state->dev_io_base;
852                 pci_state->dev_io_base += ( 0x100 * ((bars[i].num_ports / 0x100) + 1) );
853             }
854
855             pci_dev->bar[i].io_read = bars[i].io_read;
856             pci_dev->bar[i].io_write = bars[i].io_write;
857         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
858             pci_dev->bar[i].num_pages = bars[i].num_pages;
859             pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
860             pci_dev->bar[i].mem_read = bars[i].mem_read;
861             pci_dev->bar[i].mem_write = bars[i].mem_write;
862         } else {
863             pci_dev->bar[i].num_pages = 0;
864             pci_dev->bar[i].default_base_addr = 0;
865             pci_dev->bar[i].mem_read = NULL;
866             pci_dev->bar[i].mem_write = NULL;
867         }
868     }
869
870     if (init_bars(pci_dev) == -1) {
871         PrintError("could not initialize bar registers\n");
872         return NULL;
873     }
874
875     // add the device
876     add_device_to_bus(bus, pci_dev);
877
878 #ifdef DEBUG_PCI
879     pci_dump_state(pci_state);
880 #endif
881
882     return pci_dev;
883 }