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