forked from kolasa/fglrx-13.250
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkcl_pci.c
336 lines (305 loc) · 10.2 KB
/
kcl_pci.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/****************************************************************************
* *
* Copyright 1999-2005 ATI Technologies Inc., Markham, Ontario, CANADA. *
* All Rights Reserved. *
* *
* Your use and or redistribution of this software in source and \ or *
* binary form, with or without modification, is subject to: (i) your *
* ongoing acceptance of and compliance with the terms and conditions of *
* the ATI Technologies Inc. software End User License Agreement; and (ii) *
* your inclusion of this notice in any version of this software that you *
* use or redistribute. A copy of the ATI Technologies Inc. software End *
* User License Agreement is included with this software and is also *
* available by contacting ATI Technologies Inc. at http://www.ati.com *
* *
****************************************************************************/
/** \brief KCL PCI interface implementation
*
* CONVENTIONS
*
* Public symbols:
* - prefixed with KCL_PCI
* - are not static
* - declared in the corresponding header
*
* Private symbols:
* - prefixed with kcl
* - are static
* - not declared in the corresponding header
*
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
#include <generated/autoconf.h>
#else
#include <linux/autoconf.h>
#endif
#include <linux/pci.h>
#include "kcl_config.h"
#include "kcl_type.h"
#include "kcl_pci.h"
/** \brief Return info about PCI device at specified BDF
* Check presence of a PCI device at the specified (bus,device,function) triad
* and return vendor ID, device ID and IRQ number for this device
* (if corresponding pointers are provided by the caller)
** \param busnum [in] PCI bus number
** \param devnum [in] PCI device number
** \param funcnum [in] PCI function number
** \param vendor [out] Pointer to PCI vendor ID
** \param device [out] Pointer to PCI device ID
** \param irq [out] Pointer to PCI IRQ number
** \return 0 if the device is not found, 1 otherwise
*/
int ATI_API_CALL KCL_PCI_CheckBDF(
int busnum, int devnum, int funcnum,
KCL_TYPE_U16* vendor, KCL_TYPE_U16* device, unsigned int* irq)
{
struct pci_dev* pci_dev;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
pci_dev = pci_get_bus_and_slot(busnum, PCI_DEVFN(devnum, funcnum));
#else
pci_dev = pci_find_slot(busnum, PCI_DEVFN(devnum, funcnum));
#endif
if (!pci_dev)
{
return 0;
}
if (vendor)
{
*vendor = pci_dev->vendor;
}
if (device)
{
*device = pci_dev->device;
}
if (irq)
{
*irq = pci_dev->irq;
}
return 1;
}
/** \brief Get PCI device handle
** \param bus [in] PCI bus
** \param slot [in] PCI slot
** \return PCI device handle
*/
KCL_PCI_DevHandle ATI_API_CALL KCL_PCI_GetDevHandle(
KCL_TYPE_U32 bus, KCL_TYPE_U32 slot)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
return (KCL_PCI_DevHandle)pci_get_bus_and_slot(bus, slot);
#else
return (KCL_PCI_DevHandle)pci_find_slot(bus, slot);
#endif
}
/** \brief Get PCI device bus number
** \param pcidev [in] PCI device handle
** \return PCI device bus number
*/
KCL_TYPE_U8 ATI_API_CALL KCL_PCI_GetBusNumber(KCL_PCI_DevHandle pcidev)
{
struct pci_dev* dev = (struct pci_dev*)pcidev;
return dev->bus->number;
}
/** \brief Get PCI device function number
** \param pcidev [in] PCI device handle
** \return PCI device function number
*/
unsigned int ATI_API_CALL KCL_PCI_GetFunc(KCL_PCI_DevHandle pcidev)
{
struct pci_dev* dev = (struct pci_dev*)pcidev;
return PCI_FUNC(dev->devfn);
}
/** \brief Get PCI device IRQ number
** \param pcidev [in] PCI device handle
** \return PCI device IRQ number
*/
unsigned int ATI_API_CALL KCL_PCI_GetIRQ(KCL_PCI_DevHandle pcidev)
{
struct pci_dev* dev = (struct pci_dev*)pcidev;
return dev->irq;
}
/** \brief Get PCI device slot number
** \param pcidev [in] PCI device handle
** \return PCI device slot number
*/
unsigned int ATI_API_CALL KCL_PCI_GetSlot(KCL_PCI_DevHandle pcidev)
{
struct pci_dev* dev = (struct pci_dev*)pcidev;
return PCI_SLOT(dev->devfn);
}
/** \brief Read byte from PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val_ptr [out] Pointer to where to save register value
** \return TBD
*/
int ATI_API_CALL KCL_PCI_ReadConfigByte(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U8* val_ptr)
{
return pci_read_config_byte((struct pci_dev*)dev, where, val_ptr);
}
/** \brief Read 2-byte word from PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val_ptr [out] Pointer to where to save register value
** \return TBD
*/
int ATI_API_CALL KCL_PCI_ReadConfigWord(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U16* val_ptr)
{
return pci_read_config_word((struct pci_dev*)dev, where, val_ptr);
}
/** \brief Read 4-byte dword from PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val_ptr [out] Pointer to where to save register value
** \return TBD
*/
int ATI_API_CALL KCL_PCI_ReadConfigDword(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U32* val_ptr)
{
return pci_read_config_dword((struct pci_dev*)dev, where, val_ptr);
}
/** \brief Write byte to PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val [in] Value to write
** \return TBD
*/
int ATI_API_CALL KCL_PCI_WriteConfigByte(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U8 val)
{
return pci_write_config_byte((struct pci_dev*)dev, where, val);
}
/** \brief Write 2-byte word to PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val [in] Value to write
** \return TBD
*/
int ATI_API_CALL KCL_PCI_WriteConfigWord(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U16 val)
{
return pci_write_config_word((struct pci_dev*)dev, where, val);
}
/** \brief Write 4-byte dword to PCI config space
** \param pcidev [in] PCI device handle
** \param where [in] PCI register
** \param val [in] Value to write
** \return TBD
*/
int ATI_API_CALL KCL_PCI_WriteConfigDword(
KCL_PCI_DevHandle dev, KCL_TYPE_U8 where, KCL_TYPE_U32 val)
{
return pci_write_config_dword((struct pci_dev*)dev, where, val);
}
/** \brief Get base address of specified PCI BAR
** \param dev [in] PCI device handle
** \param res [in] PCI BAR index
** \return Base address of specified PCI BAR
*/
unsigned long ATI_API_CALL KCL_PCI_BAR_GetBase(
KCL_PCI_DevHandle dev, unsigned int res)
{
return pci_resource_start((struct pci_dev*)dev, res);
}
/** \brief Get address range of specified PCI BAR
** \param dev [in] PCI device handle
** \param res [in] PCI BAR index
** \return Address range of specified PCI BAR
*/
unsigned long ATI_API_CALL KCL_PCI_BAR_GetSize(
KCL_PCI_DevHandle dev, unsigned int res)
{
return pci_resource_len((struct pci_dev*)dev, res);
}
/** \brief Check if it is IO BAR
** \param dev [in] PCI device handle
** \param res [in] PCI BAR index
** \return non-zero for IO BAR
*/
unsigned int ATI_API_CALL KCL_PCI_BAR_IS_IO(
KCL_PCI_DevHandle dev, unsigned int res)
{
return pci_resource_flags((struct pci_dev*)dev, res) & IORESOURCE_IO;
}
/** \brief Check if it is 64bit MEM BAR
** \param dev [in] PCI device handle
** \param res [in] PCI BAR index
** \return non-zero for 64bit BAR
*/
unsigned int ATI_API_CALL KCL_PCI_BAR_IS_MEM64(
KCL_PCI_DevHandle dev, unsigned int res)
{
return pci_resource_flags((struct pci_dev*)dev, res) & IORESOURCE_MEM_64;
}
/** \brief Check if it is prefetchable
** \param dev [in] PCI device handle
** \param res [in] PCI BAR index
** \return non-zero for prefetchable
*/
unsigned int ATI_API_CALL KCL_PCI_BAR_IS_PREFETCHABLE(
KCL_PCI_DevHandle dev, unsigned int res)
{
return pci_resource_flags((struct pci_dev*)dev, res) & IORESOURCE_PREFETCH;
}
/** \brief Enable PCI device
** \param dev [in] PCI device handle
** \return 0 on success, nonzero otherwise
*/
int ATI_API_CALL KCL_PCI_EnableDevice(KCL_PCI_DevHandle dev)
{
return (pci_enable_device((struct pci_dev*)dev));
}
/** \brief Tell OS to enable bus mastering for the specified PCI device
** \param dev [in] PCI device handle
*/
void ATI_API_CALL KCL_PCI_EnableBusMastering(KCL_PCI_DevHandle dev)
{
pci_set_master((struct pci_dev*)dev);
}
/** \brief Tell PCI device to enable I/O space, memory space and bus mastering
** \param dev [in] PCI device handle
*/
void ATI_API_CALL KCL_PCI_EnableBars(KCL_PCI_DevHandle dev)
{
u16 cmd;
pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd);
cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd);
}
/** \brief Disable PCI device
** \param dev [in] PCI device handle
*/
void ATI_API_CALL KCL_PCI_DisableDevice(KCL_PCI_DevHandle dev)
{
// 2.6.20 ealier kernels don't like the driver doing this repeatedly.
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
pci_disable_device((struct pci_dev*)dev);
#endif
}
#if defined(__x86_64__)
/** \brief Allocate DMA coherent memory
** \param dev [in] PCI device handle
** \param size [in] Memory size
** \param dma_handle_ptr [out] Pointer to the physical (DMA) address for the allocated memory
** \return Virtual address of the allocated memory
*/
void* ATI_API_CALL KCL_PCI_AllocDmaCoherentMem(
KCL_PCI_DevHandle dev, int size, unsigned long long* dma_handle_ptr)
{
return (pci_alloc_consistent((struct pci_dev*)dev, size, dma_handle_ptr));
}
/** \brief Free DMA coherent memory
** \param dev [in] PCI device handle
** \param size [in] Memory size
** \param cpu_addr [in] Virtual memory address
** \param dma_handle [in] Physical (DMA) memory address
*/
void ATI_API_CALL KCL_PCI_FreeDmaCoherentMem(
KCL_PCI_DevHandle dev, int size, void* cpu_addr, unsigned long long dma_handle)
{
pci_free_consistent((struct pci_dev*)dev, size, cpu_addr, dma_handle);
}
#endif //__x86_64__