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