1 /* 2 * Copyright 2003-2008, Marcus Overhagen. All rights reserved. 3 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 #ifndef __PCI_H__ 8 #define __PCI_H__ 9 10 #include <bus/PCI.h> 11 12 #include <VectorMap.h> 13 14 #include "pci_msi.h" 15 16 17 #define TRACE_PCI 18 #ifndef TRACE_PCI 19 # define TRACE(x) 20 #else 21 # define TRACE(x) dprintf x 22 #endif 23 24 struct PCIDev; 25 26 struct PCIBus { 27 PCIDev * parent; 28 PCIDev * child; 29 uint8 domain; 30 uint8 bus; 31 }; 32 33 struct PCIDev { 34 PCIDev * next; 35 PCIBus * parent; 36 PCIBus * child; 37 uint8 domain; 38 uint8 bus; 39 uint8 device; 40 uint8 function; 41 pci_info info; 42 43 msi_info msi; 44 msix_info msix; 45 ht_mapping_info ht_mapping; 46 }; 47 48 49 struct domain_data { 50 ~domain_data() 51 { 52 #if !(defined(__i386__) || defined(__x86_64__)) 53 if (io_port_area >= 0) 54 delete_area(io_port_area); 55 #endif 56 } 57 58 // These two are set in PCI::AddController: 59 pci_controller_module_info *controller; 60 void * controller_cookie; 61 device_node * root_node; 62 PCIBus * bus; 63 64 // All the rest is set in PCI::InitDomainData 65 int max_bus_devices; 66 Vector<pci_resource_range> ranges; 67 68 #if !(defined(__i386__) || defined(__x86_64__)) 69 area_id io_port_area = -1; 70 uint8 * io_port_adr = NULL; 71 #endif 72 }; 73 74 75 class PCI { 76 public: 77 PCI(); 78 ~PCI(); 79 80 void InitDomainData(domain_data &data); 81 void InitBus(PCIBus *bus); 82 83 status_t AddController(pci_controller_module_info *controller, 84 void *controllerCookie, device_node *rootNode, 85 domain_data **domainData); 86 87 status_t LookupRange(uint32 type, phys_addr_t pciAddr, 88 uint8 &domain, pci_resource_range &range, uint8 **mappedAdr = NULL); 89 90 status_t GetNthInfo(long index, pci_info *outInfo); 91 92 status_t ReadConfig(uint8 domain, uint8 bus, uint8 device, 93 uint8 function, uint16 offset, uint8 size, 94 uint32 *value); 95 uint32 ReadConfig(uint8 domain, uint8 bus, uint8 device, 96 uint8 function, uint16 offset, uint8 size); 97 uint32 ReadConfig(PCIDev *device, uint16 offset, 98 uint8 size); 99 100 status_t WriteConfig(uint8 domain, uint8 bus, uint8 device, 101 uint8 function, uint16 offset, uint8 size, 102 uint32 value); 103 status_t WriteConfig(PCIDev *device, uint16 offset, 104 uint8 size, uint32 value); 105 106 status_t FindCapability(uint8 domain, uint8 bus, 107 uint8 device, uint8 function, uint8 capID, 108 uint8 *offset = NULL); 109 status_t FindCapability(PCIDev *device, uint8 capID, 110 uint8 *offset = NULL); 111 status_t FindExtendedCapability(uint8 domain, uint8 bus, 112 uint8 device, uint8 function, uint16 capID, 113 uint16 *offset = NULL); 114 status_t FindExtendedCapability(PCIDev *device, 115 uint16 capID, uint16 *offset = NULL); 116 status_t FindHTCapability(uint8 domain, uint8 bus, 117 uint8 device, uint8 function, uint16 capID, 118 uint8 *offset); 119 status_t FindHTCapability(PCIDev *device, 120 uint16 capID, uint8 *offset = NULL); 121 122 status_t ResolveVirtualBus(uint8 virtualBus, uint8 *domain, 123 uint8 *bus); 124 125 PCIDev * FindDevice(uint8 domain, uint8 bus, uint8 device, 126 uint8 function); 127 128 void ClearDeviceStatus(PCIBus *bus, bool dumpStatus); 129 130 uint8 GetPowerstate(PCIDev *device); 131 status_t GetPowerstate(uint8 domain, uint8 bus, uint8 device, 132 uint8 function, uint8* state); 133 void SetPowerstate(PCIDev *device, uint8 state); 134 status_t SetPowerstate(uint8 domain, uint8 bus, uint8 device, 135 uint8 function, uint8 newState); 136 137 void RefreshDeviceInfo(); 138 139 status_t UpdateInterruptLine(uint8 domain, uint8 bus, 140 uint8 device, uint8 function, 141 uint8 newInterruptLineValue); 142 143 uint32 GetMSICount(PCIDev *device); 144 status_t ConfigureMSI(PCIDev *device, uint32 count, uint32 *startVector); 145 status_t UnconfigureMSI(PCIDev *device); 146 status_t EnableMSI(PCIDev *device); 147 status_t DisableMSI(PCIDev *device); 148 uint32 GetMSIXCount(PCIDev *device); 149 status_t ConfigureMSIX(PCIDev *device, uint32 count, uint32 *startVector); 150 status_t EnableMSIX(PCIDev *device); 151 152 private: 153 void _EnumerateBus(uint8 domain, uint8 bus, 154 uint8 *subordinateBus = NULL); 155 156 void _FixupDevices(uint8 domain, uint8 bus); 157 158 void _DiscoverBus(PCIBus *bus); 159 void _DiscoverDevice(PCIBus *bus, uint8 dev, 160 uint8 function); 161 162 PCIDev * _CreateDevice(PCIBus *parent, uint8 dev, 163 uint8 function); 164 PCIBus * _CreateBus(PCIDev *parent, uint8 domain, 165 uint8 bus); 166 167 status_t _GetNthInfo(PCIBus *bus, long *currentIndex, 168 long wantIndex, pci_info *outInfo); 169 void _ReadBasicInfo(PCIDev *dev); 170 void _ReadHeaderInfo(PCIDev *dev); 171 172 void _ConfigureBridges(PCIBus *bus); 173 void _RefreshDeviceInfo(PCIBus *bus); 174 175 uint64 _BarSize(uint64 bits); 176 size_t _GetBarInfo(PCIDev *dev, uint8 offset, 177 uint32 &ramAddress, uint32 &pciAddress, 178 uint32 &size, uint8 &flags, 179 uint32 *highRAMAddress = NULL, 180 uint32 *highPCIAddress = NULL, 181 uint32 *highSize = NULL); 182 void _GetRomBarInfo(PCIDev *dev, uint8 offset, 183 uint32 &address, uint32 *size = NULL, 184 uint8 *flags = NULL); 185 186 public: 187 domain_data * _GetDomainData(uint8 domain); 188 189 private: 190 status_t _CreateVirtualBus(uint8 domain, uint8 bus, 191 uint8 *virtualBus); 192 193 int _NumFunctions(uint8 domain, uint8 bus, 194 uint8 device); 195 PCIDev * _FindDevice(PCIBus *current, uint8 domain, 196 uint8 bus, uint8 device, uint8 function); 197 198 void _HtMSIMap(PCIDev *device, uint64 address); 199 void _ReadMSIInfo(PCIDev *device); 200 void _ReadMSIXInfo(PCIDev *device); 201 void _ReadHtMappingInfo(PCIDev *device); 202 status_t _UnconfigureMSIX(PCIDev *device); 203 status_t _DisableMSIX(PCIDev *device); 204 205 private: 206 enum { MAX_PCI_DOMAINS = 8 }; 207 208 domain_data fDomainData[MAX_PCI_DOMAINS]; 209 uint8 fDomainCount; 210 bool fBusEnumeration; 211 212 typedef VectorMap<uint8, uint16> VirtualBusMap; 213 214 VirtualBusMap fVirtualBusMap; 215 int fNextVirtualBus; 216 }; 217 218 extern PCI *gPCI; 219 220 221 extern "C" { 222 223 status_t pci_init(void); 224 status_t pci_init_deferred(void); 225 void pci_uninit(void); 226 227 long pci_get_nth_pci_info(long index, pci_info *outInfo); 228 229 uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, 230 uint16 offset, uint8 size); 231 void pci_write_config(uint8 virtualBus, uint8 device, uint8 function, 232 uint16 offset, uint8 size, uint32 value); 233 234 void __pci_resolve_virtual_bus(uint8 virtualBus, uint8 *domain, uint8 *bus); 235 236 } 237 238 #endif /* __PCI_H__ */ 239