xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_root.cpp (revision ef240bfffa9bd342a276eb73691a6996aa254156)
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 <AutoDeleterDrivers.h>
17 
18 #include "pci_private.h"
19 #include "pci.h"
20 
21 #define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
22 
23 
24 // name of PCI root module
25 #define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/driver_v1"
26 
27 
28 static status_t
29 pci_root_register_device(device_node* parent)
30 {
31 // XXX how do we handle this for PPC?
32 // I/O port for PCI config space address
33 #define PCI_CONFIG_ADDRESS 0xcf8
34 
35 	io_resource resources[2] = {
36 		{B_IO_PORT, PCI_CONFIG_ADDRESS, 8},
37 		{}
38 	};
39 	device_attr attrs[] = {
40 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "PCI"}},
41 		{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_KEEP_DRIVER_LOADED}},
42 		{}
43 	};
44 
45 	return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs,
46 		resources, NULL);
47 }
48 
49 
50 static status_t
51 pci_root_register_child_devices(void* cookie)
52 {
53 	device_node* node = (device_node*)cookie;
54 
55 	pci_info info;
56 	for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) {
57 		uint8 domain;
58 		uint8 bus;
59 		if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) {
60 			dprintf("ResolveVirtualBus(%u) failed\n", info.bus);
61 			continue;
62 		}
63 
64 		device_attr attrs[] = {
65 			// info about device
66 			{B_DEVICE_BUS, B_STRING_TYPE, {.string = "pci"}},
67 
68 			// location on PCI bus
69 			{B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {.ui8 = domain}},
70 			{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {.ui8 = bus}},
71 			{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {.ui8 = info.device}},
72 			{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {.ui8 = info.function}},
73 
74 			// info about the device
75 			{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, {.ui16 = info.vendor_id}},
76 			{B_DEVICE_ID, B_UINT16_TYPE, {.ui16 = info.device_id}},
77 
78 			{B_DEVICE_TYPE, B_UINT16_TYPE, {.ui16 = info.class_base}},
79 			{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, {.ui16 = info.class_sub}},
80 			{B_DEVICE_INTERFACE, B_UINT16_TYPE, {.ui16 = info.class_api}},
81 
82 			{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_CHILD_ON_DEMAND}},
83 			{}
84 		};
85 
86 		gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs,
87 			NULL, NULL);
88 	}
89 
90 	return B_OK;
91 }
92 
93 
94 static status_t
95 pci_root_init(device_node* node, void** _cookie)
96 {
97 	*_cookie = node;
98 
99 	DeviceNodePutter<&gDeviceManager> pciHostNode(gDeviceManager->get_parent_node(node));
100 
101 	pci_controller_module_info* pciHostModule;
102 	void* pciHostDev;
103 	CHECK_RET(gDeviceManager->get_driver(pciHostNode.Get(), (driver_module_info**)&pciHostModule, &pciHostDev));
104 
105 	module_info *module;
106 	status_t res = get_module(B_PCI_MODULE_NAME, &module);
107 	if (res < B_OK)
108 		return res;
109 
110 	CHECK_RET(gPCI->AddController(pciHostModule, pciHostDev, node));
111 	CHECK_RET(pci_init_deferred());
112 
113 	return B_OK;
114 }
115 
116 
117 static int32
118 pci_root_std_ops(int32 op, ...)
119 {
120 	switch (op) {
121 		case B_MODULE_INIT:
122 			return B_OK;
123 
124 		case B_MODULE_UNINIT:
125 			return B_OK;
126 	}
127 
128 	return B_BAD_VALUE;
129 }
130 
131 
132 struct pci_root_module_info gPCIRootModule = {
133 	{
134 		{
135 			PCI_ROOT_MODULE_NAME,
136 			0,
137 			pci_root_std_ops
138 		},
139 
140 		NULL,
141 		pci_root_register_device,
142 		pci_root_init,
143 		NULL,	// uninit
144 		pci_root_register_child_devices,
145 		NULL,	// rescan devices
146 		NULL,	// device removed
147 	},
148 
149 	&pci_read_config,
150 	&pci_write_config
151 };
152