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