xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
1 /*
2  * Copyright 2006, Marcus Overhagen. All rights reserved.
3  * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4  * Copyright 2003, Marcus Overhagen. All rights reserved.
5  *
6  * Distributed under the terms of the MIT License.
7  */
8 
9 
10 #include <KernelExport.h>
11 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1
12 #include <PCI.h>
13 
14 #include "util/kernel_cpp.h"
15 #include "pci_priv.h"
16 #include "pci.h"
17 
18 static PCI *sPCI;
19 
20 // #pragma mark bus manager exports
21 
22 
23 status_t
24 pci_controller_add(pci_controller *controller, void *cookie)
25 {
26 	return sPCI->AddController(controller, cookie);
27 }
28 
29 
30 long
31 pci_get_nth_pci_info(long index, pci_info *outInfo)
32 {
33 	return sPCI->GetNthPciInfo(index, outInfo);
34 }
35 
36 
37 uint32
38 pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size)
39 {
40 	uint8 bus;
41 	int domain;
42 	uint32 value;
43 
44 	if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK)
45 		return 0xffffffff;
46 
47 	if (sPCI->ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK)
48 		return 0xffffffff;
49 
50 	return value;
51 }
52 
53 
54 void
55 pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
56 {
57 	uint8 bus;
58 	int domain;
59 
60 	if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK)
61 		return;
62 
63 	sPCI->WritePciConfig(domain, bus, device, function, offset, size, value);
64 }
65 
66 
67 status_t
68 pci_find_capability(uchar bus, uchar device, uchar function, uchar cap_id, uchar *offset)
69 {
70 	uint16 status;
71 	uint8 header_type;
72 	uint8 cap_ptr;
73 	int i;
74 
75 	if (!offset) {
76 		dprintf("find_pci_capability: ERROR %02x:%02x:%02x cap %02x offset NULL pointer\n", bus, device, function, cap_id);
77 		return B_BAD_VALUE;
78 	}
79 
80 	status = pci_read_config(bus, device, function, PCI_status, 2);
81 	if (!(status & PCI_status_capabilities)) {
82 		dprintf("find_pci_capability: ERROR %02x:%02x:%02x cap %02x not supported\n", bus, device, function, cap_id);
83 		return B_ERROR;
84 	}
85 
86 	header_type = pci_read_config(bus, device, function, PCI_header_type, 1);
87 	switch (header_type & PCI_header_type_mask) {
88 		case PCI_header_type_generic:
89 		case PCI_header_type_PCI_to_PCI_bridge:
90 			cap_ptr = pci_read_config(bus, device, function, PCI_capabilities_ptr, 1);
91 			break;
92 		case PCI_header_type_cardbus:
93 			cap_ptr = pci_read_config(bus, device, function, PCI_capabilities_ptr_2, 1);
94 			break;
95 		default:
96 			dprintf("find_pci_capability: ERROR %02x:%02x:%02x cap %02x unknown header type\n", bus, device, function, cap_id);
97 			return B_ERROR;
98 	}
99 
100 	cap_ptr &= ~3;
101 	if (!cap_ptr) {
102 		dprintf("find_pci_capability: ERROR %02x:%02x:%02x cap %02x empty list\n", bus, device, function, cap_id);
103 		return B_NAME_NOT_FOUND;
104 	}
105 
106 	for (i = 0; i < 48; i++) {
107 		uint8 this_cap_id = pci_read_config(bus, device, function, cap_ptr, 1);
108 		if (this_cap_id == cap_id) {
109 			*offset = cap_ptr;
110 			return B_OK;
111 		}
112 
113 		cap_ptr = pci_read_config(bus, device, function, cap_ptr + 1, 1);
114 		cap_ptr &= ~3;
115 
116 		if (!cap_ptr)
117 			return B_NAME_NOT_FOUND;
118 	}
119 
120 	dprintf("find_pci_capability: ERROR %02x:%02x:%02x cap %02x circular list\n", bus, device, function, cap_id);
121 	return B_ERROR;
122 }
123 
124 
125 // #pragma mark bus manager init/uninit
126 
127 status_t
128 pci_init(void)
129 {
130 	sPCI = new PCI;
131 
132 	if (pci_io_init() != B_OK) {
133 		TRACE(("PCI: pci_io_init failed\n"));
134 		return B_ERROR;
135 	}
136 
137 	if (pci_controller_init() != B_OK) {
138 		TRACE(("PCI: pci_controller_init failed\n"));
139 		return B_ERROR;
140 	}
141 
142 	sPCI->InitDomainData();
143 	sPCI->InitBus();
144 
145 	return B_OK;
146 }
147 
148 
149 void
150 pci_uninit(void)
151 {
152 	delete sPCI;
153 }
154 
155 
156 // #pragma mark PCI class
157 
158 PCI::PCI()
159  :	fRootBus(0)
160  ,	fDomainCount(0)
161 {
162 }
163 
164 
165 void
166 PCI::InitBus()
167 {
168 	PCIBus **ppnext = &fRootBus;
169 	for (int i = 0; i < fDomainCount; i++) {
170 		PCIBus *bus = new PCIBus;
171 		bus->next = NULL;
172 		bus->parent = NULL;
173 		bus->child = NULL;
174 		bus->domain = i;
175 		bus->bus = 0;
176 		*ppnext = bus;
177 		ppnext = &bus->next;
178 	}
179 
180 	bool bus_enumeration = true;
181 
182 	if (bus_enumeration) {
183 		for (int i = 0; i < fDomainCount; i++) {
184 			EnumerateBus(i, 0);
185 		}
186 	}
187 
188 	if (fRootBus) {
189 		DiscoverBus(fRootBus);
190 		RefreshDeviceInfo(fRootBus);
191 	}
192 }
193 
194 
195 PCI::~PCI()
196 {
197 }
198 
199 
200 status_t
201 PCI::AddVirtBus(int domain, uint8 bus, uint8 *virt_bus)
202 {
203 	if (MAX_PCI_DOMAINS != 8)
204 		panic("PCI::AddVirtBus only 8 controllers supported");
205 
206 	if (domain > 7)
207 		panic("PCI::AddVirtBus domain %d too large", domain);
208 
209 	if (bus > 31)
210 		panic("PCI::AddVirtBus bus %d too large", bus);
211 
212 	*virt_bus = (domain << 5) | bus;
213 	return B_OK;
214 }
215 
216 
217 status_t
218 PCI::GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus)
219 {
220 	// XXX if you modify this, also change pci_info.cpp print_info_basic() !!
221 	*domain = virt_bus >> 5;
222 	*bus = virt_bus & 0x1f;
223 	return B_OK;
224 }
225 
226 status_t
227 PCI::AddController(pci_controller *controller, void *controller_cookie)
228 {
229 	if (fDomainCount == MAX_PCI_DOMAINS)
230 		return B_ERROR;
231 
232 	fDomainData[fDomainCount].controller = controller;
233 	fDomainData[fDomainCount].controller_cookie = controller_cookie;
234 
235 	// initialized later to avoid call back into controller at this point
236 	fDomainData[fDomainCount].max_bus_devices = -1;
237 
238 	fDomainCount++;
239 	return B_OK;
240 }
241 
242 void
243 PCI::InitDomainData()
244 {
245 	for (int i = 0; i < fDomainCount; i++) {
246 		int32 count;
247 		status_t status;
248 
249 		status = (*fDomainData[i].controller->get_max_bus_devices)(fDomainData[i].controller_cookie, &count);
250 		fDomainData[i].max_bus_devices = (status == B_OK) ? count : 0;
251 	}
252 }
253 
254 
255 domain_data *
256 PCI::GetDomainData(int domain)
257 {
258 	if (domain < 0 || domain >= fDomainCount)
259 		return NULL;
260 
261 	return &fDomainData[domain];
262 }
263 
264 
265 status_t
266 PCI::GetNthPciInfo(long index, pci_info *outInfo)
267 {
268 	long curindex = 0;
269 	if (!fRootBus)
270 		return B_ERROR;
271 	return GetNthPciInfo(fRootBus, &curindex, index, outInfo);
272 }
273 
274 
275 status_t
276 PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo)
277 {
278 	// maps tree structure to linear indexed view
279 	PCIDev *dev = bus->child;
280 	while (dev) {
281 		if (*curindex == wantindex) {
282 			*outInfo = dev->info;
283 			return B_OK;
284 		}
285 		*curindex += 1;
286 		if (dev->child && B_OK == GetNthPciInfo(dev->child, curindex, wantindex, outInfo))
287 			return B_OK;
288 		dev = dev->next;
289 	}
290 
291 	if (bus->next)
292 		return GetNthPciInfo(bus->next, curindex, wantindex, outInfo);
293 
294 	return B_ERROR;
295 }
296 
297 void
298 PCI::EnumerateBus(int domain, uint8 bus, uint8 *subordinate_bus)
299 {
300 	TRACE(("PCI: EnumerateBus: domain %u, bus %u\n", domain, bus));
301 
302 	int max_bus_devices = GetDomainData(domain)->max_bus_devices;
303 
304 	// step 1: disable all bridges on this bus
305 	for (int dev = 0; dev < max_bus_devices; dev++) {
306 		uint16 vendor_id = ReadPciConfig(domain, bus, dev, 0, PCI_vendor_id, 2);
307 		if (vendor_id == 0xffff)
308 			continue;
309 
310 		uint8 type = ReadPciConfig(domain, bus, dev, 0, PCI_header_type, 1);
311 		int nfunc = (type & PCI_multifunction) ? 8 : 1;
312 		for (int func = 0; func < nfunc; func++) {
313 			uint16 device_id = ReadPciConfig(domain, bus, dev, func, PCI_device_id, 2);
314 			if (device_id == 0xffff)
315 				continue;
316 
317 			uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1);
318 			uint8 sub_class	 = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1);
319 			if (base_class != PCI_bridge || sub_class != PCI_pci)
320 				continue;
321 
322 			TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", domain, bus, dev, func));
323 			TRACE(("PCI: original settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n",
324 				ReadPciConfig(domain, bus, dev, func, PCI_command, 2),
325 				ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1),
326 				ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1),
327 				ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1)));
328 
329 			// disable decoding
330 			uint16 pcicmd;
331 			pcicmd = ReadPciConfig(domain, bus, dev, func, PCI_command, 2);
332 			pcicmd &= ~(PCI_command_io | PCI_command_memory | PCI_command_master);
333 			WritePciConfig(domain, bus, dev, func, PCI_command, 2, pcicmd);
334 
335 			// disable busses
336 			WritePciConfig(domain, bus, dev, func, PCI_primary_bus, 1, 0);
337 			WritePciConfig(domain, bus, dev, func, PCI_secondary_bus, 1, 0);
338 			WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, 0);
339 
340 			TRACE(("PCI: disabled settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n",
341 				ReadPciConfig(domain, bus, dev, func, PCI_command, 2),
342 				ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1),
343 				ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1),
344 				ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1)));
345 		}
346 	}
347 
348 	uint8 last_used_bus_number = bus;
349 
350 	// step 2: assign busses to all bridges, and enable them again
351 	for (int dev = 0; dev < max_bus_devices; dev++) {
352 		uint16 vendor_id = ReadPciConfig(domain, bus, dev, 0, PCI_vendor_id, 2);
353 		if (vendor_id == 0xffff)
354 			continue;
355 
356 		uint8 type = ReadPciConfig(domain, bus, dev, 0, PCI_header_type, 1);
357 		int nfunc = (type & PCI_multifunction) ? 8 : 1;
358 		for (int func = 0; func < nfunc; func++) {
359 			uint16 device_id = ReadPciConfig(domain, bus, dev, func, PCI_device_id, 2);
360 			if (device_id == 0xffff)
361 				continue;
362 
363 			uint8 base_class = ReadPciConfig(domain, bus, dev, func, PCI_class_base, 1);
364 			uint8 sub_class	 = ReadPciConfig(domain, bus, dev, func, PCI_class_sub, 1);
365 			if (base_class != PCI_bridge || sub_class != PCI_pci)
366 				continue;
367 
368 			TRACE(("PCI: configuring PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n",
369 				domain, bus, dev, func));
370 
371 			// open Scheunentor for enumerating the bus behind the bridge
372 			WritePciConfig(domain, bus, dev, func, PCI_primary_bus, 1, bus);
373 			WritePciConfig(domain, bus, dev, func, PCI_secondary_bus, 1, last_used_bus_number + 1);
374 			WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, 255);
375 
376 			// enable decoding (too early here?)
377 			uint16 pcicmd;
378 			pcicmd = ReadPciConfig(domain, bus, dev, func, PCI_command, 2);
379 			pcicmd |= PCI_command_io | PCI_command_memory | PCI_command_master;
380 			WritePciConfig(domain, bus, dev, func, PCI_command, 2, pcicmd);
381 
382 			TRACE(("PCI: probing settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n",
383 				ReadPciConfig(domain, bus, dev, func, PCI_command, 2),
384 				ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1),
385 				ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1),
386 				ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1)));
387 
388 			// enumerate bus
389 			EnumerateBus(domain, last_used_bus_number + 1, &last_used_bus_number);
390 
391 			// close Scheunentor
392 			WritePciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1, last_used_bus_number);
393 
394 			TRACE(("PCI: configured settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n",
395 				ReadPciConfig(domain, bus, dev, func, PCI_command, 2),
396 				ReadPciConfig(domain, bus, dev, func, PCI_primary_bus, 1),
397 				ReadPciConfig(domain, bus, dev, func, PCI_secondary_bus, 1),
398 				ReadPciConfig(domain, bus, dev, func, PCI_subordinate_bus, 1)));
399 			}
400 	}
401 	if (subordinate_bus)
402 		*subordinate_bus = last_used_bus_number;
403 
404 	TRACE(("PCI: EnumerateBus done: domain %u, bus %u, last used bus number %u\n", domain, bus, last_used_bus_number));
405 }
406 
407 
408 
409 void
410 PCI::DiscoverBus(PCIBus *bus)
411 {
412 	TRACE(("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus));
413 
414 	int max_bus_devices = GetDomainData(bus->domain)->max_bus_devices;
415 
416 	for (int dev = 0; dev < max_bus_devices; dev++) {
417 		uint16 vendor_id = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_vendor_id, 2);
418 		if (vendor_id == 0xffff)
419 			continue;
420 
421 		uint8 type = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_header_type, 1);
422 		int nfunc = (type & PCI_multifunction) ? 8 : 1;
423 		for (int func = 0; func < nfunc; func++)
424 			DiscoverDevice(bus, dev, func);
425 	}
426 
427 	if (bus->next)
428 		DiscoverBus(bus->next);
429 }
430 
431 
432 void
433 PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func)
434 {
435 	TRACE(("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus->domain, bus->bus, dev, func));
436 
437 	uint16 device_id = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_device_id, 2);
438 	if (device_id == 0xffff)
439 		return;
440 
441 	PCIDev *newdev = CreateDevice(bus, dev, func);
442 
443 	uint8 base_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_base, 1);
444 	uint8 sub_class	 = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_sub, 1);
445 	if (base_class == PCI_bridge && sub_class == PCI_pci) {
446 		uint8 secondary_bus = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_secondary_bus, 1);
447 		PCIBus *newbus = CreateBus(newdev, bus->domain, secondary_bus);
448 		DiscoverBus(newbus);
449 	}
450 }
451 
452 
453 PCIBus *
454 PCI::CreateBus(PCIDev *parent, int domain, uint8 bus)
455 {
456 	PCIBus *newbus = new PCIBus;
457 	newbus->next = NULL;
458 	newbus->parent = parent;
459 	newbus->child = NULL;
460 	newbus->domain = domain;
461 	newbus->bus = bus;
462 
463 	// append
464 	parent->child = newbus;
465 
466 	return newbus;
467 }
468 
469 
470 PCIDev *
471 PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func)
472 {
473 	TRACE(("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent->domain, parent->bus, dev, func));
474 
475 	PCIDev *newdev = new PCIDev;
476 	newdev->next = NULL;
477 	newdev->parent = parent;
478 	newdev->child = NULL;
479 	newdev->domain = parent->domain;
480 	newdev->bus = parent->bus;
481 	newdev->dev = dev;
482 	newdev->func = func;
483 
484 	ReadPciBasicInfo(newdev);
485 
486 	TRACE(("PCI: vendor 0x%04x, device 0x%04x, class_base 0x%02x, class_sub 0x%02x\n",
487 		newdev->info.vendor_id, newdev->info.device_id, newdev->info.class_base, newdev->info.class_sub));
488 
489 	// append
490 	if (parent->child == 0) {
491 		parent->child = newdev;
492 	} else {
493 		PCIDev *sub = parent->child;
494 		while (sub->next)
495 			sub = sub->next;
496 		sub->next = newdev;
497 	}
498 
499 	return newdev;
500 }
501 
502 
503 uint32
504 PCI::BarSize(uint32 bits, uint32 mask)
505 {
506 	bits &= mask;
507 	if (!bits)
508 		return 0;
509 	uint32 size = 1;
510 	while (!(bits & size))
511 		size <<= 1;
512 	return size;
513 }
514 
515 
516 void
517 PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
518 {
519 	uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
520 	WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff);
521 	uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
522 	WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
523 
524 	*address = oldvalue & PCI_address_memory_32_mask;
525 	if (size)
526 		*size = BarSize(newvalue, PCI_address_memory_32_mask);
527 	if (flags)
528 		*flags = newvalue & 0xf;
529 }
530 
531 
532 void
533 PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
534 {
535 	uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
536 	WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0
537 	uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
538 	WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
539 
540 	*address = oldvalue & PCI_rom_address_mask;
541 	if (size)
542 		*size = BarSize(newvalue, PCI_rom_address_mask);
543 	if (flags)
544 		*flags = newvalue & 0xf;
545 }
546 
547 
548 void
549 PCI::ReadPciBasicInfo(PCIDev *dev)
550 {
551 	uint8 virt_bus;
552 
553 	if (AddVirtBus(dev->domain, dev->bus, &virt_bus) != B_OK) {
554 		dprintf("PCI: AddVirtBus failed, domain %u, bus %u\n", dev->domain, dev->bus);
555 		return;
556 	}
557 
558 	dev->info.vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_vendor_id, 2);
559 	dev->info.device_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_device_id, 2);
560 	dev->info.bus = virt_bus;
561 	dev->info.device = dev->dev;
562 	dev->info.function = dev->func;
563 	dev->info.revision = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_revision, 1);
564 	dev->info.class_api = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_api, 1);
565 	dev->info.class_sub = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_sub, 1);
566 	dev->info.class_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_base, 1);
567 	dev->info.line_size = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_line_size, 1);
568 	dev->info.latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_latency, 1);
569 	// BeOS does not mask off the multifunction bit, developer must use (header_type & PCI_header_type_mask)
570 	dev->info.header_type = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_header_type, 1);
571 	dev->info.bist = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bist, 1);
572 	dev->info.reserved = 0;
573 }
574 
575 
576 void
577 PCI::ReadPciHeaderInfo(PCIDev *dev)
578 {
579 	switch (dev->info.header_type & PCI_header_type_mask) {
580 		case PCI_header_type_generic:
581 		{
582 			// disable PCI device address decoding (io and memory) while BARs are modified
583 			uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2);
584 			WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
585 
586 			// get BAR size infos
587 			GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, &dev->info.u.h0.rom_size);
588 			for (int i = 0; i < 6; i++) {
589 				GetBarInfo(dev, PCI_base_registers + 4*i,
590 					&dev->info.u.h0.base_registers_pci[i],
591 					&dev->info.u.h0.base_register_sizes[i],
592 					&dev->info.u.h0.base_register_flags[i]);
593 			}
594 
595 			// restore PCI device address decoding
596 			WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
597 
598 			dev->info.u.h0.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h0.rom_base_pci);
599 			for (int i = 0; i < 6; i++) {
600 				dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h0.base_registers_pci[i]);
601 			}
602 
603 			dev->info.u.h0.cardbus_cis = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_cardbus_cis, 4);
604 			dev->info.u.h0.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_id, 2);
605 			dev->info.u.h0.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_vendor_id, 2);
606 			dev->info.u.h0.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
607 			dev->info.u.h0.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
608 			dev->info.u.h0.min_grant = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_min_grant, 1);
609 			dev->info.u.h0.max_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_max_latency, 1);
610 			break;
611 		}
612 
613 		case PCI_header_type_PCI_to_PCI_bridge:
614 		{
615 			// disable PCI device address decoding (io and memory) while BARs are modified
616 			uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2);
617 			WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
618 
619 			GetRomBarInfo(dev, PCI_bridge_rom_base, &dev->info.u.h1.rom_base_pci);
620 			for (int i = 0; i < 2; i++) {
621 				GetBarInfo(dev, PCI_base_registers + 4*i,
622 					&dev->info.u.h1.base_registers_pci[i],
623 					&dev->info.u.h1.base_register_sizes[i],
624 					&dev->info.u.h1.base_register_flags[i]);
625 			}
626 
627 			// restore PCI device address decoding
628 			WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
629 
630 			dev->info.u.h1.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h1.rom_base_pci);
631 			for (int i = 0; i < 2; i++) {
632 				dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h1.base_registers_pci[i]);
633 			}
634 
635 			dev->info.u.h1.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus, 1);
636 			dev->info.u.h1.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus, 1);
637 			dev->info.u.h1.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus, 1);
638 			dev->info.u.h1.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency, 1);
639 			dev->info.u.h1.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base, 1);
640 			dev->info.u.h1.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit, 1);
641 			dev->info.u.h1.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status, 2);
642 			dev->info.u.h1.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base, 2);
643 			dev->info.u.h1.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit, 2);
644 			dev->info.u.h1.prefetchable_memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base, 2);
645 			dev->info.u.h1.prefetchable_memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2);
646 			dev->info.u.h1.prefetchable_memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base_upper32, 4);
647 			dev->info.u.h1.prefetchable_memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_upper32, 4);
648 			dev->info.u.h1.io_base_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2);
649 			dev->info.u.h1.io_limit_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit_upper16, 2);
650 			dev->info.u.h1.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
651 			dev->info.u.h1.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
652 			dev->info.u.h1.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
653 			dev->info.u.h1.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_1, 2);
654 			dev->info.u.h1.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_1, 2);
655 			break;
656 		}
657 
658 		case PCI_header_type_cardbus:
659 		{
660 			// for testing only, not final:
661 			dev->info.u.h2.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_2, 2);
662 			dev->info.u.h2.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_2, 2);
663 			dev->info.u.h2.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus_2, 1);
664 			dev->info.u.h2.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus_2, 1);
665 			dev->info.u.h2.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus_2, 1);
666 			dev->info.u.h2.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency_2, 1);
667 			dev->info.u.h2.reserved = 0;
668 			dev->info.u.h2.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base0_2, 4);
669 			dev->info.u.h2.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit0_2, 4);
670 			dev->info.u.h2.memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base1_2, 4);
671 			dev->info.u.h2.memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit1_2, 4);
672 			dev->info.u.h2.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base0_2, 4);
673 			dev->info.u.h2.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit0_2, 4);
674 			dev->info.u.h2.io_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base1_2, 4);
675 			dev->info.u.h2.io_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit1_2, 4);
676 			dev->info.u.h2.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status_2, 2);
677 			dev->info.u.h2.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control_2, 1);
678 			break;
679 		}
680 
681 		default:
682 			TRACE(("PCI: Header type unknown (0x%02x)\n", dev->info.header_type));
683 			break;
684 	}
685 }
686 
687 
688 void
689 PCI::RefreshDeviceInfo(PCIBus *bus)
690 {
691 	for (PCIDev *dev = bus->child; dev; dev = dev->next) {
692 		ReadPciBasicInfo(dev);
693 		ReadPciHeaderInfo(dev);
694 		if (dev->child)
695 			RefreshDeviceInfo(dev->child);
696 	}
697 
698 	if (bus->next)
699 		RefreshDeviceInfo(bus->next);
700 }
701 
702 
703 status_t
704 PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
705 				   uint8 offset, uint8 size, uint32 *value)
706 {
707 	domain_data *info;
708 	info = GetDomainData(domain);
709 	if (!info)
710 		return B_ERROR;
711 
712 	if (device > (info->max_bus_devices - 1)
713 		|| function > 7
714 		|| (size != 1 && size != 2 && size != 4)
715 		|| (size == 2 && (offset & 3) == 3)
716 		|| (size == 4 && (offset & 3) != 0)) {
717 		dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
718 			 domain, bus, device, function, offset, size);
719 		return B_ERROR;
720 	}
721 
722 	status_t status;
723 	status = (*info->controller->read_pci_config)(info->controller_cookie,
724 												  bus, device, function,
725 												  offset, size, value);
726 	return status;
727 }
728 
729 
730 uint32
731 PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
732 				   uint8 offset, uint8 size)
733 {
734 	uint32 value;
735 
736 	if (ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK)
737 		return 0xffffffff;
738 
739 	return value;
740 }
741 
742 
743 status_t
744 PCI::WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function,
745 					uint8 offset, uint8 size, uint32 value)
746 {
747 	domain_data *info;
748 	info = GetDomainData(domain);
749 	if (!info)
750 		return B_ERROR;
751 
752 	if (device > (info->max_bus_devices - 1)
753 		|| function > 7
754 		|| (size != 1 && size != 2 && size != 4)
755 		|| (size == 2 && (offset & 3) == 3)
756 		|| (size == 4 && (offset & 3) != 0)) {
757 		dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
758 			 domain, bus, device, function, offset, size);
759 		return B_ERROR;
760 	}
761 
762 	status_t status;
763 	status = (*info->controller->write_pci_config)(info->controller_cookie,
764 												   bus, device, function,
765 												   offset, size, value);
766 	return status;
767 }
768 
769