2 * Copyright 2003-2008, Marcus Overhagen. All rights reserved.
3 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
5 * Distributed under the terms of the MIT License.
10 #include <KernelExport.h>
11 #define __HAIKU_PCI_BUS_MANAGER_TESTING 1
14 #include "util/kernel_cpp.h"
15 #include "pci_fixup.h"
17 #include "pci_private.h"
20 #define TRACE_CAP(x...) dprintf(x)
22 //#define FLOW(x...) dprintf(x)
28 // #pragma mark bus manager exports
32 pci_controller_add(pci_controller
*controller
, void *cookie
)
34 return gPCI
->AddController(controller
, cookie
);
39 pci_get_nth_pci_info(long index
, pci_info
*outInfo
)
41 return gPCI
->GetNthInfo(index
, outInfo
);
46 pci_read_config(uint8 virtualBus
, uint8 device
, uint8 function
, uint16 offset
,
53 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
56 if (gPCI
->ReadConfig(domain
, bus
, device
, function
, offset
, size
,
65 pci_write_config(uint8 virtualBus
, uint8 device
, uint8 function
, uint16 offset
,
66 uint8 size
, uint32 value
)
70 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
73 gPCI
->WriteConfig(domain
, bus
, device
, function
, offset
, size
, value
);
78 pci_find_capability(uint8 virtualBus
, uint8 device
, uint8 function
,
79 uint8 capID
, uint8
*offset
)
83 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
86 return gPCI
->FindCapability(domain
, bus
, device
, function
, capID
, offset
);
91 pci_find_extended_capability(uint8 virtualBus
, uint8 device
, uint8 function
,
92 uint16 capID
, uint16
*offset
)
96 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
99 return gPCI
->FindExtendedCapability(domain
, bus
, device
, function
, capID
,
105 pci_reserve_device(uchar virtualBus
, uchar device
, uchar function
,
106 const char *driverName
, void *nodeCookie
)
111 TRACE(("pci_reserve_device(%d, %d, %d, %s)\n", virtualBus
, device
, function
,
115 * we add 2 nodes to the PCI devices, one with constant attributes,
116 * so adding for another driver fails, and a subnode with the
117 * driver-provided informations.
120 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
123 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
124 // domain, bus, device, function, driverName, nodeCookie));
126 device_attr matchPCIRoot
[] = {
127 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "PCI"}},
130 device_attr matchThis
[] = {
132 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "pci"}},
134 // location on PCI bus
135 {B_PCI_DEVICE_DOMAIN
, B_UINT8_TYPE
, {ui8
: domain
}},
136 {B_PCI_DEVICE_BUS
, B_UINT8_TYPE
, {ui8
: bus
}},
137 {B_PCI_DEVICE_DEVICE
, B_UINT8_TYPE
, {ui8
: device
}},
138 {B_PCI_DEVICE_FUNCTION
, B_UINT8_TYPE
, {ui8
: function
}},
141 device_attr legacyAttrs
[] = {
143 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "legacy_driver"}},
144 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "Legacy Driver Reservation"}},
147 device_attr drvAttrs
[] = {
149 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "legacy_driver"}},
150 {"legacy_driver", B_STRING_TYPE
, {string
: driverName
}},
151 {"legacy_driver_cookie", B_UINT64_TYPE
, {ui64
: (uint64
)nodeCookie
}},
154 device_node
*root
, *pci
, *node
, *legacy
;
156 status
= B_DEVICE_NOT_FOUND
;
157 root
= gDeviceManager
->get_root_node();
162 if (gDeviceManager
->get_next_child_node(root
, matchPCIRoot
, &pci
) < B_OK
)
166 if (gDeviceManager
->get_next_child_node(pci
, matchThis
, &node
) < B_OK
)
169 // common API for all legacy modules ?
170 //status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME);
172 status
= gDeviceManager
->register_node(node
, PCI_LEGACY_DRIVER_MODULE_NAME
,
173 legacyAttrs
, NULL
, &legacy
);
177 status
= gDeviceManager
->register_node(legacy
, PCI_LEGACY_DRIVER_MODULE_NAME
,
178 drvAttrs
, NULL
, NULL
);
182 gDeviceManager
->put_node(node
);
183 gDeviceManager
->put_node(pci
);
184 gDeviceManager
->put_node(root
);
189 gDeviceManager
->unregister_node(legacy
);
191 gDeviceManager
->put_node(node
);
193 gDeviceManager
->put_node(pci
);
195 gDeviceManager
->put_node(root
);
196 TRACE(("pci_reserve_device for driver %s failed: %s\n", driverName
,
203 pci_unreserve_device(uchar virtualBus
, uchar device
, uchar function
,
204 const char *driverName
, void *nodeCookie
)
209 TRACE(("pci_unreserve_device(%d, %d, %d, %s)\n", virtualBus
, device
,
210 function
, driverName
));
212 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
215 //TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
216 // domain, bus, device, function, driverName, nodeCookie));
218 device_attr matchPCIRoot
[] = {
219 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "PCI"}},
222 device_attr matchThis
[] = {
224 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "pci"}},
226 // location on PCI bus
227 {B_PCI_DEVICE_DOMAIN
, B_UINT8_TYPE
, {ui8
: domain
}},
228 {B_PCI_DEVICE_BUS
, B_UINT8_TYPE
, {ui8
: bus
}},
229 {B_PCI_DEVICE_DEVICE
, B_UINT8_TYPE
, {ui8
: device
}},
230 {B_PCI_DEVICE_FUNCTION
, B_UINT8_TYPE
, {ui8
: function
}},
233 device_attr legacyAttrs
[] = {
235 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "legacy_driver"}},
236 {B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
, {string
: "Legacy Driver Reservation"}},
239 device_attr drvAttrs
[] = {
241 {B_DEVICE_BUS
, B_STRING_TYPE
, {string
: "legacy_driver"}},
242 {"legacy_driver", B_STRING_TYPE
, {string
: driverName
}},
243 {"legacy_driver_cookie", B_UINT64_TYPE
, {ui64
: (uint64
)nodeCookie
}},
246 device_node
*root
, *pci
, *node
, *legacy
, *drv
;
248 status
= B_DEVICE_NOT_FOUND
;
249 root
= gDeviceManager
->get_root_node();
254 if (gDeviceManager
->get_next_child_node(root
, matchPCIRoot
, &pci
) < B_OK
)
258 if (gDeviceManager
->get_next_child_node(pci
, matchThis
, &node
) < B_OK
)
261 // common API for all legacy modules ?
262 //status = legacy_driver_unregister(node, driverName, nodeCookie);
265 if (gDeviceManager
->get_next_child_node(node
, legacyAttrs
, &legacy
) < B_OK
)
269 if (gDeviceManager
->get_next_child_node(legacy
, drvAttrs
, &drv
) < B_OK
)
272 gDeviceManager
->put_node(drv
);
273 status
= gDeviceManager
->unregister_node(drv
);
274 //dprintf("unreg:drv:%s\n", strerror(status));
276 gDeviceManager
->put_node(legacy
);
277 status
= gDeviceManager
->unregister_node(legacy
);
278 //dprintf("unreg:legacy:%s\n", strerror(status));
279 // we'll get EBUSY here anyway...
281 gDeviceManager
->put_node(node
);
282 gDeviceManager
->put_node(pci
);
283 gDeviceManager
->put_node(root
);
287 gDeviceManager
->put_node(legacy
);
289 gDeviceManager
->put_node(node
);
291 gDeviceManager
->put_node(pci
);
293 gDeviceManager
->put_node(root
);
294 TRACE(("pci_unreserve_device for driver %s failed: %s\n", driverName
,
301 pci_update_interrupt_line(uchar virtualBus
, uchar device
, uchar function
,
302 uchar newInterruptLineValue
)
306 if (gPCI
->ResolveVirtualBus(virtualBus
, &domain
, &bus
) != B_OK
)
309 return gPCI
->UpdateInterruptLine(domain
, bus
, device
, function
,
310 newInterruptLineValue
);
314 // used by pci_info.cpp print_info_basic()
316 __pci_resolve_virtual_bus(uint8 virtualBus
, uint8
*domain
, uint8
*bus
)
318 if (gPCI
->ResolveVirtualBus(virtualBus
, domain
, bus
) < B_OK
)
319 panic("ResolveVirtualBus failed");
323 // #pragma mark kernel debugger commands
327 display_io(int argc
, char **argv
)
339 address
= strtoul(argv
[1], NULL
, 0);
342 kprintf("usage: %s <address> [num]\n", argv
[0]);
346 // build the format string
347 if (strcmp(argv
[0], "inb") == 0 || strcmp(argv
[0], "in8") == 0) {
350 } else if (strcmp(argv
[0], "ins") == 0 || strcmp(argv
[0], "in16") == 0) {
353 } else if (strcmp(argv
[0], "inw") == 0 || strcmp(argv
[0], "in32") == 0) {
357 kprintf("display_io called in an invalid way!\n");
361 for (i
= 0; i
< num
; i
++) {
362 if ((i
% displayWidth
) == 0) {
363 int32 displayed
= min_c(displayWidth
, (num
-i
)) * itemSize
;
367 kprintf("[0x%" B_PRIx32
"] ", address
+ i
* itemSize
);
369 if (num
> displayWidth
) {
370 // make sure the spacing in the last line is correct
371 for (j
= displayed
; j
< displayWidth
* itemSize
; j
++)
379 kprintf(" %02" B_PRIx8
, pci_read_io_8(address
+ i
* itemSize
));
382 kprintf(" %04" B_PRIx16
, pci_read_io_16(address
+ i
* itemSize
));
385 kprintf(" %08" B_PRIx32
, pci_read_io_32(address
+ i
* itemSize
));
396 write_io(int argc
, char **argv
)
404 kprintf("usage: %s <address> <value> [value [...]]\n", argv
[0]);
408 address
= strtoul(argv
[1], NULL
, 0);
410 if (strcmp(argv
[0], "outb") == 0 || strcmp(argv
[0], "out8") == 0) {
412 } else if (strcmp(argv
[0], "outs") == 0 || strcmp(argv
[0], "out16") == 0) {
414 } else if (strcmp(argv
[0], "outw") == 0 || strcmp(argv
[0], "out32") == 0) {
417 kprintf("write_io called in an invalid way!\n");
421 // skip cmd name and address
425 for (i
= 0; i
< argc
; i
++) {
426 value
= strtoul(argv
[i
], NULL
, 0);
429 pci_write_io_8(address
+ i
* itemSize
, value
);
432 pci_write_io_16(address
+ i
* itemSize
, value
);
435 pci_write_io_32(address
+ i
* itemSize
, value
);
445 pcistatus(int argc
, char **argv
)
447 gPCI
->ClearDeviceStatus(NULL
, true);
453 pcirefresh(int argc
, char **argv
)
455 gPCI
->RefreshDeviceInfo();
461 // #pragma mark bus manager init/uninit
469 if (pci_io_init() != B_OK
) {
470 TRACE(("PCI: pci_io_init failed\n"));
474 add_debugger_command("inw", &display_io
, "dump io words (32-bit)");
475 add_debugger_command("in32", &display_io
, "dump io words (32-bit)");
476 add_debugger_command("ins", &display_io
, "dump io shorts (16-bit)");
477 add_debugger_command("in16", &display_io
, "dump io shorts (16-bit)");
478 add_debugger_command("inb", &display_io
, "dump io bytes (8-bit)");
479 add_debugger_command("in8", &display_io
, "dump io bytes (8-bit)");
481 add_debugger_command("outw", &write_io
, "write io words (32-bit)");
482 add_debugger_command("out32", &write_io
, "write io words (32-bit)");
483 add_debugger_command("outs", &write_io
, "write io shorts (16-bit)");
484 add_debugger_command("out16", &write_io
, "write io shorts (16-bit)");
485 add_debugger_command("outb", &write_io
, "write io bytes (8-bit)");
486 add_debugger_command("out8", &write_io
, "write io bytes (8-bit)");
488 if (pci_controller_init() != B_OK
) {
489 TRACE(("PCI: pci_controller_init failed\n"));
490 panic("PCI: pci_controller_init failed\n");
494 gPCI
->InitDomainData();
497 add_debugger_command("pcistatus", &pcistatus
, "dump and clear pci device status registers");
498 add_debugger_command("pcirefresh", &pcirefresh
, "refresh and print all pci_info");
507 remove_debugger_command("outw", &write_io
);
508 remove_debugger_command("out32", &write_io
);
509 remove_debugger_command("outs", &write_io
);
510 remove_debugger_command("out16", &write_io
);
511 remove_debugger_command("outb", &write_io
);
512 remove_debugger_command("out8", &write_io
);
514 remove_debugger_command("inw", &display_io
);
515 remove_debugger_command("in32", &display_io
);
516 remove_debugger_command("ins", &display_io
);
517 remove_debugger_command("in16", &display_io
);
518 remove_debugger_command("inb", &display_io
);
519 remove_debugger_command("in8", &display_io
);
521 remove_debugger_command("pcistatus", &pcistatus
);
522 remove_debugger_command("pcirefresh", &pcirefresh
);
528 // #pragma mark PCI class
535 fBusEnumeration(false),
539 #if defined(__POWERPC__) || defined(__M68K__)
540 fBusEnumeration
= true;
548 PCIBus
**nextBus
= &fRootBus
;
549 for (uint8 i
= 0; i
< fDomainCount
; i
++) {
550 PCIBus
*bus
= new PCIBus
;
557 nextBus
= &bus
->next
;
560 if (fBusEnumeration
) {
561 for (uint8 i
= 0; i
< fDomainCount
; i
++) {
567 for (uint8 i
= 0; i
< fDomainCount
; i
++) {
573 _DiscoverBus(fRootBus
);
574 _ConfigureBridges(fRootBus
);
575 ClearDeviceStatus(fRootBus
, false);
576 _RefreshDeviceInfo(fRootBus
);
587 PCI::_CreateVirtualBus(uint8 domain
, uint8 bus
, uint8
*virtualBus
)
589 #if defined(__INTEL__) || defined(__x86_64__)
591 // IA32 doesn't use domains
593 panic("PCI::CreateVirtualBus domain != 0");
599 if (fNextVirtualBus
> 0xff)
600 panic("PCI::CreateVirtualBus: virtual bus number space exhausted");
602 uint16 value
= domain
<< 8 | bus
;
604 for (VirtualBusMap::Iterator it
= fVirtualBusMap
.Begin();
605 it
!= fVirtualBusMap
.End(); ++it
) {
606 if (it
->Value() == value
) {
607 *virtualBus
= it
->Key();
608 FLOW("PCI::CreateVirtualBus: domain %d, bus %d already in map => "
609 "virtualBus %d\n", domain
, bus
, *virtualBus
);
614 *virtualBus
= fNextVirtualBus
++;
616 FLOW("PCI::CreateVirtualBus: domain %d, bus %d => virtualBus %d\n", domain
,
619 return fVirtualBusMap
.Insert(*virtualBus
, value
);
626 PCI::ResolveVirtualBus(uint8 virtualBus
, uint8
*domain
, uint8
*bus
)
628 #if defined(__INTEL__) || defined(__x86_64__)
630 // IA32 doesn't use domains
637 if (virtualBus
>= fNextVirtualBus
)
640 uint16 value
= fVirtualBusMap
.Get(virtualBus
);
641 *domain
= value
>> 8;
650 PCI::AddController(pci_controller
*controller
, void *controller_cookie
)
652 if (fDomainCount
== MAX_PCI_DOMAINS
)
655 fDomainData
[fDomainCount
].controller
= controller
;
656 fDomainData
[fDomainCount
].controller_cookie
= controller_cookie
;
658 // initialized later to avoid call back into controller at this point
659 fDomainData
[fDomainCount
].max_bus_devices
= -1;
666 PCI::InitDomainData()
668 for (uint8 i
= 0; i
< fDomainCount
; i
++) {
672 status
= (*fDomainData
[i
].controller
->get_max_bus_devices
)(
673 fDomainData
[i
].controller_cookie
, &count
);
674 fDomainData
[i
].max_bus_devices
= (status
== B_OK
) ? count
: 0;
680 PCI::_GetDomainData(uint8 domain
)
682 if (domain
>= fDomainCount
)
685 return &fDomainData
[domain
];
690 PCI::_NumFunctions(uint8 domain
, uint8 bus
, uint8 device
)
692 uint8 type
= ReadConfig(domain
, bus
, device
,
693 0, PCI_header_type
, 1);
694 return (type
& PCI_multifunction
) != 0 ? 8 : 1;
699 PCI::GetNthInfo(long index
, pci_info
*outInfo
)
701 long currentIndex
= 0;
705 return _GetNthInfo(fRootBus
, ¤tIndex
, index
, outInfo
);
710 PCI::_GetNthInfo(PCIBus
*bus
, long *currentIndex
, long wantIndex
,
713 // maps tree structure to linear indexed view
714 PCIDev
*dev
= bus
->child
;
716 if (*currentIndex
== wantIndex
) {
717 *outInfo
= dev
->info
;
721 if (dev
->child
&& B_OK
== _GetNthInfo(dev
->child
, currentIndex
,
728 return _GetNthInfo(bus
->next
, currentIndex
, wantIndex
, outInfo
);
735 PCI::_EnumerateBus(uint8 domain
, uint8 bus
, uint8
*subordinateBus
)
737 TRACE(("PCI: EnumerateBus: domain %u, bus %u\n", domain
, bus
));
739 int maxBusDevices
= _GetDomainData(domain
)->max_bus_devices
;
741 // step 1: disable all bridges on this bus
742 for (int dev
= 0; dev
< maxBusDevices
; dev
++) {
743 uint16 vendor_id
= ReadConfig(domain
, bus
, dev
, 0, PCI_vendor_id
, 2);
744 if (vendor_id
== 0xffff)
747 int numFunctions
= _NumFunctions(domain
, bus
, dev
);
748 for (int function
= 0; function
< numFunctions
; function
++) {
749 uint16 device_id
= ReadConfig(domain
, bus
, dev
, function
,
751 if (device_id
== 0xffff)
754 uint8 baseClass
= ReadConfig(domain
, bus
, dev
, function
,
756 uint8 subClass
= ReadConfig(domain
, bus
, dev
, function
,
758 if (baseClass
!= PCI_bridge
|| subClass
!= PCI_pci
)
761 // skip incorrectly configured devices
762 uint8 headerType
= ReadConfig(domain
, bus
, dev
, function
,
763 PCI_header_type
, 1) & PCI_header_type_mask
;
764 if (headerType
!= PCI_header_type_PCI_to_PCI_bridge
)
767 TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n",
768 domain
, bus
, dev
, function
));
769 TRACE(("PCI: original settings: pcicmd %04" B_PRIx32
", primary-bus "
770 "%" B_PRIu32
", secondary-bus %" B_PRIu32
", subordinate-bus "
772 ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2),
773 ReadConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1),
774 ReadConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1),
775 ReadConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1)));
779 pcicmd
= ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2);
780 pcicmd
&= ~(PCI_command_io
| PCI_command_memory
781 | PCI_command_master
);
782 WriteConfig(domain
, bus
, dev
, function
, PCI_command
, 2, pcicmd
);
785 WriteConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1, 0);
786 WriteConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1, 0);
787 WriteConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1, 0);
789 TRACE(("PCI: disabled settings: pcicmd %04" B_PRIx32
", primary-bus "
790 "%" B_PRIu32
", secondary-bus %" B_PRIu32
", subordinate-bus "
792 ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2),
793 ReadConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1),
794 ReadConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1),
795 ReadConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1)));
799 uint8 lastUsedBusNumber
= bus
;
801 // step 2: assign busses to all bridges, and enable them again
802 for (int dev
= 0; dev
< maxBusDevices
; dev
++) {
803 uint16 vendor_id
= ReadConfig(domain
, bus
, dev
, 0, PCI_vendor_id
, 2);
804 if (vendor_id
== 0xffff)
807 int numFunctions
= _NumFunctions(domain
, bus
, dev
);
808 for (int function
= 0; function
< numFunctions
; function
++) {
809 uint16 deviceID
= ReadConfig(domain
, bus
, dev
, function
,
811 if (deviceID
== 0xffff)
814 uint8 baseClass
= ReadConfig(domain
, bus
, dev
, function
,
816 uint8 subClass
= ReadConfig(domain
, bus
, dev
, function
,
818 if (baseClass
!= PCI_bridge
|| subClass
!= PCI_pci
)
821 // skip incorrectly configured devices
822 uint8 headerType
= ReadConfig(domain
, bus
, dev
, function
,
823 PCI_header_type
, 1) & PCI_header_type_mask
;
824 if (headerType
!= PCI_header_type_PCI_to_PCI_bridge
)
827 TRACE(("PCI: configuring PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n",
828 domain
, bus
, dev
, function
));
830 // open Scheunentor for enumerating the bus behind the bridge
831 WriteConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1, bus
);
832 WriteConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1,
833 lastUsedBusNumber
+ 1);
834 WriteConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1, 255);
836 // enable decoding (too early here?)
838 pcicmd
= ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2);
839 pcicmd
|= PCI_command_io
| PCI_command_memory
| PCI_command_master
;
840 WriteConfig(domain
, bus
, dev
, function
, PCI_command
, 2, pcicmd
);
842 TRACE(("PCI: probing settings: pcicmd %04" B_PRIx32
", primary-bus "
843 "%" B_PRIu32
", secondary-bus %" B_PRIu32
", subordinate-bus "
845 ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2),
846 ReadConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1),
847 ReadConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1),
848 ReadConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1)));
851 _EnumerateBus(domain
, lastUsedBusNumber
+ 1, &lastUsedBusNumber
);
854 WriteConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1, lastUsedBusNumber
);
856 TRACE(("PCI: configured settings: pcicmd %04" B_PRIx32
", primary-bus "
857 "%" B_PRIu32
", secondary-bus %" B_PRIu32
", subordinate-bus "
859 ReadConfig(domain
, bus
, dev
, function
, PCI_command
, 2),
860 ReadConfig(domain
, bus
, dev
, function
, PCI_primary_bus
, 1),
861 ReadConfig(domain
, bus
, dev
, function
, PCI_secondary_bus
, 1),
862 ReadConfig(domain
, bus
, dev
, function
, PCI_subordinate_bus
, 1)));
866 *subordinateBus
= lastUsedBusNumber
;
868 TRACE(("PCI: EnumerateBus done: domain %u, bus %u, last used bus number %u\n", domain
, bus
, lastUsedBusNumber
));
873 PCI::_FixupDevices(uint8 domain
, uint8 bus
)
875 FLOW("PCI: FixupDevices domain %u, bus %u\n", domain
, bus
);
877 int maxBusDevices
= _GetDomainData(domain
)->max_bus_devices
;
878 static int recursed
= 0;
880 if (recursed
++ > 10) {
881 // guard against buggy chipsets
882 // XXX: is there any official limit ?
883 dprintf("PCI: FixupDevices: too many recursions (buggy chipset?)\n");
888 for (int dev
= 0; dev
< maxBusDevices
; dev
++) {
889 uint16 vendorId
= ReadConfig(domain
, bus
, dev
, 0, PCI_vendor_id
, 2);
890 if (vendorId
== 0xffff)
893 int numFunctions
= _NumFunctions(domain
, bus
, dev
);
894 for (int function
= 0; function
< numFunctions
; function
++) {
895 uint16 deviceId
= ReadConfig(domain
, bus
, dev
, function
,
897 if (deviceId
== 0xffff)
900 pci_fixup_device(this, domain
, bus
, dev
, function
);
902 uint8 baseClass
= ReadConfig(domain
, bus
, dev
, function
,
904 if (baseClass
!= PCI_bridge
)
906 uint8 subClass
= ReadConfig(domain
, bus
, dev
, function
,
908 if (subClass
!= PCI_pci
)
911 // some FIC motherboards have a buggy BIOS...
912 // make sure the header type is correct for a bridge,
913 uint8 headerType
= ReadConfig(domain
, bus
, dev
, function
,
914 PCI_header_type
, 1) & PCI_header_type_mask
;
915 if (headerType
!= PCI_header_type_PCI_to_PCI_bridge
) {
916 dprintf("PCI: dom %u, bus %u, dev %2u, func %u, PCI bridge"
917 " class but wrong header type 0x%02x, ignoring.\n",
918 domain
, bus
, dev
, function
, headerType
);
923 int busBehindBridge
= ReadConfig(domain
, bus
, dev
, function
,
924 PCI_secondary_bus
, 1);
926 TRACE(("PCI: FixupDevices: checking bus %d behind %04x:%04x\n",
927 busBehindBridge
, vendorId
, deviceId
));
928 _FixupDevices(domain
, busBehindBridge
);
936 PCI::_ConfigureBridges(PCIBus
*bus
)
938 for (PCIDev
*dev
= bus
->child
; dev
; dev
= dev
->next
) {
939 if (dev
->info
.class_base
== PCI_bridge
940 && dev
->info
.class_sub
== PCI_pci
941 && (dev
->info
.header_type
& PCI_header_type_mask
)
942 == PCI_header_type_PCI_to_PCI_bridge
) {
943 uint16 bridgeControlOld
= ReadConfig(dev
->domain
, dev
->bus
,
944 dev
->device
, dev
->function
, PCI_bridge_control
, 2);
945 uint16 bridgeControlNew
= bridgeControlOld
;
946 // Enable: Parity Error Response, SERR, Master Abort Mode, Discard
948 // Clear: Discard Timer Status
949 bridgeControlNew
|= PCI_bridge_parity_error_response
950 | PCI_bridge_serr
| PCI_bridge_master_abort
951 | PCI_bridge_discard_timer_status
952 | PCI_bridge_discard_timer_serr
;
953 // Set discard timer to 2^15 PCI clocks
954 bridgeControlNew
&= ~(PCI_bridge_primary_discard_timeout
955 | PCI_bridge_secondary_discard_timeout
);
956 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
957 PCI_bridge_control
, 2, bridgeControlNew
);
958 bridgeControlNew
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
959 dev
->function
, PCI_bridge_control
, 2);
960 dprintf("PCI: dom %u, bus %u, dev %2u, func %u, changed PCI bridge"
961 " control from 0x%04x to 0x%04x\n", dev
->domain
, dev
->bus
,
962 dev
->device
, dev
->function
, bridgeControlOld
,
967 _ConfigureBridges(dev
->child
);
971 _ConfigureBridges(bus
->next
);
976 PCI::ClearDeviceStatus(PCIBus
*bus
, bool dumpStatus
)
984 for (PCIDev
*dev
= bus
->child
; dev
; dev
= dev
->next
) {
985 // Clear and dump PCI device status
986 uint16 status
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
987 dev
->function
, PCI_status
, 2);
988 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
989 PCI_status
, 2, status
);
991 kprintf("domain %u, bus %u, dev %2u, func %u, PCI device status "
992 "0x%04x\n", dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
994 if (status
& PCI_status_parity_error_detected
)
995 kprintf(" Detected Parity Error\n");
996 if (status
& PCI_status_serr_signalled
)
997 kprintf(" Signalled System Error\n");
998 if (status
& PCI_status_master_abort_received
)
999 kprintf(" Received Master-Abort\n");
1000 if (status
& PCI_status_target_abort_received
)
1001 kprintf(" Received Target-Abort\n");
1002 if (status
& PCI_status_target_abort_signalled
)
1003 kprintf(" Signalled Target-Abort\n");
1004 if (status
& PCI_status_parity_signalled
)
1005 kprintf(" Master Data Parity Error\n");
1008 if (dev
->info
.class_base
== PCI_bridge
1009 && dev
->info
.class_sub
== PCI_pci
) {
1010 // Clear and dump PCI bridge secondary status
1011 uint16 secondaryStatus
= ReadConfig(dev
->domain
, dev
->bus
,
1012 dev
->device
, dev
->function
, PCI_secondary_status
, 2);
1013 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1014 PCI_secondary_status
, 2, secondaryStatus
);
1016 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge "
1017 "secondary status 0x%04x\n", dev
->domain
, dev
->bus
,
1018 dev
->device
, dev
->function
, secondaryStatus
);
1019 if (secondaryStatus
& PCI_status_parity_error_detected
)
1020 kprintf(" Detected Parity Error\n");
1021 if (secondaryStatus
& PCI_status_serr_signalled
)
1022 kprintf(" Received System Error\n");
1023 if (secondaryStatus
& PCI_status_master_abort_received
)
1024 kprintf(" Received Master-Abort\n");
1025 if (secondaryStatus
& PCI_status_target_abort_received
)
1026 kprintf(" Received Target-Abort\n");
1027 if (secondaryStatus
& PCI_status_target_abort_signalled
)
1028 kprintf(" Signalled Target-Abort\n");
1029 if (secondaryStatus
& PCI_status_parity_signalled
)
1030 kprintf(" Data Parity Reported\n");
1033 // Clear and dump the discard-timer error bit located in bridge-control register
1034 uint16 bridgeControl
= ReadConfig(dev
->domain
, dev
->bus
,
1035 dev
->device
, dev
->function
, PCI_bridge_control
, 2);
1036 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1037 PCI_bridge_control
, 2, bridgeControl
);
1039 kprintf("domain %u, bus %u, dev %2u, func %u, PCI bridge "
1040 "control 0x%04x\n", dev
->domain
, dev
->bus
, dev
->device
,
1041 dev
->function
, bridgeControl
);
1042 if (bridgeControl
& PCI_bridge_discard_timer_status
) {
1043 kprintf(" bridge-control: Discard Timer Error\n");
1049 ClearDeviceStatus(dev
->child
, dumpStatus
);
1053 ClearDeviceStatus(bus
->next
, dumpStatus
);
1058 PCI::_DiscoverBus(PCIBus
*bus
)
1060 FLOW("PCI: DiscoverBus, domain %u, bus %u\n", bus
->domain
, bus
->bus
);
1062 int maxBusDevices
= _GetDomainData(bus
->domain
)->max_bus_devices
;
1063 static int recursed
= 0;
1065 if (recursed
++ > 10) {
1066 // guard against buggy chipsets
1067 // XXX: is there any official limit ?
1068 dprintf("PCI: DiscoverBus: too many recursions (buggy chipset?)\n");
1073 for (int dev
= 0; dev
< maxBusDevices
; dev
++) {
1074 uint16 vendorID
= ReadConfig(bus
->domain
, bus
->bus
, dev
, 0,
1076 if (vendorID
== 0xffff)
1079 int numFunctions
= _NumFunctions(bus
->domain
, bus
->bus
, dev
);
1080 for (int function
= 0; function
< numFunctions
; function
++)
1081 _DiscoverDevice(bus
, dev
, function
);
1085 _DiscoverBus(bus
->next
);
1091 PCI::_DiscoverDevice(PCIBus
*bus
, uint8 dev
, uint8 function
)
1093 FLOW("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus
->domain
, bus
->bus
, dev
, function
);
1095 uint16 deviceID
= ReadConfig(bus
->domain
, bus
->bus
, dev
, function
,
1097 if (deviceID
== 0xffff)
1100 PCIDev
*newDev
= _CreateDevice(bus
, dev
, function
);
1102 uint8 baseClass
= ReadConfig(bus
->domain
, bus
->bus
, dev
, function
,
1104 uint8 subClass
= ReadConfig(bus
->domain
, bus
->bus
, dev
, function
,
1106 uint8 headerType
= ReadConfig(bus
->domain
, bus
->bus
, dev
, function
,
1107 PCI_header_type
, 1) & PCI_header_type_mask
;
1108 if (baseClass
== PCI_bridge
&& subClass
== PCI_pci
1109 && headerType
== PCI_header_type_PCI_to_PCI_bridge
) {
1110 uint8 secondaryBus
= ReadConfig(bus
->domain
, bus
->bus
, dev
, function
,
1111 PCI_secondary_bus
, 1);
1112 PCIBus
*newBus
= _CreateBus(newDev
, bus
->domain
, secondaryBus
);
1113 _DiscoverBus(newBus
);
1119 PCI::_CreateBus(PCIDev
*parent
, uint8 domain
, uint8 bus
)
1121 PCIBus
*newBus
= new(std::nothrow
) PCIBus
;
1125 newBus
->next
= NULL
;
1126 newBus
->parent
= parent
;
1127 newBus
->child
= NULL
;
1128 newBus
->domain
= domain
;
1132 parent
->child
= newBus
;
1139 PCI::_CreateDevice(PCIBus
*parent
, uint8 device
, uint8 function
)
1141 FLOW("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent
->domain
,
1142 parent
->bus
, device
, function
);
1144 PCIDev
*newDev
= new(std::nothrow
) PCIDev
;
1148 newDev
->next
= NULL
;
1149 newDev
->parent
= parent
;
1150 newDev
->child
= NULL
;
1151 newDev
->domain
= parent
->domain
;
1152 newDev
->bus
= parent
->bus
;
1153 newDev
->device
= device
;
1154 newDev
->function
= function
;
1155 memset(&newDev
->info
, 0, sizeof(newDev
->info
));
1157 _ReadBasicInfo(newDev
);
1159 FLOW("PCI: CreateDevice, vendor 0x%04x, device 0x%04x, class_base 0x%02x, "
1160 "class_sub 0x%02x\n", newDev
->info
.vendor_id
, newDev
->info
.device_id
,
1161 newDev
->info
.class_base
, newDev
->info
.class_sub
);
1164 if (parent
->child
== NULL
) {
1165 parent
->child
= newDev
;
1167 PCIDev
*sub
= parent
->child
;
1178 PCI::_BarSize(uint32 bits
, uint32 mask
)
1184 while (!(bits
& size
))
1191 PCI::_GetBarInfo(PCIDev
*dev
, uint8 offset
, uint32
*_address
, uint32
*_size
,
1192 uint8
*_flags
, uint32
*_highAddress
)
1194 uint32 oldValue
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1196 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
, offset
, 4,
1198 uint32 newValue
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1200 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
, offset
, 4,
1203 uint32 mask
= PCI_address_memory_32_mask
;
1204 bool is64bit
= (oldValue
& PCI_address_type_64
) != 0;
1205 if ((oldValue
& PCI_address_space
) == PCI_address_space
)
1206 mask
= PCI_address_io_mask
;
1207 else if (is64bit
&& _highAddress
!= NULL
) {
1208 *_highAddress
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1209 dev
->function
, offset
+ 4, 4);
1212 *_address
= oldValue
& mask
;
1214 *_size
= _BarSize(newValue
, mask
);
1216 *_flags
= oldValue
& ~mask
;
1217 return is64bit
? 2 : 1;
1222 PCI::_GetRomBarInfo(PCIDev
*dev
, uint8 offset
, uint32
*_address
, uint32
*_size
,
1225 uint32 oldValue
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1227 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
, offset
, 4,
1228 0xfffffffe); // LSB must be 0
1229 uint32 newValue
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1231 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
, offset
, 4,
1234 *_address
= oldValue
& PCI_rom_address_mask
;
1236 *_size
= _BarSize(newValue
, PCI_rom_address_mask
);
1238 *_flags
= newValue
& 0xf;
1243 PCI::_ReadBasicInfo(PCIDev
*dev
)
1247 if (_CreateVirtualBus(dev
->domain
, dev
->bus
, &virtualBus
) != B_OK
) {
1248 dprintf("PCI: CreateVirtualBus failed, domain %u, bus %u\n", dev
->domain
, dev
->bus
);
1252 dev
->info
.vendor_id
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1253 dev
->function
, PCI_vendor_id
, 2);
1254 dev
->info
.device_id
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1255 dev
->function
, PCI_device_id
, 2);
1256 dev
->info
.bus
= virtualBus
;
1257 dev
->info
.device
= dev
->device
;
1258 dev
->info
.function
= dev
->function
;
1259 dev
->info
.revision
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1260 dev
->function
, PCI_revision
, 1);
1261 dev
->info
.class_api
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1262 dev
->function
, PCI_class_api
, 1);
1263 dev
->info
.class_sub
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1264 dev
->function
, PCI_class_sub
, 1);
1265 dev
->info
.class_base
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1266 dev
->function
, PCI_class_base
, 1);
1267 dev
->info
.line_size
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1268 dev
->function
, PCI_line_size
, 1);
1269 dev
->info
.latency
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1270 dev
->function
, PCI_latency
, 1);
1271 // BeOS does not mask off the multifunction bit, developer must use
1272 // (header_type & PCI_header_type_mask)
1273 dev
->info
.header_type
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1274 dev
->function
, PCI_header_type
, 1);
1275 dev
->info
.bist
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1276 dev
->function
, PCI_bist
, 1);
1277 dev
->info
.reserved
= 0;
1282 PCI::_ReadHeaderInfo(PCIDev
*dev
)
1284 switch (dev
->info
.header_type
& PCI_header_type_mask
) {
1285 case PCI_header_type_generic
:
1287 // disable PCI device address decoding (io and memory) while BARs
1289 uint16 pcicmd
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1290 dev
->function
, PCI_command
, 2);
1291 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1293 pcicmd
& ~(PCI_command_io
| PCI_command_memory
));
1295 // get BAR size infos
1296 _GetRomBarInfo(dev
, PCI_rom_base
, &dev
->info
.u
.h0
.rom_base_pci
,
1297 &dev
->info
.u
.h0
.rom_size
);
1298 for (int i
= 0; i
< 6;) {
1299 size_t barSize
= _GetBarInfo(dev
, PCI_base_registers
+ 4 * i
,
1300 &dev
->info
.u
.h0
.base_registers_pci
[i
],
1301 &dev
->info
.u
.h0
.base_register_sizes
[i
],
1302 &dev
->info
.u
.h0
.base_register_flags
[i
],
1303 i
< 5 ? &dev
->info
.u
.h0
.base_registers_pci
[i
+ 1] : NULL
);
1304 dev
->info
.u
.h0
.base_registers
[i
] = (addr_t
)pci_ram_address(
1305 (void *)(addr_t
)dev
->info
.u
.h0
.base_registers_pci
[i
]);
1309 // restore PCI device address decoding
1310 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1311 PCI_command
, 2, pcicmd
);
1313 dev
->info
.u
.h0
.rom_base
= (addr_t
)pci_ram_address(
1314 (void *)(addr_t
)dev
->info
.u
.h0
.rom_base_pci
);
1316 dev
->info
.u
.h0
.cardbus_cis
= ReadConfig(dev
->domain
, dev
->bus
,
1317 dev
->device
, dev
->function
, PCI_cardbus_cis
, 4);
1318 dev
->info
.u
.h0
.subsystem_id
= ReadConfig(dev
->domain
, dev
->bus
,
1319 dev
->device
, dev
->function
, PCI_subsystem_id
, 2);
1320 dev
->info
.u
.h0
.subsystem_vendor_id
= ReadConfig(dev
->domain
,
1321 dev
->bus
, dev
->device
, dev
->function
, PCI_subsystem_vendor_id
, 2);
1322 dev
->info
.u
.h0
.interrupt_line
= ReadConfig(dev
->domain
, dev
->bus
,
1323 dev
->device
, dev
->function
, PCI_interrupt_line
, 1);
1324 dev
->info
.u
.h0
.interrupt_pin
= ReadConfig(dev
->domain
, dev
->bus
,
1325 dev
->device
, dev
->function
, PCI_interrupt_pin
, 1);
1326 dev
->info
.u
.h0
.min_grant
= ReadConfig(dev
->domain
, dev
->bus
,
1327 dev
->device
, dev
->function
, PCI_min_grant
, 1);
1328 dev
->info
.u
.h0
.max_latency
= ReadConfig(dev
->domain
, dev
->bus
,
1329 dev
->device
, dev
->function
, PCI_max_latency
, 1);
1333 case PCI_header_type_PCI_to_PCI_bridge
:
1335 // disable PCI device address decoding (io and memory) while BARs are modified
1336 uint16 pcicmd
= ReadConfig(dev
->domain
, dev
->bus
, dev
->device
,
1337 dev
->function
, PCI_command
, 2);
1338 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1340 pcicmd
& ~(PCI_command_io
| PCI_command_memory
));
1342 _GetRomBarInfo(dev
, PCI_bridge_rom_base
,
1343 &dev
->info
.u
.h1
.rom_base_pci
);
1344 for (int i
= 0; i
< 2;) {
1345 size_t barSize
= _GetBarInfo(dev
, PCI_base_registers
+ 4 * i
,
1346 &dev
->info
.u
.h1
.base_registers_pci
[i
],
1347 &dev
->info
.u
.h1
.base_register_sizes
[i
],
1348 &dev
->info
.u
.h1
.base_register_flags
[i
],
1349 i
< 5 ? &dev
->info
.u
.h1
.base_registers_pci
[i
+ 1] : NULL
);
1350 dev
->info
.u
.h1
.base_registers
[i
] = (addr_t
)pci_ram_address(
1351 (void *)(addr_t
)dev
->info
.u
.h1
.base_registers_pci
[i
]);
1355 // restore PCI device address decoding
1356 WriteConfig(dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1357 PCI_command
, 2, pcicmd
);
1359 dev
->info
.u
.h1
.rom_base
= (addr_t
)pci_ram_address(
1360 (void *)(addr_t
)dev
->info
.u
.h1
.rom_base_pci
);
1362 dev
->info
.u
.h1
.primary_bus
= ReadConfig(dev
->domain
, dev
->bus
,
1363 dev
->device
, dev
->function
, PCI_primary_bus
, 1);
1364 dev
->info
.u
.h1
.secondary_bus
= ReadConfig(dev
->domain
, dev
->bus
,
1365 dev
->device
, dev
->function
, PCI_secondary_bus
, 1);
1366 dev
->info
.u
.h1
.subordinate_bus
= ReadConfig(dev
->domain
,
1367 dev
->bus
, dev
->device
, dev
->function
, PCI_subordinate_bus
, 1);
1368 dev
->info
.u
.h1
.secondary_latency
= ReadConfig(dev
->domain
,
1369 dev
->bus
, dev
->device
, dev
->function
, PCI_secondary_latency
, 1);
1370 dev
->info
.u
.h1
.io_base
= ReadConfig(dev
->domain
, dev
->bus
,
1371 dev
->device
, dev
->function
, PCI_io_base
, 1);
1372 dev
->info
.u
.h1
.io_limit
= ReadConfig(dev
->domain
, dev
->bus
,
1373 dev
->device
, dev
->function
, PCI_io_limit
, 1);
1374 dev
->info
.u
.h1
.secondary_status
= ReadConfig(dev
->domain
,
1375 dev
->bus
, dev
->device
, dev
->function
, PCI_secondary_status
, 2);
1376 dev
->info
.u
.h1
.memory_base
= ReadConfig(dev
->domain
, dev
->bus
,
1377 dev
->device
, dev
->function
, PCI_memory_base
, 2);
1378 dev
->info
.u
.h1
.memory_limit
= ReadConfig(dev
->domain
, dev
->bus
,
1379 dev
->device
, dev
->function
, PCI_memory_limit
, 2);
1380 dev
->info
.u
.h1
.prefetchable_memory_base
= ReadConfig(dev
->domain
,
1381 dev
->bus
, dev
->device
, dev
->function
, PCI_prefetchable_memory_base
, 2);
1382 dev
->info
.u
.h1
.prefetchable_memory_limit
= ReadConfig(
1383 dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1384 PCI_prefetchable_memory_limit
, 2);
1385 dev
->info
.u
.h1
.prefetchable_memory_base_upper32
= ReadConfig(
1386 dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1387 PCI_prefetchable_memory_base_upper32
, 4);
1388 dev
->info
.u
.h1
.prefetchable_memory_limit_upper32
= ReadConfig(
1389 dev
->domain
, dev
->bus
, dev
->device
, dev
->function
,
1390 PCI_prefetchable_memory_limit_upper32
, 4);
1391 dev
->info
.u
.h1
.io_base_upper16
= ReadConfig(dev
->domain
,
1392 dev
->bus
, dev
->device
, dev
->function
, PCI_io_base_upper16
, 2);
1393 dev
->info
.u
.h1
.io_limit_upper16
= ReadConfig(dev
->domain
,
1394 dev
->bus
, dev
->device
, dev
->function
, PCI_io_limit_upper16
, 2);
1395 dev
->info
.u
.h1
.interrupt_line
= ReadConfig(dev
->domain
, dev
->bus
,
1396 dev
->device
, dev
->function
, PCI_interrupt_line
, 1);
1397 dev
->info
.u
.h1
.interrupt_pin
= ReadConfig(dev
->domain
, dev
->bus
,
1398 dev
->device
, dev
->function
, PCI_interrupt_pin
, 1);
1399 dev
->info
.u
.h1
.bridge_control
= ReadConfig(dev
->domain
, dev
->bus
,
1400 dev
->device
, dev
->function
, PCI_bridge_control
, 2);
1401 dev
->info
.u
.h1
.subsystem_id
= ReadConfig(dev
->domain
, dev
->bus
,
1402 dev
->device
, dev
->function
, PCI_sub_device_id_1
, 2);
1403 dev
->info
.u
.h1
.subsystem_vendor_id
= ReadConfig(dev
->domain
,
1404 dev
->bus
, dev
->device
, dev
->function
, PCI_sub_vendor_id_1
, 2);
1408 case PCI_header_type_cardbus
:
1410 // for testing only, not final:
1411 dev
->info
.u
.h2
.subsystem_id
= ReadConfig(dev
->domain
, dev
->bus
,
1412 dev
->device
, dev
->function
, PCI_sub_device_id_2
, 2);
1413 dev
->info
.u
.h2
.subsystem_vendor_id
= ReadConfig(dev
->domain
,
1414 dev
->bus
, dev
->device
, dev
->function
, PCI_sub_vendor_id_2
, 2);
1415 dev
->info
.u
.h2
.primary_bus
= ReadConfig(dev
->domain
, dev
->bus
,
1416 dev
->device
, dev
->function
, PCI_primary_bus_2
, 1);
1417 dev
->info
.u
.h2
.secondary_bus
= ReadConfig(dev
->domain
, dev
->bus
,
1418 dev
->device
, dev
->function
, PCI_secondary_bus_2
, 1);
1419 dev
->info
.u
.h2
.subordinate_bus
= ReadConfig(dev
->domain
,
1420 dev
->bus
, dev
->device
, dev
->function
, PCI_subordinate_bus_2
, 1);
1421 dev
->info
.u
.h2
.secondary_latency
= ReadConfig(dev
->domain
,
1422 dev
->bus
, dev
->device
, dev
->function
, PCI_secondary_latency_2
, 1);
1423 dev
->info
.u
.h2
.reserved
= 0;
1424 dev
->info
.u
.h2
.memory_base
= ReadConfig(dev
->domain
, dev
->bus
,
1425 dev
->device
, dev
->function
, PCI_memory_base0_2
, 4);
1426 dev
->info
.u
.h2
.memory_limit
= ReadConfig(dev
->domain
, dev
->bus
,
1427 dev
->device
, dev
->function
, PCI_memory_limit0_2
, 4);
1428 dev
->info
.u
.h2
.memory_base_upper32
= ReadConfig(dev
->domain
,
1429 dev
->bus
, dev
->device
, dev
->function
, PCI_memory_base1_2
, 4);
1430 dev
->info
.u
.h2
.memory_limit_upper32
= ReadConfig(dev
->domain
,
1431 dev
->bus
, dev
->device
, dev
->function
, PCI_memory_limit1_2
, 4);
1432 dev
->info
.u
.h2
.io_base
= ReadConfig(dev
->domain
, dev
->bus
,
1433 dev
->device
, dev
->function
, PCI_io_base0_2
, 4);
1434 dev
->info
.u
.h2
.io_limit
= ReadConfig(dev
->domain
, dev
->bus
,
1435 dev
->device
, dev
->function
, PCI_io_limit0_2
, 4);
1436 dev
->info
.u
.h2
.io_base_upper32
= ReadConfig(dev
->domain
,
1437 dev
->bus
, dev
->device
, dev
->function
, PCI_io_base1_2
, 4);
1438 dev
->info
.u
.h2
.io_limit_upper32
= ReadConfig(dev
->domain
,
1439 dev
->bus
, dev
->device
, dev
->function
, PCI_io_limit1_2
, 4);
1440 dev
->info
.u
.h2
.secondary_status
= ReadConfig(dev
->domain
,
1441 dev
->bus
, dev
->device
, dev
->function
, PCI_secondary_status_2
, 2);
1442 dev
->info
.u
.h2
.bridge_control
= ReadConfig(dev
->domain
,
1443 dev
->bus
, dev
->device
, dev
->function
, PCI_bridge_control_2
, 2);
1448 TRACE(("PCI: Header type unknown (0x%02x)\n", dev
->info
.header_type
));
1455 PCI::RefreshDeviceInfo()
1457 if (fRootBus
== NULL
)
1460 _RefreshDeviceInfo(fRootBus
);
1465 PCI::_RefreshDeviceInfo(PCIBus
*bus
)
1467 for (PCIDev
*dev
= bus
->child
; dev
; dev
= dev
->next
) {
1468 _ReadBasicInfo(dev
);
1469 _ReadHeaderInfo(dev
);
1470 #if defined(__INTEL__) || defined(__x86_64__)
1471 pci_read_arch_info(dev
);
1474 _RefreshDeviceInfo(dev
->child
);
1478 _RefreshDeviceInfo(bus
->next
);
1483 PCI::ReadConfig(uint8 domain
, uint8 bus
, uint8 device
, uint8 function
,
1484 uint16 offset
, uint8 size
, uint32
*value
)
1486 domain_data
*info
= _GetDomainData(domain
);
1490 if (device
> (info
->max_bus_devices
- 1)
1492 || (size
!= 1 && size
!= 2 && size
!= 4)
1493 || (size
== 2 && (offset
& 3) == 3)
1494 || (size
== 4 && (offset
& 3) != 0)) {
1495 dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
1496 domain
, bus
, device
, function
, offset
, size
);
1500 return (*info
->controller
->read_pci_config
)(info
->controller_cookie
, bus
,
1501 device
, function
, offset
, size
, value
);
1506 PCI::ReadConfig(uint8 domain
, uint8 bus
, uint8 device
, uint8 function
,
1507 uint16 offset
, uint8 size
)
1510 if (ReadConfig(domain
, bus
, device
, function
, offset
, size
, &value
)
1519 PCI::ReadConfig(PCIDev
*device
, uint16 offset
, uint8 size
)
1522 if (ReadConfig(device
->domain
, device
->bus
, device
->device
,
1523 device
->function
, offset
, size
, &value
) != B_OK
)
1531 PCI::WriteConfig(uint8 domain
, uint8 bus
, uint8 device
, uint8 function
,
1532 uint16 offset
, uint8 size
, uint32 value
)
1534 domain_data
*info
= _GetDomainData(domain
);
1538 if (device
> (info
->max_bus_devices
- 1)
1540 || (size
!= 1 && size
!= 2 && size
!= 4)
1541 || (size
== 2 && (offset
& 3) == 3)
1542 || (size
== 4 && (offset
& 3) != 0)) {
1543 dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
1544 domain
, bus
, device
, function
, offset
, size
);
1548 return (*info
->controller
->write_pci_config
)(info
->controller_cookie
, bus
,
1549 device
, function
, offset
, size
, value
);
1554 PCI::WriteConfig(PCIDev
*device
, uint16 offset
, uint8 size
, uint32 value
)
1556 return WriteConfig(device
->domain
, device
->bus
, device
->device
,
1557 device
->function
, offset
, size
, value
);
1562 PCI::FindCapability(uint8 domain
, uint8 bus
, uint8 device
, uint8 function
,
1563 uint8 capID
, uint8
*offset
)
1565 uint16 status
= ReadConfig(domain
, bus
, device
, function
, PCI_status
, 2);
1566 if (!(status
& PCI_status_capabilities
)) {
1567 FLOW("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x "
1568 "not supported\n", bus
, device
, function
, capID
);
1572 uint8 headerType
= ReadConfig(domain
, bus
, device
, function
,
1573 PCI_header_type
, 1);
1576 switch (headerType
& PCI_header_type_mask
) {
1577 case PCI_header_type_generic
:
1578 case PCI_header_type_PCI_to_PCI_bridge
:
1579 capPointer
= PCI_capabilities_ptr
;
1581 case PCI_header_type_cardbus
:
1582 capPointer
= PCI_capabilities_ptr_2
;
1585 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability "
1586 "%#02x unknown header type\n", bus
, device
, function
, capID
);
1590 capPointer
= ReadConfig(domain
, bus
, device
, function
, capPointer
, 1);
1592 if (capPointer
== 0) {
1593 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x "
1594 "empty list\n", bus
, device
, function
, capID
);
1595 return B_NAME_NOT_FOUND
;
1598 for (int i
= 0; i
< 48; i
++) {
1599 if (ReadConfig(domain
, bus
, device
, function
, capPointer
, 1) == capID
) {
1601 *offset
= capPointer
;
1605 capPointer
= ReadConfig(domain
, bus
, device
, function
, capPointer
+ 1,
1609 if (capPointer
== 0)
1610 return B_NAME_NOT_FOUND
;
1613 TRACE_CAP("PCI: find_pci_capability ERROR %u:%u:%u capability %#02x circular list\n", bus
, device
, function
, capID
);
1619 PCI::FindCapability(PCIDev
*device
, uint8 capID
, uint8
*offset
)
1621 return FindCapability(device
->domain
, device
->bus
, device
->device
,
1622 device
->function
, capID
, offset
);
1627 PCI::FindExtendedCapability(uint8 domain
, uint8 bus
, uint8 device
,
1628 uint8 function
, uint16 capID
, uint16
*offset
)
1630 if (FindCapability(domain
, bus
, device
, function
, PCI_cap_id_pcie
)
1632 FLOW("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#02x "
1633 "not supported\n", bus
, device
, function
, capID
);
1636 uint16 capPointer
= PCI_extended_capability
;
1637 uint32 capability
= ReadConfig(domain
, bus
, device
, function
,
1640 if (capability
== 0 || capability
== 0xffffffff)
1641 return B_NAME_NOT_FOUND
;
1643 for (int i
= 0; i
< 48; i
++) {
1644 if (PCI_extcap_id(capability
) == capID
) {
1646 *offset
= capPointer
;
1650 capPointer
= PCI_extcap_next_ptr(capability
) & ~3;
1651 if (capPointer
< PCI_extended_capability
)
1652 return B_NAME_NOT_FOUND
;
1653 capability
= ReadConfig(domain
, bus
, device
, function
,
1657 TRACE_CAP("PCI:FindExtendedCapability ERROR %u:%u:%u capability %#04x "
1658 "circular list\n", bus
, device
, function
, capID
);
1664 PCI::FindExtendedCapability(PCIDev
*device
, uint16 capID
, uint16
*offset
)
1666 return FindExtendedCapability(device
->domain
, device
->bus
, device
->device
,
1667 device
->function
, capID
, offset
);
1672 PCI::FindHTCapability(uint8 domain
, uint8 bus
, uint8 device
,
1673 uint8 function
, uint16 capID
, uint8
*offset
)
1676 // consider the passed offset as the current ht capability block pointer
1677 // when it's non zero
1678 if (offset
!= NULL
&& *offset
!= 0) {
1679 capPointer
= ReadConfig(domain
, bus
, device
, function
, *offset
+ 1,
1681 } else if (FindCapability(domain
, bus
, device
, function
, PCI_cap_id_ht
,
1682 &capPointer
) != B_OK
) {
1683 FLOW("PCI:FindHTCapability ERROR %u:%u:%u capability %#02x "
1684 "not supported\n", bus
, device
, function
, capID
);
1685 return B_NAME_NOT_FOUND
;
1688 uint16 mask
= PCI_ht_command_cap_mask_5_bits
;
1689 if (capID
== PCI_ht_command_cap_slave
|| capID
== PCI_ht_command_cap_host
)
1690 mask
= PCI_ht_command_cap_mask_3_bits
;
1691 for (int i
= 0; i
< 48; i
++) {
1693 if (capPointer
== 0)
1694 return B_NAME_NOT_FOUND
;
1696 uint8 capability
= ReadConfig(domain
, bus
, device
, function
,
1698 if (capability
== PCI_cap_id_ht
) {
1699 if ((ReadConfig(domain
, bus
, device
, function
,
1700 capPointer
+ PCI_ht_command
, 2) & mask
) == capID
) {
1702 *offset
= capPointer
;
1707 capPointer
= ReadConfig(domain
, bus
, device
, function
, capPointer
+ 1,
1711 TRACE_CAP("PCI:FindHTCapability ERROR %u:%u:%u capability %#04x "
1712 "circular list\n", bus
, device
, function
, capID
);
1718 PCI::FindHTCapability(PCIDev
*device
, uint16 capID
, uint8
*offset
)
1720 return FindHTCapability(device
->domain
, device
->bus
, device
->device
,
1721 device
->function
, capID
, offset
);
1726 PCI::FindDevice(uint8 domain
, uint8 bus
, uint8 device
, uint8 function
)
1728 return _FindDevice(fRootBus
, domain
, bus
, device
, function
);
1733 PCI::_FindDevice(PCIBus
*current
, uint8 domain
, uint8 bus
, uint8 device
,
1736 if (current
->domain
== domain
) {
1737 // search device on this bus
1739 for (PCIDev
*child
= current
->child
; child
!= NULL
;
1740 child
= child
->next
) {
1741 if (child
->bus
== bus
&& child
->device
== device
1742 && child
->function
== function
)
1745 if (child
->child
!= NULL
) {
1746 // search child busses
1747 PCIDev
*found
= _FindDevice(child
->child
, domain
, bus
, device
,
1755 // search other busses
1756 if (current
->next
!= NULL
)
1757 return _FindDevice(current
->next
, domain
, bus
, device
, function
);
1764 PCI::UpdateInterruptLine(uint8 domain
, uint8 bus
, uint8 _device
, uint8 function
,
1765 uint8 newInterruptLineValue
)
1767 PCIDev
*device
= FindDevice(domain
, bus
, _device
, function
);
1771 pci_info
&info
= device
->info
;
1772 switch (info
.header_type
& PCI_header_type_mask
) {
1773 case PCI_header_type_generic
:
1774 info
.u
.h0
.interrupt_line
= newInterruptLineValue
;
1777 case PCI_header_type_PCI_to_PCI_bridge
:
1778 info
.u
.h1
.interrupt_line
= newInterruptLineValue
;
1785 return WriteConfig(device
, PCI_interrupt_line
, 1, newInterruptLineValue
);