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