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