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 void 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 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 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 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