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#include <linux/dma-mapping.h>
26#include <linux/export.h>
27#include <linux/pci.h>
28#include <linux/slab.h>
29
30#include <drm/drm.h>
31#include <drm/drm_agpsupport.h>
32#include <drm/drm_drv.h>
33#include <drm/drm_print.h>
34
35#include "drm_internal.h"
36#include "drm_legacy.h"
37
38#ifdef CONFIG_DRM_LEGACY
39
40
41
42
43
44
45
46
47
48
49
50
51
52drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
53{
54 drm_dma_handle_t *dmah;
55
56
57
58
59
60 if (align > size)
61 return NULL;
62
63 dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
64 if (!dmah)
65 return NULL;
66
67 dmah->size = size;
68 dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size,
69 &dmah->busaddr,
70 GFP_KERNEL);
71
72 if (dmah->vaddr == NULL) {
73 kfree(dmah);
74 return NULL;
75 }
76
77 return dmah;
78}
79EXPORT_SYMBOL(drm_pci_alloc);
80
81
82
83
84
85
86
87
88
89void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
90{
91 dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
92 dmah->busaddr);
93 kfree(dmah);
94}
95
96EXPORT_SYMBOL(drm_pci_free);
97#endif
98
99static int drm_get_pci_domain(struct drm_device *dev)
100{
101#ifndef __alpha__
102
103
104
105
106 if (dev->if_version < 0x10004)
107 return 0;
108#endif
109
110 return pci_domain_nr(dev->pdev->bus);
111}
112
113int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
114{
115 master->unique = kasprintf(GFP_KERNEL, "pci:%04x:%02x:%02x.%d",
116 drm_get_pci_domain(dev),
117 dev->pdev->bus->number,
118 PCI_SLOT(dev->pdev->devfn),
119 PCI_FUNC(dev->pdev->devfn));
120 if (!master->unique)
121 return -ENOMEM;
122
123 master->unique_len = strlen(master->unique);
124 return 0;
125}
126
127static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
128{
129 if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
130 (p->busnum & 0xff) != dev->pdev->bus->number ||
131 p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
132 return -EINVAL;
133
134 p->irq = dev->pdev->irq;
135
136 DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
137 p->irq);
138 return 0;
139}
140
141
142
143
144
145
146
147
148
149
150
151
152
153int drm_irq_by_busid(struct drm_device *dev, void *data,
154 struct drm_file *file_priv)
155{
156 struct drm_irq_busid *p = data;
157
158 if (!drm_core_check_feature(dev, DRIVER_LEGACY))
159 return -EOPNOTSUPP;
160
161
162 if (WARN_ON(!dev->pdev))
163 return -EINVAL;
164
165 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
166 return -EOPNOTSUPP;
167
168 return drm_pci_irq_by_busid(dev, p);
169}
170
171void drm_pci_agp_destroy(struct drm_device *dev)
172{
173 if (dev->agp) {
174 arch_phys_wc_del(dev->agp->agp_mtrr);
175 drm_legacy_agp_clear(dev);
176 kfree(dev->agp);
177 dev->agp = NULL;
178 }
179}
180
181#ifdef CONFIG_DRM_LEGACY
182
183static void drm_pci_agp_init(struct drm_device *dev)
184{
185 if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
186 if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
187 dev->agp = drm_agp_init(dev);
188 if (dev->agp) {
189 dev->agp->agp_mtrr = arch_phys_wc_add(
190 dev->agp->agp_info.aper_base,
191 dev->agp->agp_info.aper_size *
192 1024 * 1024);
193 }
194 }
195}
196
197static int drm_get_pci_dev(struct pci_dev *pdev,
198 const struct pci_device_id *ent,
199 struct drm_driver *driver)
200{
201 struct drm_device *dev;
202 int ret;
203
204 DRM_DEBUG("\n");
205
206 dev = drm_dev_alloc(driver, &pdev->dev);
207 if (IS_ERR(dev))
208 return PTR_ERR(dev);
209
210 ret = pci_enable_device(pdev);
211 if (ret)
212 goto err_free;
213
214 dev->pdev = pdev;
215#ifdef __alpha__
216 dev->hose = pdev->sysdata;
217#endif
218
219 if (drm_core_check_feature(dev, DRIVER_MODESET))
220 pci_set_drvdata(pdev, dev);
221
222 drm_pci_agp_init(dev);
223
224 ret = drm_dev_register(dev, ent->driver_data);
225 if (ret)
226 goto err_agp;
227
228
229
230 if (drm_core_check_feature(dev, DRIVER_LEGACY))
231 list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list);
232
233 return 0;
234
235err_agp:
236 drm_pci_agp_destroy(dev);
237 pci_disable_device(pdev);
238err_free:
239 drm_dev_put(dev);
240 return ret;
241}
242
243
244
245
246
247
248
249
250
251
252int drm_legacy_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
253{
254 struct pci_dev *pdev = NULL;
255 const struct pci_device_id *pid;
256 int i;
257
258 DRM_DEBUG("\n");
259
260 if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY)))
261 return -EINVAL;
262
263
264 INIT_LIST_HEAD(&driver->legacy_dev_list);
265 for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
266 pid = &pdriver->id_table[i];
267
268
269
270
271
272
273
274 pdev = NULL;
275 while ((pdev =
276 pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
277 pid->subdevice, pdev)) != NULL) {
278 if ((pdev->class & pid->class_mask) != pid->class)
279 continue;
280
281
282 pci_dev_get(pdev);
283 drm_get_pci_dev(pdev, pid, driver);
284 }
285 }
286 return 0;
287}
288EXPORT_SYMBOL(drm_legacy_pci_init);
289
290
291
292
293
294
295
296
297
298void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
299{
300 struct drm_device *dev, *tmp;
301
302 DRM_DEBUG("\n");
303
304 if (!(driver->driver_features & DRIVER_LEGACY)) {
305 WARN_ON(1);
306 } else {
307 list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list,
308 legacy_dev_list) {
309 list_del(&dev->legacy_dev_list);
310 drm_put_dev(dev);
311 }
312 }
313 DRM_INFO("Module unloaded\n");
314}
315EXPORT_SYMBOL(drm_legacy_pci_exit);
316
317#endif
318