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