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.


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