xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_root.cpp (revision c6e67432610771fa8d2a9df9ad5f1543107e043a)
1 /*
2  * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Copyright 2003, Marcus Overhagen. All rights reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 
9 #include <device_manager.h>
10 #include <PCI.h>
11 #include <drivers/ACPI.h>
12 #include <drivers/bus/FDT.h>
13 
14 #include <string.h>
15 
16 #include "pci_private.h"
17 #include "pci.h"
18 
19 
20 // name of PCI root module
21 #define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/driver_v1"
22 
23 
24 device_node* gPCIRootNode = NULL;
25 
26 
27 static float
28 pci_root_supports_device(device_node* parent)
29 {
30 	const char* bus;
31 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) < B_OK)
32 		return -1.0f;
33 
34 #if defined(__riscv)
35 	if (strcmp(bus, "fdt") == 0) {
36 		const char* compatible;
37 		if (gDeviceManager->get_attr_string(parent, "fdt/compatible", &compatible, false) < B_OK)
38 			return -1.0f;
39 
40 		if (strcmp(compatible, "pci-host-ecam-generic") == 0
41 			|| strcmp(compatible, "sifive,fu740-pcie") == 0) {
42 			return 1.0f;
43 		}
44 	}
45 #elif defined(__aarch64__)
46 	if (strcmp(bus, "acpi") == 0) {
47 		const char* hid;
48 		if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &hid, false) < B_OK)
49 			return -1.0f;
50 
51 		if (strcmp(hid, "PNP0A03") == 0 || strcmp(hid, "PNP0A08") == 0)
52 			return 1.0f;
53 	}
54 #else
55 	if (strcmp(bus, "root") == 0)
56 		return 1.0f;
57 #endif
58 
59 	return 0.0;
60 }
61 
62 
63 static status_t
64 pci_root_register_device(device_node* parent)
65 {
66 // XXX how do we handle this for PPC?
67 // I/O port for PCI config space address
68 #define PCI_CONFIG_ADDRESS 0xcf8
69 
70 	io_resource resources[2] = {
71 		{B_IO_PORT, PCI_CONFIG_ADDRESS, 8},
72 		{}
73 	};
74 	device_attr attrs[] = {
75 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}},
76 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_KEEP_DRIVER_LOADED}},
77 		{}
78 	};
79 
80 	return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs,
81 		resources, NULL);
82 }
83 
84 
85 static status_t
86 pci_root_register_child_devices(void* cookie)
87 {
88 	device_node* node = (device_node*)cookie;
89 
90 	pci_info info;
91 	for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) {
92 		uint8 domain;
93 		uint8 bus;
94 		if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) {
95 			dprintf("ResolveVirtualBus(%u) failed\n", info.bus);
96 			continue;
97 		}
98 
99 		device_attr attrs[] = {
100 			// info about device
101 			{B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}},
102 
103 			// location on PCI bus
104 			{B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {ui8: domain}},
105 			{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}},
106 			{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: info.device}},
107 			{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: info.function}},
108 
109 			// info about the device
110 			{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { ui16: info.vendor_id }},
111 			{B_DEVICE_ID, B_UINT16_TYPE, { ui16: info.device_id }},
112 
113 			{B_DEVICE_TYPE, B_UINT16_TYPE, { ui16: info.class_base }},
114 			{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, { ui16: info.class_sub }},
115 			{B_DEVICE_INTERFACE, B_UINT16_TYPE, { ui16: info.class_api }},
116 
117 			{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}},
118 			{}
119 		};
120 
121 		gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs,
122 			NULL, NULL);
123 	}
124 
125 	return B_OK;
126 }
127 
128 
129 static status_t
130 pci_root_init(device_node* node, void** _cookie)
131 {
132 	*_cookie = node;
133 
134 	gPCIRootNode = node;
135 
136 	module_info *module;
137 	status_t res = get_module(B_PCI_MODULE_NAME, &module);
138 	if (res < B_OK)
139 		return res;
140 
141 	return pci_init_deferred();
142 }
143 
144 
145 static int32
146 pci_root_std_ops(int32 op, ...)
147 {
148 	switch (op) {
149 		case B_MODULE_INIT:
150 			return B_OK;
151 
152 		case B_MODULE_UNINIT:
153 			return B_OK;
154 	}
155 
156 	return B_BAD_VALUE;
157 }
158 
159 
160 struct pci_root_module_info gPCIRootModule = {
161 	{
162 		{
163 			PCI_ROOT_MODULE_NAME,
164 			0,
165 			pci_root_std_ops
166 		},
167 
168 		pci_root_supports_device,
169 		pci_root_register_device,
170 		pci_root_init,
171 		NULL,	// uninit
172 		pci_root_register_child_devices,
173 		NULL,	// rescan devices
174 		NULL,	// device removed
175 	},
176 
177 	&pci_read_config,
178 	&pci_write_config
179 };
180