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