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