1 /* Northwestern University */
2 /* (c) 2008, Peter Dinda <pdinda@northwestern.edu> */
4 #include <geekos/malloc.h>
5 #include <geekos/pci.h>
7 #include <geekos/debug.h>
9 #define PCI_CONFIG_ADDRESS 0xcf8 // 32 bit, little endian
10 #define PCI_CONFIG_DATA 0xcfc // 32 bit, little endian
12 #define PCI_MAX_NUM_BUSES 4
15 struct pci_device_config {
21 uchar_t class_code[3]; // in order: programming interface, subclass, class code
23 #define PROG_INTERFACE(x) ((x)[0])
24 #define SUBCLASS(x) ((x)[1])
25 #define CLASSCODE(x) ((x)[2])
28 uchar_t cache_line_size;
30 uchar_t header_type; // bits 6-0: 00: other, 01: pci-pci bridge, 02: pci-cardbus; bit 7: 1=multifunction
32 #define HEADER_TYPE(x) ((x)&0x7f)
34 #define PCI_DEVICE 0x0
35 #define PCI_PCI_BRIDGE 0x1
36 #define PCI_CARDBUS_BRIDGE 0x2
38 #define MULTIFUNCTION(x) ((x)&0x80)
40 #define IS_DEVICE(x) (HEADER_TYPE(x)==0x0)
41 #define IS_PCI_PCI_BRIDGE(x) (HEADER_TYPE(x)==0x1)
42 #define IS_PCI_CARDBUS_BRIDGE(x) (HEADER_TYPE(x)==0x2)
48 // header = 00 (Device)
52 #define IS_IO_ADDR(x) ((x)&0x1)
53 #define IS_MEM_ADDR(x) (!((x)&0x1))
54 #define GET_IO_ADDR(x) (((uint_t)(x))&0xfffffffc)
55 #define GET_MEM_ADDR(x) (((uint_t)(x))&0xfffffff0)
56 #define GET_MEM_TYPE(x) (((x)&0x6)>>2)
57 #define GET_MEM_PREFETCHABLE(x) ((x)&0x8)
59 uint_t cardbus_cis_pointer;
60 ushort_t subsystem_vendor_id;
61 ushort_t subsystem_id;
62 uint_t expansion_rom_address;
63 uchar_t cap_ptr; // capabilities list offset in config space
65 uchar_t intr_line; // 00=none, 01=IRQ1, etc.
66 uchar_t intr_pin; // 00=none, otherwise INTA# to INTD#
67 uchar_t min_grant; // min busmaster time - units of 250ns
68 uchar_t max_latency; // units of 250ns - busmasters
69 uint_t device_data[48];
70 } __attribute__((__packed__)) pci_device_config;
72 // header = 01 (pci-pci bridge)
75 uchar_t primary_bus; // the one closer to the processor
76 uchar_t secondary_bus; // the one further away
77 uchar_t subordinate_bus;
78 uchar_t secondary_lat_timer;
81 ushort_t secondary_status;
83 ushort_t memory_limit;
84 ushort_t prefetchable_memory_base;
85 ushort_t prefetchable_memory_limit;
86 uint_t prefetchable_memory_base_upper; // for 64 bit?
87 uint_t prefetchable_memory_limit_upper;
88 ushort_t io_base_upper; // upper 16
89 ushort_t io_limit_upper;
91 uint_t expansion_rom_address;
95 uint_t device_data[48];
96 } __attribute__((__packed__)) pci_pci_bridge_config;
99 // header = 02 (pci-cardbus bridge)
101 uint_t cardbus_base_addr;
104 ushort_t secondary_status;
107 uchar_t subordinate_bus;
108 uchar_t cardbus_lat_timer;
110 uint_t memory_limit0;
112 uint_t memory_limit1;
114 ushort_t io_base0_upper;
116 ushort_t io_limit0_upper;
118 ushort_t io_base1_upper;
120 ushort_t io_limit1_upper;
124 ushort_t subsystem_vendor_id;
125 ushort_t subsystem_device_id;
126 uint_t legacy_16bit_base_addr;
127 uint_t reserved2[14];
128 uint_t device_data[32];
129 } __attribute__((__packed__)) pci_cardbus_bridge_config;
131 } __attribute__((__packed__)) u;
137 struct pci_bus *next;
139 struct pci_device *device_list; //
146 struct pci_device *next;
148 struct pci_device_config config;
153 struct pci_bus *bus_list;
157 static uint_t ReadPCIDWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
162 address = ((bus << 16) | (dev << 11) |
163 (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
165 Out_DWord(PCI_CONFIG_ADDRESS,address);
166 data=In_DWord(PCI_CONFIG_DATA);
173 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
178 address = ((bus << 16) | (dev << 11) |
179 (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
181 Out_DWord(PCI_CONFIG_ADDRESS,address);
182 data=In_DWord(PCI_CONFIG_DATA);
184 //PrintBoth("PCI: [0x%x] = 0x%x\n",address,data);
187 return (ushort_t) ((data>>((offset&0x2)*8)) & 0xffff);
192 static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
194 return (ushort_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x2)*8));
197 #if 0 // not currently used
198 static uchar_t ReadPCIByte(uint_t bus, uint_t dev, uint_t func, uint_t offset)
200 return (uchar_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x3)*8));
204 static struct pci *NewPCI()
206 struct pci *p = (struct pci *)Malloc(sizeof(struct pci));
212 static void AddPCIBus(struct pci *p, struct pci_bus *bus)
214 bus->next = p->bus_list;
219 static struct pci_bus *NewPCIBus(struct pci *p)
221 struct pci_bus *pb = (struct pci_bus *)Malloc(sizeof(struct pci_bus));
222 pb->device_list=NULL;
223 pb->number = (p->num_buses);
228 static void AddPCIDevice(struct pci_bus *b, struct pci_device *d)
231 d->next=b->device_list;
235 static struct pci_device *NewPCIDevice(struct pci_bus *pb)
237 struct pci_device *pd = (struct pci_device *)Malloc(sizeof(struct pci_device));
244 static void GetPCIDeviceConfig(uint_t bus,
246 struct pci_device *d)
248 uint_t numdwords=sizeof(struct pci_device_config) / 4;
251 uint_t *p = (uint_t *) (&(d->config));
253 for (i=0;i<numdwords;i++) {
254 p[i]=ReadPCIDWord(bus,dev,0,i*4);
260 static struct pci *ScanPCI()
265 struct pci *thepci = NewPCI();
266 struct pci_bus *thebus;
268 for (bus=0;bus<PCI_MAX_NUM_BUSES;bus++) {
269 // Are there any devices on the bus?
270 for (dev=0;dev<32;dev++) {
271 vendor=ReadPCIWord(bus,dev,0,0);
272 if (vendor!=0xffff) {
279 // There are devices. Create a bus.
280 thebus = NewPCIBus(thepci);
282 // Add the devices to the bus
283 for (dev=0;dev<32;dev++) {
284 vendor=ReadPCIWord(bus,dev,0,0);
285 if (vendor!=0xffff) {
286 struct pci_device *thedev=NewPCIDevice(thebus);
288 GetPCIDeviceConfig(bus,dev,thedev);
289 AddPCIDevice(thebus,thedev);
292 AddPCIBus(thepci,thebus);
297 static void PrintPCIShared(struct pci_device *thedev)
299 PrintBoth(" Slot: %u\n",thedev->number);
300 PrintBoth(" vendor_id: 0x%x\n", (uint_t) thedev->config.vendor_id);
301 PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id);
302 PrintBoth(" command: 0x%x\n", (uint_t) thedev->config.command);
303 PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status);
304 PrintBoth(" revision: 0x%x\n", (uint_t) thedev->config.revision);
305 PrintBoth(" class_code: 0x%x%x%x (prog_interface 0x%x, subclass 0x%x, classcode 0x%x)\n",
306 (uint_t) thedev->config.class_code[0],
307 (uint_t) thedev->config.class_code[1],
308 (uint_t) thedev->config.class_code[2],
309 (uint_t) PROG_INTERFACE(thedev->config.class_code),
310 (uint_t) SUBCLASS(thedev->config.class_code),
311 (uint_t) CLASSCODE(thedev->config.class_code)
313 PrintBoth(" cache_line_size: 0x%x\n", (uint_t) thedev->config.cache_line_size);
314 PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time);
315 PrintBoth(" header_type: 0x%x (%s%s)\n", (uint_t) thedev->config.header_type,
316 HEADER_TYPE(thedev->config.header_type)==PCI_DEVICE ? "PCI Device" :
317 HEADER_TYPE(thedev->config.header_type)==PCI_PCI_BRIDGE ? "PCI-PCI Bridge" :
318 HEADER_TYPE(thedev->config.header_type)==PCI_CARDBUS_BRIDGE ? "PCI-Cardbus Bridge" : "UNKNOWN",
319 MULTIFUNCTION(thedev->config.header_type) ? " Multifunction" : ""
321 PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST);
324 static void PrintPCIDevice(struct pci_device *thedev)
328 PrintBoth(" PCI Device:\n");
329 PrintPCIShared(thedev);
331 PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_device_config.BAR[i]);
332 if (IS_IO_ADDR(thedev->config.u.pci_device_config.BAR[i])) {
333 PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_device_config.BAR[i]));
334 } else if (IS_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i])) {
335 PrintBoth("Memory Address 0x%x type=0x%x%s\n",
336 GET_MEM_ADDR(thedev->config.u.pci_device_config.BAR[i]),
337 GET_MEM_TYPE(thedev->config.u.pci_device_config.BAR[i]),
338 GET_MEM_PREFETCHABLE(thedev->config.u.pci_device_config.BAR[i]) ? " prefetchable)" : ")");
340 PrintBoth("UNKNOWN)\n");
343 PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cardbus_cis_pointer);
344 PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_vendor_id);
345 PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.subsystem_id);
346 PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.expansion_rom_address);
347 PrintBoth(" cap ptr 0x%x\n", (uint_t) thedev->config.u.pci_device_config.cap_ptr);
349 PrintBoth(" reserved[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.reserved[i]);
351 PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_line);
352 PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.intr_pin);
353 PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.min_grant);
354 PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.u.pci_device_config.max_latency);
356 PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_device_config.device_data[i]);
360 static void PrintPCIPCIBridge(struct pci_device *thedev)
364 PrintBoth(" PCI-PCI Bridge:\n");
365 PrintPCIShared(thedev);
367 PrintBoth(" BAR[%d]: 0x%x (", i, (uint_t) thedev->config.u.pci_pci_bridge_config.BAR[i]);
368 if (IS_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) {
369 PrintBoth("IO Address 0x%x)\n", GET_IO_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]));
370 } else if (IS_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i])) {
371 PrintBoth("Memory Address 0x%x type=0x%x%s\n",
372 GET_MEM_ADDR(thedev->config.u.pci_pci_bridge_config.BAR[i]),
373 GET_MEM_TYPE(thedev->config.u.pci_pci_bridge_config.BAR[i]),
374 GET_MEM_PREFETCHABLE(thedev->config.u.pci_pci_bridge_config.BAR[i]) ? " prefetchable)" : ")");
376 PrintBoth("UNKNOWN)\n");
379 PrintBoth(" primary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.primary_bus);
380 PrintBoth(" secondary_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_bus);
381 PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.subordinate_bus);
382 PrintBoth(" second_lat_timer: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_lat_timer);
383 PrintBoth(" io_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base);
384 PrintBoth(" io_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit);
385 PrintBoth(" secondary_status: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.secondary_status);
386 PrintBoth(" memory_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_base);
387 PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
388 PrintBoth(" prefetch_base: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base);
389 PrintBoth(" prefetch_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit);
390 PrintBoth(" prefetch_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_base_upper);
391 PrintBoth(" prefetch_limit_u: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.prefetchable_memory_limit_upper);
392 PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
393 PrintBoth(" memory_limit: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.memory_limit);
394 PrintBoth(" io_base_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_base_upper);
395 PrintBoth(" io_limit_up: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.io_limit_upper);
396 PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.reserved);
397 PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.expansion_rom_address);
398 PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_line);
399 PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_pci_bridge_config.intr_pin);
401 PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_pci_bridge_config.device_data[i]);
405 static void PrintPCICardbusBridge(struct pci_device *thedev)
409 PrintBoth(" PCI-Cardbus Bridge:\n");
410 PrintPCIShared(thedev);
411 PrintBoth(" cardbus_base_add: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_base_addr);
412 PrintBoth(" cap_ptr: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cap_ptr);
413 PrintBoth(" reserved: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved);
414 PrintBoth(" secondary_status 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.secondary_status);
415 PrintBoth(" pci_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.pci_bus);
416 PrintBoth(" cardbus_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_bus);
417 PrintBoth(" subordinate_bus: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subordinate_bus);
418 PrintBoth(" cardbus_lat_time: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.cardbus_lat_timer);
419 PrintBoth(" memory_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base0);
420 PrintBoth(" memory_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit0);
421 PrintBoth(" memory_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_base1);
422 PrintBoth(" memory_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.memory_limit1);
423 PrintBoth(" io_base0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0);
424 PrintBoth(" io_base0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base0_upper);
425 PrintBoth(" io_limit0 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0);
426 PrintBoth(" io_limit0_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit0_upper);
427 PrintBoth(" io_base1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1);
428 PrintBoth(" io_base1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_base1_upper);
429 PrintBoth(" io_limit1 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1);
430 PrintBoth(" io_limit1_up 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.io_limit1_upper);
431 PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_line);
432 PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.intr_pin);
433 PrintBoth(" bridge_ctl: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.bridge_ctl);
434 PrintBoth(" subsys_vend_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_vendor_id);
435 PrintBoth(" subsys_dev_id: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.subsystem_device_id);
436 PrintBoth(" legacy16_base: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.legacy_16bit_base_addr);
438 PrintBoth(" reserved2[%d]: 0x%x\n", (uint_t) thedev->config.u.pci_cardbus_bridge_config.reserved2[i]);
441 PrintBoth(" device_data[%d]: 0x%x\n", i, (uint_t) thedev->config.u.pci_cardbus_bridge_config.device_data[i]);
445 static void PrintPCIUnknown(struct pci_device *thedev)
447 PrintBoth(" PCI Unknown Element\n");
448 PrintPCIShared(thedev);
451 static void PrintPCIElement(struct pci_device *thedev)
453 switch (HEADER_TYPE(thedev->config.header_type)) {
455 PrintPCIDevice(thedev);
458 PrintPCIPCIBridge(thedev);
460 case PCI_CARDBUS_BRIDGE:
461 PrintPCICardbusBridge(thedev);
464 PrintPCIUnknown(thedev);
470 static void PrintPCIBus(struct pci_bus *thebus)
472 struct pci_device *thedev;
474 PrintBoth(" PCI Bus:\n");
475 PrintBoth(" Number: %u\n",thebus->number);
477 thedev=thebus->device_list;
480 PrintPCIElement(thedev);
485 static void PrintPCI(struct pci *thepci)
487 struct pci_bus *thebus;
489 PrintBoth("PCI Configuration:\n");
490 PrintBoth(" Number of Buses: %u\n",thepci->num_buses);
491 thebus=thepci->bus_list;