xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_info.cpp (revision 9eb55bc1d104b8fda80898f8b25c94d8000c8255)
1 /*
2 ** Copyright 2003, Marcus Overhagen. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS License.
4 */
5 
6 
7 #include <KernelExport.h>
8 #include <PCI.h>
9 #include <string.h>
10 #include "pci_info.h"
11 #include "pci.h"
12 
13 #define PCI_VERBOSE	1
14 #define USE_PCI_HEADER 1
15 
16 #if USE_PCI_HEADER
17 #	include "pcihdr.h"
18 #endif
19 
20 
21 void print_bridge_info(pci_info *info, bool verbose);
22 void print_generic_info(pci_info *info, bool verbose);
23 void print_info_basic(pci_info *info, bool verbose);
24 void get_vendor_info(uint16 vendorID, const char **venShort, const char **venFull);
25 void get_device_info(uint16 vendorID, uint16 deviceID, const char **devShort, const char **devFull);
26 const char *get_class_info(uint8 class_base, uint8 class_sub, uint8 class_api);
27 
28 
29 void
30 print_bridge_info(pci_info *info, bool verbose)
31 {
32 	dprintf("PCI:   primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, secondary_latency %02x\n",
33 			info->u.h1.primary_bus, info->u.h1.secondary_bus, info->u.h1.subordinate_bus, info->u.h1.secondary_latency);
34 	dprintf("PCI:   io_base %04x%02x, io_limit %04x%02x\n",
35 			info->u.h1.io_base_upper16, info->u.h1.io_base, info->u.h1.io_limit_upper16, info->u.h1.io_limit);
36 	dprintf("PCI:   memory_base %04x, memory_limit %04x\n",
37 			info->u.h1.memory_base, info->u.h1.memory_limit);
38 	dprintf("PCI:   prefetchable memory base %08lx%04x, limit %08lx%04x\n",
39 		info->u.h1.prefetchable_memory_base_upper32, info->u.h1.prefetchable_memory_base,
40 		info->u.h1.prefetchable_memory_limit_upper32, info->u.h1.prefetchable_memory_limit);
41 	dprintf("PCI:   bridge_control %04x, secondary_status %04x\n",
42 			info->u.h1.bridge_control, info->u.h1.secondary_status);
43 	dprintf("PCI:   interrupt_line %02x, interrupt_pin %02x\n",
44 			info->u.h1.interrupt_line, info->u.h1.interrupt_pin);
45 	dprintf("PCI:   ROM base host %08lx, pci %08lx, size ??\n",
46 			info->u.h1.rom_base, info->u.h1.rom_base_pci);
47 	for (int i = 0; i < 2; i++)
48 		dprintf("PCI:   base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n",
49 			i, info->u.h1.base_registers[i], info->u.h1.base_registers_pci[i],
50 			info->u.h1.base_register_sizes[i], info->u.h1.base_register_flags[i]);
51 }
52 
53 
54 void
55 print_generic_info(pci_info *info, bool verbose)
56 {
57 	dprintf("PCI:   ROM base host %08lx, pci %08lx, size %08lx\n",
58 			info->u.h0.rom_base, info->u.h0.rom_base_pci, info->u.h0.rom_size);
59 	dprintf("PCI:   cardbus_CIS %08lx, subsystem_id %04x, subsystem_vendor_id %04x\n",
60 			info->u.h0.cardbus_cis, info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id);
61 	dprintf("PCI:   interrupt_line %02x, interrupt_pin %02x, min_grant %02x, max_latency %02x\n",
62 			info->u.h0.interrupt_line, info->u.h0.interrupt_pin, info->u.h0.min_grant, info->u.h0.max_latency);
63 	for (int i = 0; i < 6; i++)
64 		dprintf("PCI:   base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n",
65 			i, info->u.h0.base_registers[i], info->u.h0.base_registers_pci[i],
66 			info->u.h0.base_register_sizes[i], info->u.h0.base_register_flags[i]);
67 }
68 
69 
70 void
71 print_info_basic(pci_info *info, bool verbose)
72 {
73 	dprintf("PCI: bus %2d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
74 			info->bus, info->device, info->function, info->vendor_id, info->device_id, info->revision);
75 	dprintf("PCI:   class_base %02x, class_function %02x, class_api %02x\n",
76 			info->class_base, info->class_sub, info->class_api);
77 
78 	if (verbose) {
79 #if USE_PCI_HEADER
80 		const char *venShort;
81 		const char *venFull;
82 		get_vendor_info(info->vendor_id, &venShort, &venFull);
83 		if (!venShort && !venFull) {
84 			dprintf("PCI:   vendor %04x: Unknown\n", info->vendor_id);
85 		} else if (venShort && venFull) {
86 			dprintf("PCI:   vendor %04x: %s - %s\n", info->vendor_id, venShort, venFull);
87 		} else {
88 			dprintf("PCI:   vendor %04x: %s\n", info->vendor_id, venShort ? venShort : venFull);
89 		}
90 		const char *devShort;
91 		const char *devFull;
92 		get_device_info(info->vendor_id, info->device_id, &devShort, &devFull);
93 		if (!devShort && !devFull) {
94 			dprintf("PCI:   device %04x: Unknown\n", info->device_id);
95 		} else if (devShort && devFull) {
96 			dprintf("PCI:   device %04x: %s - %s\n", info->device_id, devShort, devFull);
97 		} else {
98 			dprintf("PCI:   device %04x: %s\n", info->device_id, devShort ? devShort : devFull);
99 		}
100 #endif
101 		dprintf("PCI:   info: %s\n", get_class_info(info->class_base, info->class_sub, info->class_api));
102 	}
103 	dprintf("PCI:   line_size %02x, latency %02x, header_type %02x, BIST %02x\n",
104 			info->line_size, info->latency, info->header_type, info->bist);
105 
106 	switch (info->header_type) {
107 		case 0:
108 			print_generic_info(info, verbose);
109 			break;
110 		case 1:
111 			print_bridge_info(info, verbose);
112 			break;
113 		default:
114 			dprintf("PCI:   unknown header type\n");
115 	}
116 }
117 
118 
119 void
120 pci_print_info()
121 {
122 	pci_info info;
123 	for (long index = 0; B_OK == pci_get_nth_pci_info(index, &info); index++) {
124 		print_info_basic(&info, PCI_VERBOSE);
125 	}
126 }
127 
128 
129 const char *
130 get_class_info(uint8 class_base, uint8 class_sub, uint8 class_api)
131 {
132 	switch (class_base) {
133 		case PCI_early:
134 			switch (class_sub) {
135 				case PCI_early_not_vga:
136 					return "Not VGA-compatible pre-2.0 PCI specification device";
137 				case PCI_early_vga:
138 					return "VGA-compatible pre-2.0 PCI specification device";
139 				default:
140 					return "Unknown pre-2.0 PCI specification device";
141 			}
142 
143 		case PCI_mass_storage:
144 			switch (class_sub) {
145 				case PCI_scsi:
146 					return "SCSI mass storage controller";
147 				case PCI_ide:
148 					return "IDE mass storage controller";
149 				case PCI_floppy:
150 					return "Floppy disk controller";
151 				case PCI_ipi:
152 					return "IPI mass storage controller";
153 				case PCI_raid:
154 					return "RAID mass storage controller";
155 				case PCI_mass_storage_other:
156 					return "Other mass storage controller";
157 				default:
158 					return "Unknown mass storage controller";
159 			}
160 
161 		case PCI_network:
162 			switch (class_sub) {
163 				case PCI_ethernet:
164 					return "Ethernet network controller";
165 				case PCI_token_ring:
166 					return "Token ring network controller";
167 				case PCI_fddi:
168 					return "FDDI network controller";
169 				case PCI_atm:
170 					return "ATM network controller";
171 				case PCI_isdn:
172 					return "ISDN network controller";
173 				case PCI_network_other:
174 					return "Other network controller";
175 				default:
176 					return "Unknown network controller";
177 			}
178 
179 		case PCI_display:
180 			switch (class_sub) {
181 				case PCI_vga:
182 					switch (class_api) {
183 						case 0x00:
184 							return "VGA-compatible display controller";
185 						case 0x01:
186 							return "8514-compatible display controller";
187 						default:
188 							return "Unknown VGA display controller";
189 					}
190 				case PCI_xga:
191 					return "XGA display controller";
192 				case PCI_3d:
193 					return "3D display controller";
194 				case PCI_display_other:
195 					return "Other display controller";
196 				default:
197 					return "Unknown display controller";
198 			}
199 
200 		case PCI_multimedia:
201 			switch (class_sub) {
202 				case PCI_video:
203 					return "Video multimedia device";
204 				case PCI_audio:
205 					return "Audio multimedia device";
206 				case PCI_telephony:
207 					return "Computer telephony multimedia device";
208 				case PCI_multimedia_other:
209 					return "Other multimedia device";
210 				default:
211 					return "Unknown multimedia device";
212 			}
213 
214 		case PCI_memory:
215 			switch (class_sub) {
216 				case PCI_ram:
217 					return "RAM memory controller";
218 				case PCI_flash:
219 					return "Flash memory controller";
220 				case PCI_memory_other:
221 					return "Other memory controller";
222 				default:
223 					return "Unknown memory controller";
224 			}
225 
226 		case PCI_bridge:
227 			switch (class_sub) {
228 				case PCI_host:
229 					return "Host/PCI bridge device";
230 				case PCI_isa:
231 					return "PCI/ISA bridge device";
232 				case PCI_eisa:
233 					return "PCI/EISA bridge device";
234 				case PCI_microchannel:
235 					return "PCI/Micro Channel bridge device";
236 				case PCI_pci:
237 					switch (class_api) {
238 						case 0x00:
239 							return "PCI/PCI bridge device";
240 						case 0x01:
241 							return "Transparent PCI/PCI bridge device";
242 						default:
243 							return "Unknown PCI/PCI bridge device";
244 					}
245 				case PCI_pcmcia:
246 					return "PCI/PCMCIA bridge device";
247 				case PCI_nubus:
248 					return "PCI/NuBus bridge device";
249 				case PCI_cardbus:
250 					return "PCI/CardBus bridge device";
251 				case PCI_raceway:
252 					if (class_api & 1)
253 						return "PCI/RACEway bridge device, end-point mode";
254 					else
255 						return "PCI/RACEway bridge device, transparent mode";
256 				case PCI_bridge_other:
257 					return "Other bridge device";
258 				default:
259 					return "Unknown bridge device";
260 			}
261 
262 		case PCI_simple_communications:
263 			switch (class_sub) {
264 				case PCI_serial:
265 					switch (class_api) {
266 						case PCI_serial_xt:
267 							return "Generic XT-compatible serial communications controller";
268 						case PCI_serial_16450:
269 							return "16450-compatible serial communications controller";
270 						case PCI_serial_16550:
271 							return "16550-compatible serial communications controller";
272 						case 0x03:
273 							return "16650-compatible serial communications controller";
274 						case 0x04:
275 							return "16750-compatible serial communications controller";
276 						case 0x05:
277 							return "16850-compatible serial communications controller";
278 						case 0x06:
279 							return "16950-compatible serial communications controller";
280 						default:
281 							return "Unknown serial communications controller";
282 					}
283 				case PCI_parallel:
284 					switch (class_api) {
285 						case PCI_parallel_simple:
286 							return "Simple parallel port communications controller";
287 						case PCI_parallel_bidirectional:
288 							return "Bi-directional parallel port communications controller";
289 						case PCI_parallel_ecp:
290 							return "ECP 1.x compliant parallel port communications controller";
291 						case 0x03:
292 							return "IEEE 1284 parallel communications controller";
293 						case 0xfe:
294 							return "IEEE 1284 parallel communications target device";
295 						default:
296 							return "Unknown parallel communications controller";
297 					}
298 				case PCI_multiport_serial:
299 					return "Multiport serial communications controller";
300 				case PCI_modem:
301 					switch (class_api) {
302 						case 0x00:
303 							return "Generic modem";
304 						case 0x01:
305 							return "Hayes-compatible modem, 16450-compatible interface";
306 						case 0x02:
307 							return "Hayes-compatible modem, 16550-compatible interface";
308 						case 0x03:
309 							return "Hayes-compatible modem, 16650-compatible interface";
310 						case 0x04:
311 							return "Hayes-compatible modem, 16750-compatible interface";
312 						default:
313 							return "Unknown modem communications controller";
314 					}
315 				case PCI_simple_communications_other:
316 					return "Other simple communications controller";
317 				default:
318 					return "Unknown simple communications controller";
319 			}
320 
321 		case PCI_base_peripheral:
322 			switch (class_sub) {
323 				case PCI_pic:
324 					switch (class_api) {
325 						case PCI_pic_8259:
326 							return "Generic 8259 programmable interrupt controller (PIC)";
327 						case PCI_pic_isa:
328 							return "ISA programmable interrupt controller (PIC)";
329 						case PCI_pic_eisa:
330 							return "EISA programmable interrupt controller (PIC)";
331 						case 0x10:
332 							return "IO advanced programmable interrupt controller (APIC)";
333 						case 0x20:
334 							return "IO(x) advanced programmable interrupt controller (APIC)";
335 						default:
336 							return "Unknown programmable interrupt controller (PIC)";
337 					}
338 				case PCI_dma:
339 					switch (class_api) {
340 						case PCI_dma_8237:
341 							return "Generic 8237 DMA controller";
342 						case PCI_dma_isa:
343 							return "ISA DMA controller";
344 						case PCI_dma_eisa:
345 							return "EISA DMA controller";
346 						default:
347 							return "Unknown DMA controller";
348 					}
349 				case PCI_timer:
350 					switch (class_api) {
351 						case PCI_timer_8254:
352 							return "Generic 8254 timer";
353 						case PCI_timer_isa:
354 							return "ISA system timers";
355 						case PCI_timer_eisa:
356 							return "EISA system timers";
357 						default:
358 							return "Unknown timer";
359 					}
360 				case PCI_rtc:
361 					switch (class_api) {
362 						case PCI_rtc_generic:
363 							return "Generic real time clock (RTC) controller";
364 						case PCI_rtc_isa:
365 							return "ISA real time clock (RTC) controller";
366 						default:
367 							return "Unknown real time clock (RTC) controller";
368 					}
369 				case PCI_generic_hot_plug:
370 					return "Generic PCI Hot-Plug controller";
371 				case PCI_system_peripheral_other:
372 					return "Other base system peripheral";
373 				default:
374 					return "Unknown base system peripheral";
375 			}
376 
377 		case PCI_input:
378 			switch (class_sub) {
379 				case PCI_keyboard:
380 					return "Keyboard controller";
381 				case PCI_pen:
382 					return "Digitizer (pen) input device";
383 				case PCI_mouse:
384 					return "Mouse controller";
385 				case PCI_scanner:
386 					return "Scanner controller";
387 				case PCI_gameport:
388 					switch (class_api) {
389 						case 0x00:
390 							return "Generic gameport controller";
391 						case 0x10:
392 							return "Gameport controller";
393 						default:
394 							return "Unknown gameport controller";
395 					}
396 				case PCI_input_other:
397 					return "Other input controller";
398 				default:
399 					return "Unknown input controller";
400 			}
401 
402 		case PCI_docking_station:
403 			switch (class_sub) {
404 				case PCI_docking_generic:
405 					return "Generic docking station";
406 				case 0x80:
407 					return "Other type of docking station";
408 				default:
409 					return "Unknown docking station";
410 			}
411 
412 		case PCI_processor:
413 			switch (class_sub) {
414 				case PCI_386:
415 					return "386 processor";
416 				case PCI_486:
417 					return "486 processor";
418 				case PCI_pentium:
419 					return "Pentium processor";
420 				case PCI_alpha:
421 					return "Alpha processor";
422 				case PCI_PowerPC:
423 					return "PowerPC processor";
424 				case PCI_mips:
425 					return "MIPS processor";
426 				case PCI_coprocessor:
427 					return "Co-processor";
428 				default:
429 					return "Unknown processor";
430 			}
431 
432 		case PCI_serial_bus:
433 			switch (class_sub) {
434 				case PCI_firewire:
435 					switch (class_api) {
436 						case 0x00:
437 							return "Firewire (IEEE 1394) serial bus controller";
438 						case 0x10:
439 							return "Firewire (IEEE 1394) OpenHCI serial bus controller";
440 						default:
441 							return "Unknown Firewire (IEEE 1394) serial bus controller";
442 					}
443 				case PCI_access:
444 					return "ACCESS serial bus controller";
445 				case PCI_ssa:
446 					return "Serial Storage Architecture (SSA) controller";
447 				case PCI_usb:
448 					switch (class_api) {
449 						case PCI_usb_uhci:
450 							return "USB UHCI controller";
451 						case PCI_usb_ohci:
452 							return "USB OHCI controller";
453 						case 0x80:
454 							return "Other USB controller";
455 						case 0xfe:
456 							return "USB device";
457 						default:
458 							return "Unknown USB serial bus controller";
459 					}
460 				case PCI_fibre_channel:
461 					return "Fibre Channel serial bus controller";
462 				case 0x05:
463 					return "System Management Bus (SMBus) controller";
464 				default:
465 					return "Unknown serial bus controller";
466 			}
467 
468 		case PCI_wireless:
469 			switch (class_sub) {
470 				case 0x00:
471 					return "iRDA compatible wireless controller";
472 				case 0x01:
473 					return "Consumer IR wireless controller";
474 				case 0x10:
475 					return "RF wireless controller";
476 				case 0x80:
477 					return "Other wireless controller";
478 				default:
479 					return "Unknown wireless controller";
480 			}
481 
482 		case PCI_intelligent_io:
483 			switch (class_sub) {
484 				case 0x00:
485 					return "Intelligent IO controller";
486 				default:
487 					return "Unknown intelligent IO controller";
488 			}
489 
490 		case PCI_satellite_communications:
491 			switch (class_sub) {
492 				case 0x01:
493 					return "TV satellite communications controller";
494 				case 0x02:
495 					return "Audio satellite communications controller";
496 				case 0x03:
497 					return "Voice satellite communications controller";
498 				case 0x04:
499 					return "Data satellite communications controller";
500 				default:
501 					return "Unknown satellite communications controller";
502 			}
503 
504 		case PCI_encryption_decryption:
505 			switch (class_sub) {
506 				case 0x00:
507 					return "Network and computing encryption/decryption controller";
508 				case 0x10:
509 					return "Entertainment encryption/decryption controller";
510 				case 0x80:
511 					return "Other encryption/decryption controller";
512 				default:
513 					return "Unknown encryption/decryption controller";
514 			}
515 
516 		case PCI_data_acquisition:
517 			switch (class_sub) {
518 				case 0x00:
519 					return "DPIO modules (data acquisition and signal processing controller)";
520 				case 0x80:
521 					return " Other data acquisition and signal processing controller";
522 				default:
523 					return "Unknown data acquisition and signal processing controller";
524 			}
525 
526 		case PCI_undefined:
527 			return "Does not fit any defined class";
528 
529 		default:
530 			return "Unknown device class base";
531 	}
532 }
533 
534 
535 #if USE_PCI_HEADER
536 void
537 get_vendor_info(uint16 vendorID, const char **venShort, const char **venFull)
538 {
539 	for (int i = 0; i < (int)PCI_VENTABLE_LEN; i++) {
540 		if (PciVenTable[i].VenId == vendorID) {
541 			if (0 == strcmp(PciVenTable[i].VenShort, PciVenTable[i].VenFull)) {
542 				*venShort = PciVenTable[i].VenShort[0] ? PciVenTable[i].VenShort : NULL;
543 				*venFull = NULL;
544 			} else {
545 				*venShort = PciVenTable[i].VenShort[0] ? PciVenTable[i].VenShort : NULL;
546 				*venFull = PciVenTable[i].VenFull[0] ? PciVenTable[i].VenFull : NULL;
547 			}
548 			return;
549 		}
550 	}
551 	*venShort = NULL;
552 	*venFull = NULL;
553 }
554 
555 
556 void
557 get_device_info(uint16 vendorID, uint16 deviceID, const char **devShort, const char **devFull)
558 {
559 	for (int i = 0; i < (int)PCI_DEVTABLE_LEN; i++) {
560 		if (PciDevTable[i].VenId == vendorID && PciDevTable[i].DevId == deviceID ) {
561 			*devShort = PciDevTable[i].Chip[0] ? PciDevTable[i].Chip : NULL;
562 			*devFull = PciDevTable[i].ChipDesc[0] ? PciDevTable[i].ChipDesc : NULL;
563 			return;
564 		}
565 	}
566 	*devShort = NULL;
567 	*devFull = NULL;
568 }
569 #endif	/* USE_PCI_HEADER */
570