xref: /haiku/src/add-ons/kernel/busses/pci/ecam/ECAMPCIController.h (revision 1978089f7cec856677e46204e992c7273d70b9af)
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