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.


Release 1.0
[palacios.git] / geekos / src / geekos / 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) 2008, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <geekos/malloc.h>
21 #include <geekos/pci.h>
22 #include <geekos/io.h>
23 #include <geekos/debug.h>
24
25 #define PCI_CONFIG_ADDRESS 0xcf8  // 32 bit, little endian
26 #define PCI_CONFIG_DATA    0xcfc  // 32 bit, little endian
27
28 #define PCI_MAX_NUM_BUSES  4
29
30
31 struct pci_device_config {
32   ushort_t   vendor_id;
33   ushort_t   device_id;
34   ushort_t   command;
35   ushort_t   status;
36   uchar_t    revision;
37   uchar_t    class_code[3];  // in order: programming interface, subclass, class code
38
39 #define PROG_INTERFACE(x) ((x)[0])
40 #define SUBCLASS(x) ((x)[1])
41 #define CLASSCODE(x) ((x)[2])
42   
43   
44   uchar_t    cache_line_size;
45   uchar_t    latency_time;
46   uchar_t    header_type; // bits 6-0: 00: other, 01: pci-pci bridge, 02: pci-cardbus; bit 7: 1=multifunction
47   
48 #define HEADER_TYPE(x) ((x)&0x7f)
49   
50 #define PCI_DEVICE 0x0
51 #define PCI_PCI_BRIDGE 0x1
52 #define PCI_CARDBUS_BRIDGE 0x2
53
54 #define MULTIFUNCTION(x) ((x)&0x80)
55
56 #define IS_DEVICE(x) (HEADER_TYPE(x)==0x0)
57 #define IS_PCI_PCI_BRIDGE(x) (HEADER_TYPE(x)==0x1)
58 #define IS_PCI_CARDBUS_BRIDGE(x) (HEADER_TYPE(x)==0x2)
59
60   uchar_t    BIST;
61   
62   union {  
63     
64     // header = 00 (Device)
65     struct {
66       uint_t     BAR[6];
67       
68 #define IS_IO_ADDR(x)   ((x)&0x1)
69 #define IS_MEM_ADDR(x)  (!((x)&0x1))
70 #define GET_IO_ADDR(x)  (((uint_t)(x))&0xfffffffc) 
71 #define GET_MEM_ADDR(x) (((uint_t)(x))&0xfffffff0)
72 #define GET_MEM_TYPE(x) (((x)&0x6)>>2)
73 #define GET_MEM_PREFETCHABLE(x) ((x)&0x8)
74
75       uint_t     cardbus_cis_pointer;
76       ushort_t   subsystem_vendor_id;
77       ushort_t   subsystem_id;
78       uint_t     expansion_rom_address;
79       uchar_t    cap_ptr;  // capabilities list offset in config space
80       uchar_t    reserved[7];
81       uchar_t    intr_line; // 00=none, 01=IRQ1, etc.
82       uchar_t    intr_pin;  // 00=none, otherwise INTA# to INTD#
83       uchar_t    min_grant; // min busmaster time - units of 250ns
84       uchar_t    max_latency; // units of 250ns - busmasters
85       uint_t     device_data[48];
86     }  __attribute__((__packed__))  pci_device_config;
87     
88     // header = 01 (pci-pci bridge)
89     struct {
90       uint_t     BAR[2];
91       uchar_t    primary_bus;  // the one closer to the processor
92       uchar_t    secondary_bus; // the one further away
93       uchar_t    subordinate_bus;
94       uchar_t    secondary_lat_timer;
95       uchar_t    io_base;
96       uchar_t    io_limit;
97       ushort_t   secondary_status;
98       ushort_t   memory_base;
99       ushort_t   memory_limit;
100       ushort_t   prefetchable_memory_base;
101       ushort_t   prefetchable_memory_limit;
102       uint_t     prefetchable_memory_base_upper;  // for 64 bit?
103       uint_t     prefetchable_memory_limit_upper;
104       ushort_t   io_base_upper;  // upper 16
105       ushort_t   io_limit_upper; 
106       uint_t     reserved;
107       uint_t     expansion_rom_address;
108       uchar_t    intr_line;
109       uchar_t    intr_pin;
110       ushort_t   bridge_ctl;
111       uint_t     device_data[48];
112     }  __attribute__((__packed__))  pci_pci_bridge_config;
113
114
115     // header = 02 (pci-cardbus bridge)
116     struct {
117       uint_t     cardbus_base_addr;
118       uchar_t    cap_ptr;
119       uchar_t    reserved;
120       ushort_t   secondary_status;
121       uchar_t    pci_bus;
122       uchar_t    cardbus_bus;
123       uchar_t    subordinate_bus;
124       uchar_t    cardbus_lat_timer;
125       uint_t     memory_base0;
126       uint_t     memory_limit0;
127       uint_t     memory_base1;
128       uint_t     memory_limit1;
129       ushort_t   io_base0;
130       ushort_t   io_base0_upper;
131       ushort_t   io_limit0;
132       ushort_t   io_limit0_upper;
133       ushort_t   io_base1;
134       ushort_t   io_base1_upper;
135       ushort_t   io_limit1;
136       ushort_t   io_limit1_upper;
137       uchar_t    intr_line;
138       uchar_t    intr_pin;
139       ushort_t   bridge_ctl;
140       ushort_t   subsystem_vendor_id;
141       ushort_t   subsystem_device_id;
142       uint_t     legacy_16bit_base_addr;
143       uint_t     reserved2[14];
144       uint_t     device_data[32];
145     }  __attribute__((__packed__)) pci_cardbus_bridge_config;
146
147   }  __attribute__((__packed__)) u;
148   
149 };
150
151 struct pci_bus {
152   uint_t number;
153   struct pci_bus *next;
154
155   struct pci_device *device_list; //
156
157 };
158
159 struct pci_device {
160   uint_t number;
161   struct pci_bus    *bus;
162   struct pci_device *next;
163   
164   struct pci_device_config config;
165 };
166
167 struct pci {
168   uint_t          num_buses;
169   struct pci_bus *bus_list;
170 };
171     
172
173 static uint_t ReadPCIDWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
174 {
175    uint_t address;
176    uint_t data;
177  
178    address = ((bus << 16) | (dev << 11) |
179               (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
180  
181    Out_DWord(PCI_CONFIG_ADDRESS,address);
182    data=In_DWord(PCI_CONFIG_DATA);
183
184    return data;
185 }
186
187 #if 0
188
189 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
190 {
191    uint_t address;
192    uint_t data;
193  
194    address = ((bus << 16) | (dev << 11) |
195              (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
196  
197    Out_DWord(PCI_CONFIG_ADDRESS,address);
198    data=In_DWord(PCI_CONFIG_DATA);
199
200    //PrintBoth("PCI: [0x%x] = 0x%x\n",address,data);
201
202
203    return (ushort_t) ((data>>((offset&0x2)*8)) & 0xffff);
204 }
205
206 #endif
207
208 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
209 {
210   return (ushort_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x2)*8));
211 }
212
213 #if 0  // not currently used
214 static uchar_t ReadPCIByte(uint_t bus, uint_t dev, uint_t func, uint_t offset)
215 {
216   return (uchar_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x3)*8));
217 }
218 #endif
219
220 static struct pci *NewPCI()
221 {
222   struct pci *p = (struct pci *)Malloc(sizeof(struct pci));
223   p->bus_list=NULL;
224   p->num_buses=0;
225   return p;
226 }
227
228 static void AddPCIBus(struct pci *p, struct pci_bus *bus) 
229 {
230   bus->next = p->bus_list;
231   p->bus_list=bus;
232 }
233     
234
235 static struct pci_bus *NewPCIBus(struct pci *p)
236 {
237   struct pci_bus *pb = (struct pci_bus *)Malloc(sizeof(struct pci_bus));
238   pb->device_list=NULL;
239   pb->number = (p->num_buses);
240   p->num_buses++;
241   return pb;
242 }
243
244 static void AddPCIDevice(struct pci_bus *b, struct pci_device *d)
245 {
246   d->bus=b;
247   d->next=b->device_list;
248   b->device_list=d;
249 }
250  
251 static struct pci_device *NewPCIDevice(struct pci_bus *pb) 
252 {
253   struct pci_device *pd = (struct pci_device *)Malloc(sizeof(struct pci_device));
254   pd->number=0;
255   pd->bus=NULL;
256   pd->next=NULL;
257   return pd;
258 }
259
260 static void GetPCIDeviceConfig(uint_t bus,
261                                uint_t dev,
262                                struct pci_device *d)
263 {
264   uint_t numdwords=sizeof(struct pci_device_config) / 4;
265   uint_t i;
266
267   uint_t *p = (uint_t *) (&(d->config));
268
269   for (i=0;i<numdwords;i++) {
270     p[i]=ReadPCIDWord(bus,dev,0,i*4);
271   }
272 }
273
274
275
276 static struct pci *ScanPCI()
277 {
278   uint_t bus, dev;
279   ushort_t vendor;
280
281   struct pci *thepci = NewPCI();
282   struct pci_bus *thebus;
283  
284   for (bus=0;bus<PCI_MAX_NUM_BUSES;bus++) {
285     // Are there any devices on the bus?
286     for (dev=0;dev<32;dev++) { 
287       vendor=ReadPCIWord(bus,dev,0,0);
288       if (vendor!=0xffff) { 
289         break;
290       }
291     }
292     if (dev==32) { 
293       continue;
294     }
295     // There are devices.  Create a bus.
296     thebus = NewPCIBus(thepci);
297     thebus->number=bus;
298     // Add the devices to the bus
299     for (dev=0;dev<32;dev++) { 
300       vendor=ReadPCIWord(bus,dev,0,0);
301       if (vendor!=0xffff) { 
302         struct pci_device *thedev=NewPCIDevice(thebus);
303         thedev->number=dev;
304         GetPCIDeviceConfig(bus,dev,thedev);
305         AddPCIDevice(thebus,thedev);
306       }
307     }
308     AddPCIBus(thepci,thebus);
309   }
310   return thepci;
311 }
312
313 static void PrintPCIShared(struct pci_device *thedev)
314 {
315   PrintBoth("     Slot: %u\n",thedev->number);
316   PrintBoth("      vendor_id:        0x%x\n", (uint_t) thedev->config.vendor_id);
317   PrintBoth("      device_id:        0x%x\n", (uint_t) thedev->config.device_id);
318   PrintBoth("      command:          0x%x\n", (uint_t) thedev->config.command);
319   PrintBoth("      status:           0x%x\n", (uint_t) thedev->config.status);
320   PrintBoth("      revision:         0x%x\n", (uint_t) thedev->config.revision);
321   PrintBoth("      class_code:       0x%x%x%x (prog_interface 0x%x, subclass 0x%x, classcode 0x%x)\n", 
322             (uint_t) thedev->config.class_code[0],
323             (uint_t) thedev->config.class_code[1],
324             (uint_t) thedev->config.class_code[2],
325             (uint_t) PROG_INTERFACE(thedev->config.class_code),
326             (uint_t) SUBCLASS(thedev->config.class_code),
327             (uint_t) CLASSCODE(thedev->config.class_code)
328             );
329   PrintBoth("      cache_line_size:  0x%x\n", (uint_t) thedev->config.cache_line_size);
330   PrintBoth("      latency_time:     0x%x\n", (uint_t) thedev->config.latency_time);
331   PrintBoth("      header_type:      0x%x (%s%s)\n", (uint_t) thedev->config.header_type,
332             HEADER_TYPE(thedev->config.header_type)==PCI_DEVICE ? "PCI Device" :
333             HEADER_TYPE(thedev->config.header_type)==PCI_PCI_BRIDGE ? "PCI-PCI Bridge" :
334             HEADER_TYPE(thedev->config.header_type)==PCI_CARDBUS_BRIDGE ? "PCI-Cardbus Bridge" : "UNKNOWN",
335             MULTIFUNCTION(thedev->config.header_type) ? " Multifunction" : ""
336             );
337   PrintBoth("      BIST:             0x%x\n", (uint_t) thedev->config.BIST);
338 }
339
340 static void PrintPCIDevice(struct pci_device *thedev)
341 {
342   int i;
343   
344   PrintBoth("     PCI Device:\n");
345   PrintPCIShared(thedev);
346   for (i=0;i<6;i++) { 
347     PrintBoth("      BAR[%d]:           0x%x (", i, (uint_t) thedev->config.u.pci_device_config.BAR[i]);
348     if (IS_IO_ADDR(thedev->config.u.pci_device_config.BAR[i])) { 
349       PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_device_config.BAR[i]));
350     } else if (IS_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i])) { 
351       PrintBoth("Memory Address 0x%x type=0x%x%s\n", 
352                 GET_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i]),
353                 GET_MEM_TYPE(thedev->config.u.pci_device_config.BAR[i]),
354                 GET_MEM_PREFETCHABLE(thedev->config.u.pci_device_config.BAR[i]) ? " prefetchable)" : ")");
355     } else {
356       PrintBoth("UNKNOWN)\n");
357     }
358   }
359   PrintBoth("      cardbus_cis_ptr:  0x%x\n", (uint_t) thedev->config.u.pci_device_config.cardbus_cis_pointer);
360   PrintBoth("      subsystem_vendor: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_vendor_id);
361   PrintBoth("      subsystem_id:     0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_id);
362   PrintBoth("      exp_rom_address:  0x%x\n", (uint_t) thedev->config.u.pci_device_config.expansion_rom_address);
363   PrintBoth("      cap ptr           0x%x\n", (uint_t) thedev->config.u.pci_device_config.cap_ptr);
364   for (i=0;i<7;i++) { 
365     PrintBoth("      reserved[%d]:      0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.reserved[i]);
366   }
367   PrintBoth("      intr_line:        0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_line);
368   PrintBoth("      intr_pin:         0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_pin);
369   PrintBoth("      min_grant:        0x%x\n", (uint_t) thedev->config.u.pci_device_config.min_grant);
370   PrintBoth("      max_latency:      0x%x\n", (uint_t) thedev->config.u.pci_device_config.max_latency);
371   for (i=0;i<48;i++) { 
372     PrintBoth("      device_data[%d]:   0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.device_data[i]);
373   }
374 }
375
376 static void PrintPCIPCIBridge(struct pci_device *thedev)
377 {
378   int i;
379   
380   PrintBoth("     PCI-PCI Bridge:\n");
381   PrintPCIShared(thedev);
382   for (i=0;i<2;i++) { 
383     PrintBoth("      BAR[%d]:           0x%x (", i, (uint_t) thedev->config.u.pci_pci_bridge_config.BAR[i]);
384     if (IS_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) { 
385       PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]));
386     } else if (IS_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) { 
387       PrintBoth("Memory Address 0x%x type=0x%x%s\n",
388                 GET_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]),
389         GET_MEM_TYPE(thedev->config.u.pci_pci_bridge_config.BAR[i]),
390                 GET_MEM_PREFETCHABLE(thedev->config.u.pci_pci_bridge_config.BAR[i]) ? " prefetchable)" : ")");
391     } else {
392       PrintBoth("UNKNOWN)\n");
393     }
394   }
395   PrintBoth("      primary_bus:      0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.primary_bus);
396   PrintBoth("      secondary_bus:    0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_bus);
397   PrintBoth("      subordinate_bus:  0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.subordinate_bus);
398   PrintBoth("      second_lat_timer: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_lat_timer);
399   PrintBoth("      io_base:          0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base);
400   PrintBoth("      io_limit:         0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit);
401   PrintBoth("      secondary_status: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_status);
402   PrintBoth("      memory_base:      0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_base);
403   PrintBoth("      memory_limit:     0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
404   PrintBoth("      prefetch_base:    0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base);
405   PrintBoth("      prefetch_limit:   0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit);
406   PrintBoth("      prefetch_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base_upper);
407   PrintBoth("      prefetch_limit_u: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit_upper);
408   PrintBoth("      memory_limit:     0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
409   PrintBoth("      memory_limit:     0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
410   PrintBoth("      io_base_up:       0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base_upper);
411   PrintBoth("      io_limit_up:      0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit_upper);
412   PrintBoth("      reserved:         0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.reserved);
413   PrintBoth("      exp_rom_address:  0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.expansion_rom_address);
414   PrintBoth("      intr_line:        0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_line);
415   PrintBoth("      intr_pin:         0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_pin);
416   for (i=0;i<48;i++) { 
417     PrintBoth("      device_data[%d]:   0x%x\n", i, (uint_t) thedev->config.u.pci_pci_bridge_config.device_data[i]);
418   }
419 }
420
421 static void PrintPCICardbusBridge(struct pci_device *thedev)
422 {
423   int i;
424   
425   PrintBoth("     PCI-Cardbus Bridge:\n");
426   PrintPCIShared(thedev);
427   PrintBoth("      cardbus_base_add: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_base_addr);
428   PrintBoth("      cap_ptr:          0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cap_ptr);
429   PrintBoth("      reserved:         0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved);
430   PrintBoth("      secondary_status  0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.secondary_status);
431   PrintBoth("      pci_bus:          0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.pci_bus);
432   PrintBoth("      cardbus_bus:      0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_bus);
433   PrintBoth("      subordinate_bus:  0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subordinate_bus);
434   PrintBoth("      cardbus_lat_time: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_lat_timer);
435   PrintBoth("      memory_base0      0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base0);
436   PrintBoth("      memory_limit0     0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit0);
437   PrintBoth("      memory_base1      0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base1);
438   PrintBoth("      memory_limit1     0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit1);
439   PrintBoth("      io_base0          0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0);
440   PrintBoth("      io_base0_up       0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0_upper);
441   PrintBoth("      io_limit0         0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0);
442   PrintBoth("      io_limit0_up      0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0_upper);
443   PrintBoth("      io_base1          0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1);
444   PrintBoth("      io_base1_up       0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1_upper);
445   PrintBoth("      io_limit1         0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1);
446   PrintBoth("      io_limit1_up      0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1_upper);
447   PrintBoth("      intr_line:        0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_line);
448   PrintBoth("      intr_pin:         0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_pin);
449   PrintBoth("      bridge_ctl:       0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.bridge_ctl);
450   PrintBoth("      subsys_vend_id:   0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_vendor_id);
451   PrintBoth("      subsys_dev_id:    0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_device_id);
452   PrintBoth("      legacy16_base:    0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.legacy_16bit_base_addr);
453   for (i=0;i<14;i++) {
454     PrintBoth("      reserved2[%d]:    0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved2[i]);
455   }
456   for (i=0;i<48;i++) { 
457     PrintBoth("      device_data[%d]:   0x%x\n", i, (uint_t) thedev->config.u.pci_cardbus_bridge_config.device_data[i]);
458   }
459 }
460
461 static void PrintPCIUnknown(struct pci_device *thedev)
462 {
463   PrintBoth("    PCI Unknown Element\n");
464   PrintPCIShared(thedev);
465 }
466
467 static void PrintPCIElement(struct pci_device *thedev) 
468
469   switch (HEADER_TYPE(thedev->config.header_type)) { 
470   case PCI_DEVICE:
471     PrintPCIDevice(thedev);
472     break;
473   case PCI_PCI_BRIDGE:
474     PrintPCIPCIBridge(thedev);
475     break;
476   case PCI_CARDBUS_BRIDGE:
477     PrintPCICardbusBridge(thedev);
478     break;
479   default:
480     PrintPCIUnknown(thedev);
481     break;
482   }
483 }
484     
485
486 static void PrintPCIBus(struct pci_bus *thebus)
487 {
488   struct pci_device *thedev;
489
490   PrintBoth("  PCI Bus:\n");
491   PrintBoth("   Number: %u\n",thebus->number);
492
493   thedev=thebus->device_list;
494
495   while (thedev) { 
496     PrintPCIElement(thedev);
497     thedev=thedev->next;
498   }
499 }
500
501 static void PrintPCI(struct pci *thepci)
502 {
503   struct pci_bus *thebus;
504
505   PrintBoth("PCI Configuration:\n");
506   PrintBoth(" Number of Buses: %u\n",thepci->num_buses);
507   thebus=thepci->bus_list;
508   while (thebus) { 
509     PrintPCIBus(thebus);
510     thebus=thebus->next;
511   }
512
513 }
514
515 int Init_PCI()
516 {
517   PrintPCI(ScanPCI());
518
519   return 0;
520
521 }