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 "pci_private.h" 17 #include "pci.h" 18 19 20 // name of PCI root module 21 #define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/driver_v1" 22 23 24 device_node* gPCIRootNode = NULL; 25 26 27 static float 28 pci_root_supports_device(device_node* parent) 29 { 30 const char* bus; 31 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) < B_OK) 32 return -1.0f; 33 34 #if defined(__riscv) 35 if (strcmp(bus, "fdt") == 0) { 36 const char* compatible; 37 if (gDeviceManager->get_attr_string(parent, "fdt/compatible", &compatible, false) < B_OK) 38 return -1.0f; 39 40 if (strcmp(compatible, "pci-host-ecam-generic") == 0 41 || strcmp(compatible, "sifive,fu740-pcie") == 0) { 42 return 1.0f; 43 } 44 } 45 #elif defined(__arm__) || defined(__aarch64__) 46 if (strcmp(bus, "fdt") == 0) { 47 const char* compatible; 48 if (gDeviceManager->get_attr_string(parent, "fdt/compatible", &compatible, false) < B_OK) 49 return -1.0f; 50 51 if (strcmp(compatible, "pci-host-ecam-generic") == 0) 52 return 1.0f; 53 } 54 55 if (strcmp(bus, "acpi") == 0) { 56 const char* hid; 57 if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &hid, false) < B_OK) 58 return -1.0f; 59 60 if (strcmp(hid, "PNP0A03") == 0 || strcmp(hid, "PNP0A08") == 0) 61 return 1.0f; 62 } 63 #else 64 if (strcmp(bus, "root") == 0) 65 return 1.0f; 66 #endif 67 68 return 0.0; 69 } 70 71 72 static status_t 73 pci_root_register_device(device_node* parent) 74 { 75 // XXX how do we handle this for PPC? 76 // I/O port for PCI config space address 77 #define PCI_CONFIG_ADDRESS 0xcf8 78 79 io_resource resources[2] = { 80 {B_IO_PORT, PCI_CONFIG_ADDRESS, 8}, 81 {} 82 }; 83 device_attr attrs[] = { 84 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}}, 85 {B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_KEEP_DRIVER_LOADED}}, 86 {} 87 }; 88 89 return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs, 90 resources, NULL); 91 } 92 93 94 static status_t 95 pci_root_register_child_devices(void* cookie) 96 { 97 device_node* node = (device_node*)cookie; 98 99 pci_info info; 100 for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) { 101 uint8 domain; 102 uint8 bus; 103 if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) { 104 dprintf("ResolveVirtualBus(%u) failed\n", info.bus); 105 continue; 106 } 107 108 device_attr attrs[] = { 109 // info about device 110 {B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}}, 111 112 // location on PCI bus 113 {B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {ui8: domain}}, 114 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}}, 115 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: info.device}}, 116 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: info.function}}, 117 118 // info about the device 119 {B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { ui16: info.vendor_id }}, 120 {B_DEVICE_ID, B_UINT16_TYPE, { ui16: info.device_id }}, 121 122 {B_DEVICE_TYPE, B_UINT16_TYPE, { ui16: info.class_base }}, 123 {B_DEVICE_SUB_TYPE, B_UINT16_TYPE, { ui16: info.class_sub }}, 124 {B_DEVICE_INTERFACE, B_UINT16_TYPE, { ui16: info.class_api }}, 125 126 {B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}}, 127 {} 128 }; 129 130 gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs, 131 NULL, NULL); 132 } 133 134 return B_OK; 135 } 136 137 138 static status_t 139 pci_root_init(device_node* node, void** _cookie) 140 { 141 *_cookie = node; 142 143 gPCIRootNode = node; 144 145 module_info *module; 146 status_t res = get_module(B_PCI_MODULE_NAME, &module); 147 if (res < B_OK) 148 return res; 149 150 return pci_init_deferred(); 151 } 152 153 154 static int32 155 pci_root_std_ops(int32 op, ...) 156 { 157 switch (op) { 158 case B_MODULE_INIT: 159 return B_OK; 160 161 case B_MODULE_UNINIT: 162 return B_OK; 163 } 164 165 return B_BAD_VALUE; 166 } 167 168 169 struct pci_root_module_info gPCIRootModule = { 170 { 171 { 172 PCI_ROOT_MODULE_NAME, 173 0, 174 pci_root_std_ops 175 }, 176 177 pci_root_supports_device, 178 pci_root_register_device, 179 pci_root_init, 180 NULL, // uninit 181 pci_root_register_child_devices, 182 NULL, // rescan devices 183 NULL, // device removed 184 }, 185 186 &pci_read_config, 187 &pci_write_config 188 }; 189