Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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