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 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 status_t 51 pci_root_register_child_devices(void* cookie) 52 { 53 device_node* node = (device_node*)cookie; 54 55 pci_info info; 56 for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) { 57 uint8 domain; 58 uint8 bus; 59 if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) { 60 dprintf("ResolveVirtualBus(%u) failed\n", info.bus); 61 continue; 62 } 63 64 device_attr attrs[] = { 65 // info about device 66 {B_DEVICE_BUS, B_STRING_TYPE, {.string = "pci"}}, 67 68 // location on PCI bus 69 {B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {.ui8 = domain}}, 70 {B_PCI_DEVICE_BUS, B_UINT8_TYPE, {.ui8 = bus}}, 71 {B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {.ui8 = info.device}}, 72 {B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {.ui8 = info.function}}, 73 74 // info about the device 75 {B_DEVICE_VENDOR_ID, B_UINT16_TYPE, {.ui16 = info.vendor_id}}, 76 {B_DEVICE_ID, B_UINT16_TYPE, {.ui16 = info.device_id}}, 77 78 {B_DEVICE_TYPE, B_UINT16_TYPE, {.ui16 = info.class_base}}, 79 {B_DEVICE_SUB_TYPE, B_UINT16_TYPE, {.ui16 = info.class_sub}}, 80 {B_DEVICE_INTERFACE, B_UINT16_TYPE, {.ui16 = info.class_api}}, 81 82 {B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_CHILD_ON_DEMAND}}, 83 {} 84 }; 85 86 gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs, 87 NULL, NULL); 88 } 89 90 return B_OK; 91 } 92 93 94 static status_t 95 pci_root_init(device_node* node, void** _cookie) 96 { 97 *_cookie = node; 98 99 DeviceNodePutter<&gDeviceManager> pciHostNode(gDeviceManager->get_parent_node(node)); 100 101 pci_controller_module_info* pciHostModule; 102 void* pciHostDev; 103 CHECK_RET(gDeviceManager->get_driver(pciHostNode.Get(), (driver_module_info**)&pciHostModule, &pciHostDev)); 104 105 module_info *module; 106 status_t res = get_module(B_PCI_MODULE_NAME, &module); 107 if (res < B_OK) 108 return res; 109 110 CHECK_RET(gPCI->AddController(pciHostModule, pciHostDev, node)); 111 CHECK_RET(pci_init_deferred()); 112 113 return B_OK; 114 } 115 116 117 static int32 118 pci_root_std_ops(int32 op, ...) 119 { 120 switch (op) { 121 case B_MODULE_INIT: 122 return B_OK; 123 124 case B_MODULE_UNINIT: 125 return B_OK; 126 } 127 128 return B_BAD_VALUE; 129 } 130 131 132 struct pci_root_module_info gPCIRootModule = { 133 { 134 { 135 PCI_ROOT_MODULE_NAME, 136 0, 137 pci_root_std_ops 138 }, 139 140 NULL, 141 pci_root_register_device, 142 pci_root_init, 143 NULL, // uninit 144 pci_root_register_child_devices, 145 NULL, // rescan devices 146 NULL, // device removed 147 }, 148 149 &pci_read_config, 150 &pci_write_config 151 }; 152