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