xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_root.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 // XXX how do we handle this for PPC?
59 // I/O port for PCI config space address
60 #define PCI_CONFIG_ADDRESS 0xcf8
61 
62 	io_resource resources[2] = {
63 		{B_IO_PORT, PCI_CONFIG_ADDRESS, 8},
64 		{}
65 	};
66 	device_attr attrs[] = {
67 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}},
68 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_KEEP_DRIVER_LOADED}},
69 		{}
70 	};
71 
72 	return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs,
73 		resources, NULL);
74 }
75 
76 
77 static status_t
78 pci_root_register_child_devices(void* cookie)
79 {
80 	device_node* node = (device_node*)cookie;
81 
82 	pci_info info;
83 	for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) {
84 		uint8 domain;
85 		uint8 bus;
86 		if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) {
87 			dprintf("ResolveVirtualBus(%u) failed\n", info.bus);
88 			continue;
89 		}
90 
91 		device_attr attrs[] = {
92 			// info about device
93 			{B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}},
94 
95 			// location on PCI bus
96 			{B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {ui8: domain}},
97 			{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}},
98 			{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: info.device}},
99 			{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: info.function}},
100 
101 			// info about the device
102 			{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { ui16: info.vendor_id }},
103 			{B_DEVICE_ID, B_UINT16_TYPE, { ui16: info.device_id }},
104 
105 			{B_DEVICE_TYPE, B_UINT16_TYPE, { ui16: info.class_base }},
106 			{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, { ui16: info.class_sub }},
107 			{B_DEVICE_INTERFACE, B_UINT16_TYPE, { ui16: info.class_api }},
108 
109 			{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}},
110 			{}
111 		};
112 
113 		gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs,
114 			NULL, NULL);
115 	}
116 
117 	return B_OK;
118 }
119 
120 
121 static status_t
122 pci_root_init(device_node* node, void** _cookie)
123 {
124 	*_cookie = node;
125 
126 	gPCIRootNode = node;
127 
128 	module_info *module;
129 	status_t res = get_module(B_PCI_MODULE_NAME, &module);
130 	if (res < B_OK)
131 		return res;
132 
133 	return B_OK;
134 }
135 
136 
137 static int32
138 pci_root_std_ops(int32 op, ...)
139 {
140 	switch (op) {
141 		case B_MODULE_INIT:
142 			return B_OK;
143 
144 		case B_MODULE_UNINIT:
145 			return B_OK;
146 	}
147 
148 	return B_BAD_VALUE;
149 }
150 
151 
152 struct pci_root_module_info gPCIRootModule = {
153 	{
154 		{
155 			PCI_ROOT_MODULE_NAME,
156 			0,
157 			pci_root_std_ops
158 		},
159 
160 		pci_root_supports_device,
161 		pci_root_register_device,
162 		pci_root_init,
163 		NULL,	// uninit
164 		pci_root_register_child_devices,
165 		NULL,	// rescan devices
166 		NULL,	// device removed
167 	},
168 
169 	&pci_read_config,
170 	&pci_write_config
171 };
172