xref: /haiku/src/add-ons/kernel/bus_managers/pci/pci_root.cpp (revision 3634f142352af2428aed187781fc9d75075e9140)
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 void
51 pci_root_traverse(device_node* node, PCIBus* bus)
52 {
53 	for (PCIDev* dev = bus->child; dev != NULL; dev = dev->next) {
54 		const pci_info& info = dev->info;
55 
56 		device_attr attrs[] = {
57 			// info about device
58 			{B_DEVICE_BUS, B_STRING_TYPE, {.string = "pci"}},
59 
60 			// location on PCI bus
61 			{B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {.ui8 = dev->domain}},
62 			{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {.ui8 = dev->bus}},
63 			{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {.ui8 = info.device}},
64 			{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {.ui8 = info.function}},
65 
66 			// info about the device
67 			{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, {.ui16 = info.vendor_id}},
68 			{B_DEVICE_ID, B_UINT16_TYPE, {.ui16 = info.device_id}},
69 
70 			{B_DEVICE_TYPE, B_UINT16_TYPE, {.ui16 = info.class_base}},
71 			{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, {.ui16 = info.class_sub}},
72 			{B_DEVICE_INTERFACE, B_UINT16_TYPE, {.ui16 = info.class_api}},
73 
74 			{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_CHILD_ON_DEMAND}},
75 			{}
76 		};
77 
78 		gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
79 
80 		if (dev->child != NULL)
81 			pci_root_traverse(node, dev->child);
82 	}
83 }
84 
85 
86 static status_t
87 pci_root_register_child_devices(void* cookie)
88 {
89 	domain_data* domainData = (domain_data*)cookie;
90 
91 	pci_root_traverse(domainData->root_node, domainData->bus);
92 
93 	return B_OK;
94 }
95 
96 
97 static status_t
98 pci_root_init(device_node* node, void** _cookie)
99 {
100 	DeviceNodePutter<&gDeviceManager> pciHostNode(gDeviceManager->get_parent_node(node));
101 
102 	pci_controller_module_info* pciHostModule;
103 	void* pciHostDev;
104 	CHECK_RET(gDeviceManager->get_driver(pciHostNode.Get(), (driver_module_info**)&pciHostModule, &pciHostDev));
105 
106 	module_info *module;
107 	status_t res = get_module(B_PCI_MODULE_NAME, &module);
108 	if (res < B_OK)
109 		return res;
110 
111 	domain_data* domainData = NULL;
112 	CHECK_RET(gPCI->AddController(pciHostModule, pciHostDev, node, &domainData));
113 
114 	*_cookie = domainData;
115 
116 	return B_OK;
117 }
118 
119 
120 static int32
121 pci_root_std_ops(int32 op, ...)
122 {
123 	switch (op) {
124 		case B_MODULE_INIT:
125 			return B_OK;
126 
127 		case B_MODULE_UNINIT:
128 			return B_OK;
129 	}
130 
131 	return B_BAD_VALUE;
132 }
133 
134 
135 struct pci_root_module_info gPCIRootModule = {
136 	{
137 		{
138 			PCI_ROOT_MODULE_NAME,
139 			0,
140 			pci_root_std_ops
141 		},
142 
143 		NULL,
144 		pci_root_register_device,
145 		pci_root_init,
146 		NULL,	// uninit
147 		pci_root_register_child_devices,
148 		NULL,	// rescan devices
149 		NULL,	// device removed
150 	},
151 
152 	&pci_read_config,
153 	&pci_write_config
154 };
155