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