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.


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