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.


Update to the 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         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_free(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
585 static struct v3_device_ops dev_ops = {
586     .free = pci_free,
587     .reset = pci_reset_device,
588     .start = pci_start_device,
589     .stop = pci_stop_device,
590 };
591
592
593
594
595 static int pci_init(struct guest_info * vm, void * cfg_data) {
596     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
597     int i = 0;
598     
599     PrintDebug("PCI internal at %p\n",(void *)pci_state);
600     
601     struct vm_device * dev = v3_allocate_device("PCI", &dev_ops, pci_state);
602     
603     if (v3_attach_device(vm, dev) == -1) {
604         PrintError("Could not attach device %s\n", "PCI");
605         return -1;
606     }
607
608     
609     pci_state->addr_reg.val = 0; 
610
611     init_pci_busses(pci_state);
612     
613     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
614     
615     for (i = 0; i < 4; i++) {
616         v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
617         v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
618     }
619
620     return 0;
621 }
622
623
624 device_register("PCI", pci_init)
625
626
627 static inline int init_bars(struct pci_device * pci_dev) {
628     int i = 0;
629
630     for (i = 0; i < 6; i++) {
631         int bar_offset = 0x10 + (4 * i);
632
633         if (pci_dev->bar[i].type == PCI_BAR_IO) {
634             int j = 0;
635             pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
636
637             pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
638             pci_dev->bar[i].val |= 0x00000001;
639
640             for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
641                 // hook IO
642                 if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
643                                    pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
644                     PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
645                     return -1;
646                 }
647             }
648
649             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
650
651         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
652             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
653             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
654
655             pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
656
657             // hook memory
658             if (pci_dev->bar[i].mem_read) {
659                 // full hook
660                 v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
661                                  pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
662                                  pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
663             } else if (pci_dev->bar[i].mem_write) {
664                 // write hook
665                 PrintError("Write hooks not supported for PCI devices\n");
666                 return -1;
667                 /*
668                   v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
669                   pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
670                   pci_dev->bar[i].mem_write, pci_dev->vm_dev);
671                 */
672             } else {
673                 // set the prefetchable flag...
674                 pci_dev->bar[i].val |= 0x00000008;
675             }
676
677
678             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
679
680         } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
681             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
682             return -1;
683         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
684             pci_dev->bar[i].val = 0x00000000;
685             pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
686             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
687         } else {
688             PrintError("Invalid BAR type for bar #%d\n", i);
689             return -1;
690         }
691     }
692
693     return 0;
694 }
695
696
697 // if dev_num == -1, auto assign 
698 struct pci_device * v3_pci_register_device(struct vm_device * pci,
699                                            pci_device_type_t dev_type, 
700                                            int bus_num,
701                                            int dev_num,
702                                            int fn_num,
703                                            const char * name,
704                                            struct v3_pci_bar * bars,
705                                            int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
706                                            int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
707                                            int (*ext_rom_update)(struct pci_device * pci_dev),
708                                            struct vm_device * dev) {
709
710     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
711     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
712     struct pci_device * pci_dev = NULL;
713     int i;
714
715     if (dev_num > MAX_BUS_DEVICES) {
716         PrintError("Requested Invalid device number (%d)\n", dev_num);
717         return NULL;
718     }
719
720     if (dev_num == -1) {
721         if ((dev_num = get_free_dev_num(bus)) == -1) {
722             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
723             return NULL;
724         }
725     }
726     
727     if (get_device(bus, dev_num, fn_num) != NULL) {
728         PrintError("PCI Device already registered at slot %d on bus %d\n", 
729                    dev_num, bus->bus_num);
730         return NULL;
731     }
732
733     
734     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
735
736     if (pci_dev == NULL) {
737         PrintError("Could not allocate pci device\n");
738         return NULL;
739     }
740
741     memset(pci_dev, 0, sizeof(struct pci_device));
742
743     
744     switch (dev_type) {
745         case PCI_STD_DEVICE:
746             pci_dev->config_header.header_type = 0x00;
747             break;
748         case PCI_MULTIFUNCTION:
749             pci_dev->config_header.header_type = 0x80;
750             break;
751         default:
752             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
753             return NULL;
754     }
755
756     pci_dev->bus_num = bus_num;
757     pci_dev->dev_num = dev_num;
758     pci_dev->fn_num = fn_num;
759
760     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
761     pci_dev->vm_dev = dev;
762
763     // register update callbacks
764     pci_dev->config_update = config_update;
765     pci_dev->cmd_update = cmd_update;
766     pci_dev->ext_rom_update = ext_rom_update;
767
768
769     //copy bars
770     for (i = 0; i < 6; i ++) {
771         pci_dev->bar[i].type = bars[i].type;
772
773         if (pci_dev->bar[i].type == PCI_BAR_IO) {
774             pci_dev->bar[i].num_ports = bars[i].num_ports;
775             pci_dev->bar[i].default_base_port = bars[i].default_base_port;
776             pci_dev->bar[i].io_read = bars[i].io_read;
777             pci_dev->bar[i].io_write = bars[i].io_write;
778         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
779             pci_dev->bar[i].num_pages = bars[i].num_pages;
780             pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
781             pci_dev->bar[i].mem_read = bars[i].mem_read;
782             pci_dev->bar[i].mem_write = bars[i].mem_write;
783         } else {
784             pci_dev->bar[i].num_pages = 0;
785             pci_dev->bar[i].default_base_addr = 0;
786             pci_dev->bar[i].mem_read = NULL;
787             pci_dev->bar[i].mem_write = NULL;
788         }
789     }
790
791     if (init_bars(pci_dev) == -1) {
792         PrintError("could not initialize bar registers\n");
793         return NULL;
794     }
795
796     // add the device
797     add_device_to_bus(bus, pci_dev);
798
799 #ifdef DEBUG_PCI
800     pci_dump_state(pci_state);
801 #endif
802
803     return pci_dev;
804 }
805
806
807