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.


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