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 virtual NE2000
[palacios-OLD.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_NONE: {
401             PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
402                        pci->name, bar_num, new_val);
403             break;
404         }
405         default:
406             PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num);
407             return -1;
408     }
409
410     return 0;
411 }
412
413
414 static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
415     struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
416     struct pci_device * pci_dev = NULL;
417     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
418     int i;
419
420
421     if (pci_state->addr_reg.bus_num != 0) {
422         return length;
423     }
424
425     PrintDebug("Writing PCI Data register. bus = %d, dev = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
426                pci_state->addr_reg.bus_num, 
427                pci_state->addr_reg.dev_num, 
428                reg_num, reg_num, 
429                pci_state->addr_reg.val,
430                *(uint32_t *)src, length);
431
432
433     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
434     
435     if (pci_dev == NULL) {
436         PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
437                    pci_state->addr_reg.dev_num); 
438         return -1;
439     }
440     
441
442     for (i = 0; i < length; i++) {
443         uint_t cur_reg = reg_num + i;
444         int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
445         
446         if (writable == -1) {
447             PrintError("Invalid PCI configuration space\n");
448             return -1;
449         }
450
451         if (writable) {
452             pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
453
454             if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
455                 // BAR Register Update
456                 int bar_reg = ((cur_reg & ~0x3) - 0x10) / 4;
457                 
458                 pci_dev->bar_update_flag = 1;
459                 pci_dev->bar[bar_reg].updated = 1;
460                 
461                 // PrintDebug("Updating BAR register %d\n", bar_reg);
462
463             } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
464                 // Extension ROM update
465
466                 pci_dev->ext_rom_update_flag = 1;
467             } else if (cur_reg == 0x04) {
468                 // COMMAND update            
469                 uint8_t command = *((uint8_t *)src + i);
470                 
471                 PrintError("command update for %s old=%x new=%x\n",
472                            pci_dev->name, 
473                            pci_dev->config_space[cur_reg],command);
474
475                 pci_dev->config_space[cur_reg] = command;             
476
477                 if (pci_dev->cmd_update) {
478                     pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
479                 }
480                 
481             } else if (cur_reg == 0x0f) {
482                 // BIST update
483                 pci_dev->config_header.BIST = 0x00;
484             }
485         }
486     }
487
488     if (pci_dev->config_update) {
489         pci_dev->config_update(pci_dev, reg_num, length);
490     }
491
492     // Scan for BAR updated
493     if (pci_dev->bar_update_flag) {
494         for (i = 0; i < 6; i++) {
495             if (pci_dev->bar[i].updated) {
496                 int bar_offset = 0x10 + 4 * i;
497
498                 *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
499                 // check special flags....
500
501                 // bar_update
502                 if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
503                     PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
504                     return -1;
505                 }
506
507                 pci_dev->bar[i].updated = 0;
508             }
509         }
510         pci_dev->bar_update_flag = 0;
511     }
512
513     if ((pci_dev->ext_rom_update_flag) && (pci_dev->ext_rom_update)) {
514         pci_dev->ext_rom_update(pci_dev);
515         pci_dev->ext_rom_update_flag = 0;
516     }
517
518
519     return length;
520 }
521
522
523
524 static int pci_reset_device(struct vm_device * dev) {
525     PrintDebug("pci: reset device\n");    
526     return 0;
527 }
528
529
530 static int pci_start_device(struct vm_device * dev) {
531     PrintDebug("pci: start device\n");
532     return 0;
533 }
534
535
536 static int pci_stop_device(struct vm_device * dev) {
537     PrintDebug("pci: stop device\n");  
538     return 0;
539 }
540
541
542
543 static int pci_deinit_device(struct vm_device * dev) {
544     int i = 0;
545     
546     for (i = 0; i < 4; i++){
547         v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i);
548         v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i);
549     }
550     
551     return 0;
552 }
553
554
555
556 static void init_pci_busses(struct pci_internal * pci_state) {
557     int i;
558
559     for (i = 0; i < PCI_BUS_COUNT; i++) {
560         pci_state->bus_list[i].bus_num = i;
561         pci_state->bus_list[i].devices.rb_node = NULL;
562         memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map));
563     }
564 }
565
566
567
568 static int pci_init_device(struct vm_device * dev) {
569     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;;
570     int i = 0;
571     
572     PrintDebug("pci: init_device\n");
573
574     // JRL: Fix this....
575     //    dev->vm->pci = dev;   //should be in vmm_config.c
576     
577     pci_state->addr_reg.val = 0; 
578
579     init_pci_busses(pci_state);
580     
581     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
582     
583     for (i = 0; i < 4; i++) {
584         v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
585         v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
586     }
587
588     return 0;
589 }
590
591
592 static struct vm_device_ops dev_ops = {
593     .init = pci_init_device, 
594     .deinit = pci_deinit_device,
595     .reset = pci_reset_device,
596     .start = pci_start_device,
597     .stop = pci_stop_device,
598 };
599
600
601 struct vm_device * v3_create_pci() {
602     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
603     
604     PrintDebug("PCI internal at %p\n",(void *)pci_state);
605     
606     struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);
607     
608     return device;
609 }
610
611
612
613 static inline int init_bars(struct pci_device * pci_dev) {
614     int i = 0;
615
616     for (i = 0; i < 6; i++) {
617         int bar_offset = 0x10 + (4 * i);
618
619         if (pci_dev->bar[i].type == PCI_BAR_IO) {
620             int j = 0;
621             pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
622
623             pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
624             pci_dev->bar[i].val |= 0x00000001;
625
626             for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
627                 // hook IO
628                 if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
629                                    pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
630                     PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
631                     return -1;
632                 }
633             }
634
635             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
636
637         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
638             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
639             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
640
641             pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
642
643             // hook memory
644             if (pci_dev->bar[i].mem_read) {
645                 // full hook
646                 v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
647                                  pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
648                                  pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
649             } else if (pci_dev->bar[i].mem_write) {
650                 // write hook
651                 PrintError("Write hooks not supported for PCI devices\n");
652                 return -1;
653                 /*
654                   v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
655                   pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
656                   pci_dev->bar[i].mem_write, pci_dev->vm_dev);
657                 */
658             } else {
659                 // set the prefetchable flag...
660                 pci_dev->bar[i].val |= 0x00000008;
661             }
662
663
664             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
665
666         } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
667             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
668             return -1;
669         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
670             pci_dev->bar[i].val = 0x00000000;
671             pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
672             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
673         } else {
674             PrintError("Invalid BAR type for bar #%d\n", i);
675             return -1;
676         }
677     }
678
679     return 0;
680 }
681
682
683 // if dev_num == -1, auto assign 
684 struct pci_device * v3_pci_register_device(struct vm_device * pci,
685                                            pci_device_type_t dev_type, 
686                                            int bus_num,
687                                            int dev_num,
688                                            int fn_num,
689                                            const char * name,
690                                            struct v3_pci_bar * bars,
691                                            int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
692                                            int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
693                                            int (*ext_rom_update)(struct pci_device * pci_dev),
694                                            struct vm_device * dev) {
695
696     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
697     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
698     struct pci_device * pci_dev = NULL;
699     int i;
700
701     if (dev_num > MAX_BUS_DEVICES) {
702         PrintError("Requested Invalid device number (%d)\n", dev_num);
703         return NULL;
704     }
705
706     if (dev_num == -1) {
707         if ((dev_num = get_free_dev_num(bus)) == -1) {
708             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
709             return NULL;
710         }
711     }
712     
713     if (get_device(bus, dev_num, fn_num) != NULL) {
714         PrintError("PCI Device already registered at slot %d on bus %d\n", 
715                    dev_num, bus->bus_num);
716         return NULL;
717     }
718
719     
720     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
721
722     if (pci_dev == NULL) {
723         PrintError("Could not allocate pci device\n");
724         return NULL;
725     }
726
727     memset(pci_dev, 0, sizeof(struct pci_device));
728
729     
730     switch (dev_type) {
731         case PCI_STD_DEVICE:
732             pci_dev->config_header.header_type = 0x00;
733             break;
734         case PCI_MULTIFUNCTION:
735             pci_dev->config_header.header_type = 0x80;
736             break;
737         default:
738             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
739             return NULL;
740     }
741
742     pci_dev->bus_num = bus_num;
743     pci_dev->dev_num = dev_num;
744     pci_dev->fn_num = fn_num;
745
746     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
747     pci_dev->vm_dev = dev;
748
749     // register update callbacks
750     pci_dev->config_update = config_update;
751     pci_dev->cmd_update = cmd_update;
752     pci_dev->ext_rom_update = ext_rom_update;
753
754
755     //copy bars
756     for (i = 0; i < 6; i ++) {
757         pci_dev->bar[i].type = bars[i].type;
758
759         if (pci_dev->bar[i].type == PCI_BAR_IO) {
760             pci_dev->bar[i].num_ports = bars[i].num_ports;
761             pci_dev->bar[i].default_base_port = bars[i].default_base_port;
762             pci_dev->bar[i].io_read = bars[i].io_read;
763             pci_dev->bar[i].io_write = bars[i].io_write;
764         } else {
765             pci_dev->bar[i].num_pages = bars[i].num_pages;
766             pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
767             pci_dev->bar[i].mem_read = bars[i].mem_read;
768             pci_dev->bar[i].mem_write = bars[i].mem_write;
769         }
770     }
771
772     if (init_bars(pci_dev) == -1) {
773         PrintError("could not initialize bar registers\n");
774         return NULL;
775     }
776
777     // add the device
778     add_device_to_bus(bus, pci_dev);
779
780 #ifdef DEBUG_PCI
781     pci_dump_state(pci_state);
782 #endif
783
784     return pci_dev;
785 }
786
787
788