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
pci_root_register_device(device_node * parent)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
pci_root_traverse(device_node * node,PCIBus * bus)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
pci_root_register_child_devices(void * cookie)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
pci_root_init(device_node * node,void ** _cookie)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
pci_root_std_ops(int32 op,...)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