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