1 /* 2 * Copyright 2022, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #ifndef _ECAM_PCI_CONTROLLER_H_ 8 #define _ECAM_PCI_CONTROLLER_H_ 9 10 #include <bus/PCI.h> 11 #include <bus/FDT.h> 12 #include <ACPI.h> 13 14 #include <AutoDeleterOS.h> 15 #include <lock.h> 16 #include <util/Vector.h> 17 18 19 #define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;} 20 21 #define ECAM_PCI_DRIVER_MODULE_NAME "busses/pci/ecam/driver_v1" 22 23 24 enum { 25 fdtPciRangeConfig = 0x00000000, 26 fdtPciRangeIoPort = 0x01000000, 27 fdtPciRangeMmio32Bit = 0x02000000, 28 fdtPciRangeMmio64Bit = 0x03000000, 29 fdtPciRangeTypeMask = 0x03000000, 30 fdtPciRangeAliased = 0x20000000, 31 fdtPciRangePrefechable = 0x40000000, 32 fdtPciRangeRelocatable = 0x80000000, 33 }; 34 35 36 enum PciBarKind { 37 kRegIo, 38 kRegMmio32, 39 kRegMmio64, 40 kRegMmio1MB, 41 kRegUnknown, 42 }; 43 44 45 union PciAddress { 46 struct { 47 uint32 offset: 8; 48 uint32 function: 3; 49 uint32 device: 5; 50 uint32 bus: 8; 51 uint32 unused: 8; 52 }; 53 uint32 val; 54 }; 55 56 union PciAddressEcam { 57 struct { 58 uint32 offset: 12; 59 uint32 function: 3; 60 uint32 device: 5; 61 uint32 bus: 8; 62 uint32 unused: 4; 63 }; 64 uint32 val; 65 }; 66 67 struct RegisterRange { 68 phys_addr_t parentBase; 69 phys_addr_t childBase; 70 uint64 size; 71 }; 72 73 struct InterruptMapMask { 74 uint32_t childAdr; 75 uint32_t childIrq; 76 }; 77 78 struct InterruptMap { 79 uint32_t childAdr; 80 uint32_t childIrq; 81 uint32_t parentIrqCtrl; 82 uint32_t parentIrq; 83 }; 84 85 86 class ECAMPCIController { 87 public: 88 virtual ~ECAMPCIController() = default; 89 90 static float SupportsDevice(device_node* parent); 91 static status_t RegisterDevice(device_node* parent); 92 static status_t InitDriver(device_node* node, ECAMPCIController*& outDriver); 93 void UninitDriver(); 94 95 status_t ReadConfig( 96 uint8 bus, uint8 device, uint8 function, 97 uint16 offset, uint8 size, uint32 &value); 98 99 status_t WriteConfig( 100 uint8 bus, uint8 device, uint8 function, 101 uint16 offset, uint8 size, uint32 value); 102 103 status_t GetMaxBusDevices(int32& count); 104 105 status_t ReadIrq( 106 uint8 bus, uint8 device, uint8 function, 107 uint8 pin, uint8& irq); 108 109 status_t WriteIrq( 110 uint8 bus, uint8 device, uint8 function, 111 uint8 pin, uint8 irq); 112 113 status_t GetRange(uint32 index, pci_resource_range* range); 114 115 virtual status_t Finalize() = 0; 116 117 private: 118 inline addr_t ConfigAddress(uint8 bus, uint8 device, uint8 function, uint16 offset); 119 120 protected: 121 virtual status_t ReadResourceInfo() = 0; 122 123 protected: 124 struct mutex fLock = MUTEX_INITIALIZER("ECAM PCI"); 125 126 device_node* fNode{}; 127 128 AreaDeleter fRegsArea; 129 uint8 volatile* fRegs{}; 130 uint64 fRegsLen{}; 131 132 Vector<pci_resource_range> fResourceRanges; 133 }; 134 135 136 class ECAMPCIControllerACPI: public ECAMPCIController { 137 public: 138 ~ECAMPCIControllerACPI() = default; 139 140 status_t Finalize() final; 141 142 protected: 143 status_t ReadResourceInfo() final; 144 status_t ReadResourceInfo(device_node* parent); 145 146 uint8 fStartBusNumber{}; 147 uint8 fEndBusNumber{}; 148 149 private: 150 friend class X86PCIControllerMethPcie; 151 152 static acpi_status AcpiCrsScanCallback(acpi_resource *res, void *context); 153 inline acpi_status AcpiCrsScanCallbackInt(acpi_resource *res); 154 }; 155 156 157 class ECAMPCIControllerFDT: public ECAMPCIController { 158 public: 159 ~ECAMPCIControllerFDT() = default; 160 161 status_t Finalize() final; 162 163 protected: 164 status_t ReadResourceInfo() final; 165 166 private: 167 static void FinalizeInterrupts(fdt_device_module_info* fdtModule, 168 struct fdt_interrupt_map* interruptMap, int bus, int device, int function); 169 }; 170 171 172 extern device_manager_info* gDeviceManager; 173 extern pci_module_info* gPCI; 174 175 #endif // _ECAM_PCI_CONTROLLER_H_ 176