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