Rev 4560 | Rev 5271 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
1 | /* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */ |
- | |
2 | /** |
- | |
3 | * \file drm_pci.c |
- | |
4 | * \brief Functions and ioctls to manage PCI memory |
- | |
5 | * |
- | |
6 | * \warning These interfaces aren't stable yet. |
- | |
7 | * |
- | |
8 | * \todo Implement the remaining ioctl's for the PCI pools. |
- | |
9 | * \todo The wrappers here are so thin that they would be better off inlined.. |
- | |
10 | * |
- | |
11 | * \author José Fonseca |
- | |
12 | * \author Leif Delgass |
- | |
13 | */ |
- | |
14 | - | ||
15 | /* |
1 | /* |
16 | * Copyright 2003 José Fonseca. |
2 | * Copyright 2003 José Fonseca. |
17 | * Copyright 2003 Leif Delgass. |
3 | * Copyright 2003 Leif Delgass. |
18 | * All Rights Reserved. |
4 | * All Rights Reserved. |
19 | * |
5 | * |
20 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
21 | * copy of this software and associated documentation files (the "Software"), |
7 | * copy of this software and associated documentation files (the "Software"), |
22 | * to deal in the Software without restriction, including without limitation |
8 | * to deal in the Software without restriction, including without limitation |
23 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
24 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * and/or sell copies of the Software, and to permit persons to whom the |
25 | * Software is furnished to do so, subject to the following conditions: |
11 | * Software is furnished to do so, subject to the following conditions: |
26 | * |
12 | * |
27 | * The above copyright notice and this permission notice (including the next |
13 | * The above copyright notice and this permission notice (including the next |
28 | * paragraph) shall be included in all copies or substantial portions of the |
14 | * paragraph) shall be included in all copies or substantial portions of the |
29 | * Software. |
15 | * Software. |
30 | * |
16 | * |
31 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
32 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
33 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
34 | * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
20 | * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
36 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
22 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
37 | */ |
23 | */ |
38 | 24 | ||
39 | //#include |
25 | //#include |
40 | //#include |
26 | //#include |
41 | //#include |
27 | #include |
42 | #include |
28 | #include |
43 | #include |
29 | #include |
44 | 30 | ||
45 | #include |
31 | #include |
46 | - | ||
47 | /**********************************************************************/ |
- | |
48 | /** \name PCI memory */ |
- | |
49 | /*@{*/ |
- | |
50 | - | ||
51 | /** |
32 | /** |
52 | * \brief Allocate a PCI consistent memory block, for DMA. |
33 | * drm_pci_alloc - Allocate a PCI consistent memory block, for DMA. |
- | 34 | * @dev: DRM device |
|
- | 35 | * @size: size of block to allocate |
|
- | 36 | * @align: alignment of block |
|
- | 37 | * |
|
- | 38 | * Return: A handle to the allocated memory block on success or NULL on |
|
- | 39 | * failure. |
|
53 | */ |
40 | */ |
54 | drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) |
41 | drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) |
55 | { |
42 | { |
56 | drm_dma_handle_t *dmah; |
43 | drm_dma_handle_t *dmah; |
57 | #if 1 |
- | |
58 | unsigned long addr; |
44 | unsigned long addr; |
59 | size_t sz; |
45 | size_t sz; |
60 | #endif |
- | |
61 | 46 | ||
62 | /* pci_alloc_consistent only guarantees alignment to the smallest |
47 | /* pci_alloc_consistent only guarantees alignment to the smallest |
63 | * PAGE_SIZE order which is greater than or equal to the requested size. |
48 | * PAGE_SIZE order which is greater than or equal to the requested size. |
64 | * Return NULL here for now to make sure nobody tries for larger alignment |
49 | * Return NULL here for now to make sure nobody tries for larger alignment |
65 | */ |
50 | */ |
66 | if (align > size) |
51 | if (align > size) |
67 | return NULL; |
52 | return NULL; |
68 | 53 | ||
69 | dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); |
54 | dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); |
70 | if (!dmah) |
55 | if (!dmah) |
71 | return NULL; |
56 | return NULL; |
72 | 57 | ||
73 | dmah->size = size; |
58 | dmah->size = size; |
74 | dmah->vaddr = (void*)KernelAlloc(size); |
59 | dmah->vaddr = (void*)KernelAlloc(size); |
75 | dmah->busaddr = GetPgAddr(dmah->vaddr); |
60 | dmah->busaddr = GetPgAddr(dmah->vaddr); |
76 | 61 | ||
77 | if (dmah->vaddr == NULL) { |
62 | if (dmah->vaddr == NULL) { |
78 | kfree(dmah); |
63 | kfree(dmah); |
79 | return NULL; |
64 | return NULL; |
80 | } |
65 | } |
81 | 66 | ||
82 | memset(dmah->vaddr, 0, size); |
67 | memset(dmah->vaddr, 0, size); |
83 | 68 | ||
84 | return dmah; |
69 | return dmah; |
85 | } |
70 | } |
86 | 71 | ||
87 | EXPORT_SYMBOL(drm_pci_alloc); |
72 | EXPORT_SYMBOL(drm_pci_alloc); |
88 | 73 | ||
89 | #if 0 |
74 | #if 0 |
90 | /** |
75 | /** |
91 | * \brief Free a PCI consistent memory block without freeing its descriptor. |
76 | * \brief Free a PCI consistent memory block without freeing its descriptor. |
92 | * |
77 | * |
93 | * This function is for internal use in the Linux-specific DRM core code. |
78 | * This function is for internal use in the Linux-specific DRM core code. |
94 | */ |
79 | */ |
95 | void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
80 | void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
96 | { |
81 | { |
97 | unsigned long addr; |
82 | unsigned long addr; |
98 | size_t sz; |
83 | size_t sz; |
99 | 84 | ||
100 | if (dmah->vaddr) { |
85 | if (dmah->vaddr) { |
101 | /* XXX - Is virt_to_page() legal for consistent mem? */ |
86 | /* XXX - Is virt_to_page() legal for consistent mem? */ |
102 | /* Unreserve */ |
87 | /* Unreserve */ |
103 | for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; |
88 | for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; |
104 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { |
89 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { |
105 | ClearPageReserved(virt_to_page((void *)addr)); |
90 | ClearPageReserved(virt_to_page((void *)addr)); |
106 | } |
91 | } |
107 | dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, |
92 | dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, |
108 | dmah->busaddr); |
93 | dmah->busaddr); |
109 | } |
94 | } |
110 | } |
95 | } |
111 | 96 | ||
112 | /** |
97 | /** |
113 | * \brief Free a PCI consistent memory block |
98 | * drm_pci_free - Free a PCI consistent memory block |
- | 99 | * @dev: DRM device |
|
- | 100 | * @dmah: handle to memory block |
|
114 | */ |
101 | */ |
115 | void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
102 | void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
116 | { |
103 | { |
117 | __drm_pci_free(dev, dmah); |
104 | __drm_pci_free(dev, dmah); |
118 | kfree(dmah); |
105 | kfree(dmah); |
119 | } |
106 | } |
120 | 107 | ||
121 | EXPORT_SYMBOL(drm_pci_free); |
108 | EXPORT_SYMBOL(drm_pci_free); |
122 | 109 | ||
123 | 110 | ||
124 | static int drm_get_pci_domain(struct drm_device *dev) |
111 | static int drm_get_pci_domain(struct drm_device *dev) |
125 | { |
112 | { |
126 | #ifndef __alpha__ |
113 | #ifndef __alpha__ |
127 | /* For historical reasons, drm_get_pci_domain() is busticated |
114 | /* For historical reasons, drm_get_pci_domain() is busticated |
128 | * on most archs and has to remain so for userspace interface |
115 | * on most archs and has to remain so for userspace interface |
129 | * < 1.4, except on alpha which was right from the beginning |
116 | * < 1.4, except on alpha which was right from the beginning |
130 | */ |
117 | */ |
131 | if (dev->if_version < 0x10004) |
118 | if (dev->if_version < 0x10004) |
132 | return 0; |
119 | return 0; |
133 | #endif /* __alpha__ */ |
120 | #endif /* __alpha__ */ |
134 | 121 | ||
135 | return pci_domain_nr(dev->pdev->bus); |
122 | return pci_domain_nr(dev->pdev->bus); |
136 | } |
123 | } |
137 | 124 | ||
138 | static int drm_pci_get_irq(struct drm_device *dev) |
125 | static int drm_pci_get_irq(struct drm_device *dev) |
139 | { |
126 | { |
140 | return dev->pdev->irq; |
127 | return dev->pdev->irq; |
141 | } |
128 | } |
142 | 129 | ||
143 | static const char *drm_pci_get_name(struct drm_device *dev) |
130 | static const char *drm_pci_get_name(struct drm_device *dev) |
144 | { |
131 | { |
145 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
132 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
146 | return pdriver->name; |
133 | return pdriver->name; |
147 | } |
134 | } |
148 | 135 | ||
149 | static int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) |
136 | static int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) |
150 | { |
137 | { |
151 | int len, ret; |
138 | int len, ret; |
152 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
139 | struct pci_driver *pdriver = dev->driver->kdriver.pci; |
153 | master->unique_len = 40; |
140 | master->unique_len = 40; |
154 | master->unique_size = master->unique_len; |
141 | master->unique_size = master->unique_len; |
155 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
142 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
156 | if (master->unique == NULL) |
143 | if (master->unique == NULL) |
157 | return -ENOMEM; |
144 | return -ENOMEM; |
158 | 145 | ||
159 | 146 | ||
160 | len = snprintf(master->unique, master->unique_len, |
147 | len = snprintf(master->unique, master->unique_len, |
161 | "pci:%04x:%02x:%02x.%d", |
148 | "pci:%04x:%02x:%02x.%d", |
162 | drm_get_pci_domain(dev), |
149 | drm_get_pci_domain(dev), |
163 | dev->pdev->bus->number, |
150 | dev->pdev->bus->number, |
164 | PCI_SLOT(dev->pdev->devfn), |
151 | PCI_SLOT(dev->pdev->devfn), |
165 | PCI_FUNC(dev->pdev->devfn)); |
152 | PCI_FUNC(dev->pdev->devfn)); |
166 | 153 | ||
167 | if (len >= master->unique_len) { |
154 | if (len >= master->unique_len) { |
168 | DRM_ERROR("buffer overflow"); |
155 | DRM_ERROR("buffer overflow"); |
169 | ret = -EINVAL; |
156 | ret = -EINVAL; |
170 | goto err; |
157 | goto err; |
171 | } else |
158 | } else |
172 | master->unique_len = len; |
159 | master->unique_len = len; |
173 | 160 | ||
174 | dev->devname = |
161 | dev->devname = |
175 | kmalloc(strlen(pdriver->name) + |
162 | kmalloc(strlen(pdriver->name) + |
176 | master->unique_len + 2, GFP_KERNEL); |
163 | master->unique_len + 2, GFP_KERNEL); |
177 | 164 | ||
178 | if (dev->devname == NULL) { |
165 | if (dev->devname == NULL) { |
179 | ret = -ENOMEM; |
166 | ret = -ENOMEM; |
180 | goto err; |
167 | goto err; |
181 | } |
168 | } |
182 | 169 | ||
183 | sprintf(dev->devname, "%s@%s", pdriver->name, |
170 | sprintf(dev->devname, "%s@%s", pdriver->name, |
184 | master->unique); |
171 | master->unique); |
185 | 172 | ||
186 | return 0; |
173 | return 0; |
187 | err: |
174 | err: |
188 | return ret; |
175 | return ret; |
189 | } |
176 | } |
190 | 177 | ||
191 | static int drm_pci_set_unique(struct drm_device *dev, |
178 | static int drm_pci_set_unique(struct drm_device *dev, |
192 | struct drm_master *master, |
179 | struct drm_master *master, |
193 | struct drm_unique *u) |
180 | struct drm_unique *u) |
194 | { |
181 | { |
195 | int domain, bus, slot, func, ret; |
182 | int domain, bus, slot, func, ret; |
196 | const char *bus_name; |
183 | const char *bus_name; |
197 | 184 | ||
198 | master->unique_len = u->unique_len; |
185 | master->unique_len = u->unique_len; |
199 | master->unique_size = u->unique_len + 1; |
186 | master->unique_size = u->unique_len + 1; |
200 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
187 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); |
201 | if (!master->unique) { |
188 | if (!master->unique) { |
202 | ret = -ENOMEM; |
189 | ret = -ENOMEM; |
203 | goto err; |
190 | goto err; |
204 | } |
191 | } |
205 | 192 | ||
206 | if (copy_from_user(master->unique, u->unique, master->unique_len)) { |
193 | if (copy_from_user(master->unique, u->unique, master->unique_len)) { |
207 | ret = -EFAULT; |
194 | ret = -EFAULT; |
208 | goto err; |
195 | goto err; |
209 | } |
196 | } |
210 | 197 | ||
211 | master->unique[master->unique_len] = '\0'; |
198 | master->unique[master->unique_len] = '\0'; |
212 | 199 | ||
213 | bus_name = dev->driver->bus->get_name(dev); |
200 | bus_name = dev->driver->bus->get_name(dev); |
214 | dev->devname = kmalloc(strlen(bus_name) + |
201 | dev->devname = kmalloc(strlen(bus_name) + |
215 | strlen(master->unique) + 2, GFP_KERNEL); |
202 | strlen(master->unique) + 2, GFP_KERNEL); |
216 | if (!dev->devname) { |
203 | if (!dev->devname) { |
217 | ret = -ENOMEM; |
204 | ret = -ENOMEM; |
218 | goto err; |
205 | goto err; |
219 | } |
206 | } |
220 | 207 | ||
221 | sprintf(dev->devname, "%s@%s", bus_name, |
208 | sprintf(dev->devname, "%s@%s", bus_name, |
222 | master->unique); |
209 | master->unique); |
223 | 210 | ||
224 | /* Return error if the busid submitted doesn't match the device's actual |
211 | /* Return error if the busid submitted doesn't match the device's actual |
225 | * busid. |
212 | * busid. |
226 | */ |
213 | */ |
227 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); |
214 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); |
228 | if (ret != 3) { |
215 | if (ret != 3) { |
229 | ret = -EINVAL; |
216 | ret = -EINVAL; |
230 | goto err; |
217 | goto err; |
231 | } |
218 | } |
232 | 219 | ||
233 | domain = bus >> 8; |
220 | domain = bus >> 8; |
234 | bus &= 0xff; |
221 | bus &= 0xff; |
235 | 222 | ||
236 | if ((domain != drm_get_pci_domain(dev)) || |
223 | if ((domain != drm_get_pci_domain(dev)) || |
237 | (bus != dev->pdev->bus->number) || |
224 | (bus != dev->pdev->bus->number) || |
238 | (slot != PCI_SLOT(dev->pdev->devfn)) || |
225 | (slot != PCI_SLOT(dev->pdev->devfn)) || |
239 | (func != PCI_FUNC(dev->pdev->devfn))) { |
226 | (func != PCI_FUNC(dev->pdev->devfn))) { |
240 | ret = -EINVAL; |
227 | ret = -EINVAL; |
241 | goto err; |
228 | goto err; |
242 | } |
229 | } |
243 | return 0; |
230 | return 0; |
244 | err: |
231 | err: |
245 | return ret; |
232 | return ret; |
246 | } |
233 | } |
247 | - | ||
248 | 234 | ||
249 | static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) |
235 | static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) |
250 | { |
236 | { |
251 | if ((p->busnum >> 8) != drm_get_pci_domain(dev) || |
237 | if ((p->busnum >> 8) != drm_get_pci_domain(dev) || |
252 | (p->busnum & 0xff) != dev->pdev->bus->number || |
238 | (p->busnum & 0xff) != dev->pdev->bus->number || |
253 | p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) |
239 | p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) |
254 | return -EINVAL; |
240 | return -EINVAL; |
255 | 241 | ||
256 | p->irq = dev->pdev->irq; |
242 | p->irq = dev->pdev->irq; |
257 | 243 | ||
258 | DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, |
244 | DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, |
259 | p->irq); |
245 | p->irq); |
260 | return 0; |
246 | return 0; |
261 | } |
247 | } |
262 | 248 | ||
263 | static void drm_pci_agp_init(struct drm_device *dev) |
249 | static void drm_pci_agp_init(struct drm_device *dev) |
264 | { |
250 | { |
265 | if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { |
251 | if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { |
266 | if (drm_pci_device_is_agp(dev)) |
252 | if (drm_pci_device_is_agp(dev)) |
267 | dev->agp = drm_agp_init(dev); |
253 | dev->agp = drm_agp_init(dev); |
268 | if (dev->agp) { |
254 | if (dev->agp) { |
269 | dev->agp->agp_mtrr = arch_phys_wc_add( |
255 | dev->agp->agp_mtrr = arch_phys_wc_add( |
270 | dev->agp->agp_info.aper_base, |
256 | dev->agp->agp_info.aper_base, |
271 | dev->agp->agp_info.aper_size * |
257 | dev->agp->agp_info.aper_size * |
272 | 1024 * 1024); |
258 | 1024 * 1024); |
273 | } |
259 | } |
274 | } |
260 | } |
275 | } |
261 | } |
276 | 262 | ||
277 | void drm_pci_agp_destroy(struct drm_device *dev) |
263 | void drm_pci_agp_destroy(struct drm_device *dev) |
278 | { |
264 | { |
279 | if (dev->agp) { |
265 | if (dev->agp) { |
280 | arch_phys_wc_del(dev->agp->agp_mtrr); |
266 | arch_phys_wc_del(dev->agp->agp_mtrr); |
281 | drm_agp_clear(dev); |
267 | drm_agp_clear(dev); |
282 | kfree(dev->agp); |
268 | kfree(dev->agp); |
283 | dev->agp = NULL; |
269 | dev->agp = NULL; |
284 | } |
270 | } |
285 | } |
271 | } |
286 | 272 | ||
287 | static struct drm_bus drm_pci_bus = { |
273 | static struct drm_bus drm_pci_bus = { |
288 | .bus_type = DRIVER_BUS_PCI, |
274 | .bus_type = DRIVER_BUS_PCI, |
289 | .get_irq = drm_pci_get_irq, |
275 | .get_irq = drm_pci_get_irq, |
290 | .get_name = drm_pci_get_name, |
276 | .get_name = drm_pci_get_name, |
291 | .set_busid = drm_pci_set_busid, |
277 | .set_busid = drm_pci_set_busid, |
292 | .set_unique = drm_pci_set_unique, |
278 | .set_unique = drm_pci_set_unique, |
293 | .irq_by_busid = drm_pci_irq_by_busid, |
279 | .irq_by_busid = drm_pci_irq_by_busid, |
294 | }; |
280 | }; |
295 | #endif |
281 | #endif |
296 | 282 | ||
297 | /** |
283 | /** |
298 | * Register. |
284 | * Register. |
299 | * |
285 | * |
300 | * \param pdev - PCI device structure |
286 | * \param pdev - PCI device structure |
301 | * \param ent entry from the PCI ID table with device type flags |
287 | * \param ent entry from the PCI ID table with device type flags |
302 | * \return zero on success or a negative number on failure. |
288 | * \return zero on success or a negative number on failure. |
303 | * |
289 | * |
304 | * Attempt to gets inter module "drm" information. If we are first |
290 | * Attempt to gets inter module "drm" information. If we are first |
305 | * then register the character device and inter module information. |
291 | * then register the character device and inter module information. |
306 | * Try and register, if we fail to register, backout previous work. |
292 | * Try and register, if we fail to register, backout previous work. |
307 | */ |
293 | */ |
308 | int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, |
294 | int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, |
309 | struct drm_driver *driver) |
295 | struct drm_driver *driver) |
310 | { |
296 | { |
311 | static struct drm_device drm_dev; |
297 | static struct drm_device drm_dev; |
312 | static struct drm_file drm_file; |
298 | static struct drm_file drm_file; |
313 | 299 | ||
314 | struct drm_device *dev; |
300 | struct drm_device *dev; |
315 | struct drm_file *priv; |
301 | struct drm_file *priv; |
316 | 302 | ||
317 | int ret; |
303 | int ret; |
318 | 304 | ||
319 | dev = &drm_dev; |
305 | dev = &drm_dev; |
320 | priv = &drm_file; |
306 | priv = &drm_file; |
321 | 307 | ||
322 | drm_file_handlers[0] = priv; |
308 | drm_file_handlers[0] = priv; |
323 | 309 | ||
324 | // ret = pci_enable_device(pdev); |
310 | // ret = pci_enable_device(pdev); |
325 | // if (ret) |
311 | // if (ret) |
326 | // goto err_g1; |
312 | // goto err_g1; |
327 | 313 | ||
328 | pci_set_master(pdev); |
314 | pci_set_master(pdev); |
329 | 315 | ||
330 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
316 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
331 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
317 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
332 | goto err_g2; |
318 | goto err_g2; |
333 | } |
319 | } |
334 | 320 | ||
335 | DRM_DEBUG("\n"); |
321 | DRM_DEBUG("\n"); |
336 | 322 | ||
337 | 323 | ||
338 | dev->pdev = pdev; |
324 | dev->pdev = pdev; |
339 | dev->pci_device = pdev->device; |
- | |
340 | dev->pci_vendor = pdev->vendor; |
- | |
341 | - | ||
342 | #ifdef __alpha__ |
325 | #ifdef __alpha__ |
343 | dev->hose = pdev->sysdata; |
326 | dev->hose = pdev->sysdata; |
344 | #endif |
327 | #endif |
345 | - | ||
346 | // mutex_lock(&drm_global_mutex); |
328 | |
347 | 329 | ||
348 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
330 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
349 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
331 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
350 | goto err_g2; |
332 | goto err_g2; |
351 | } |
333 | } |
352 | 334 | ||
353 | #if 0 |
335 | #if 0 |
354 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
336 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
355 | pci_set_drvdata(pdev, dev); |
337 | pci_set_drvdata(pdev, dev); |
356 | ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); |
338 | ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); |
357 | if (ret) |
339 | if (ret) |
358 | goto err_g2; |
340 | goto err_g2; |
359 | } |
341 | } |
360 | 342 | ||
361 | if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { |
343 | if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { |
362 | ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); |
344 | ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); |
363 | if (ret) |
345 | if (ret) |
364 | goto err_g21; |
346 | goto err_g21; |
365 | } |
347 | } |
366 | 348 | ||
367 | if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) |
349 | if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) |
368 | goto err_g3; |
350 | goto err_g3; |
369 | #endif |
351 | #endif |
370 | 352 | ||
371 | if (dev->driver->load) { |
353 | if (dev->driver->load) { |
372 | ret = dev->driver->load(dev, ent->driver_data); |
354 | ret = dev->driver->load(dev, ent->driver_data); |
373 | if (ret) |
355 | if (ret) |
374 | goto err_g4; |
356 | goto err_g4; |
375 | } |
357 | } |
376 | 358 | ||
377 | if (dev->driver->open) { |
359 | if (dev->driver->open) { |
378 | ret = dev->driver->open(dev, priv); |
360 | ret = dev->driver->open(dev, priv); |
379 | if (ret < 0) |
361 | if (ret < 0) |
380 | goto err_g4; |
362 | goto err_g4; |
381 | } |
363 | } |
382 | 364 | ||
383 | 365 | ||
384 | // mutex_unlock(&drm_global_mutex); |
366 | // mutex_unlock(&drm_global_mutex); |
385 | return 0; |
367 | return 0; |
386 | 368 | ||
387 | err_g4: |
369 | err_g4: |
388 | // drm_put_minor(&dev->primary); |
370 | // drm_put_minor(&dev->primary); |
389 | err_g3: |
371 | err_g3: |
390 | // if (dev->render) |
372 | // if (dev->render) |
391 | // drm_put_minor(&dev->render); |
373 | // drm_put_minor(&dev->render); |
392 | err_g21: |
374 | err_g21: |
393 | // if (drm_core_check_feature(dev, DRIVER_MODESET)) |
375 | // if (drm_core_check_feature(dev, DRIVER_MODESET)) |
394 | // drm_put_minor(&dev->control); |
376 | // drm_put_minor(&dev->control); |
395 | err_g2: |
377 | err_g2: |
396 | // pci_disable_device(pdev); |
378 | // pci_disable_device(pdev); |
397 | err_g1: |
379 | err_g1: |
398 | // kfree(dev); |
380 | // kfree(dev); |
399 | // mutex_unlock(&drm_global_mutex); |
381 | // mutex_unlock(&drm_global_mutex); |
400 | return ret; |
382 | return ret; |
401 | } |
383 | } |
402 | EXPORT_SYMBOL(drm_get_pci_dev); |
384 | EXPORT_SYMBOL(drm_get_pci_dev); |
403 | 385 | ||
404 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) |
386 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) |
405 | { |
387 | { |
406 | struct pci_dev *root; |
388 | struct pci_dev *root; |
407 | u32 lnkcap, lnkcap2; |
389 | u32 lnkcap, lnkcap2; |
408 | 390 | ||
409 | *mask = 0; |
391 | *mask = 0; |
410 | if (!dev->pdev) |
392 | if (!dev->pdev) |
411 | return -EINVAL; |
393 | return -EINVAL; |
412 | 394 | ||
413 | 395 | ||
414 | return -EINVAL; |
396 | return -EINVAL; |
415 | 397 | ||
416 | #if 0 |
398 | #if 0 |
417 | root = dev->pdev->bus->self; |
399 | root = dev->pdev->bus->self; |
418 | 400 | ||
419 | /* we've been informed via and serverworks don't make the cut */ |
401 | /* we've been informed via and serverworks don't make the cut */ |
420 | if (root->vendor == PCI_VENDOR_ID_VIA || |
402 | if (root->vendor == PCI_VENDOR_ID_VIA || |
421 | root->vendor == PCI_VENDOR_ID_SERVERWORKS) |
403 | root->vendor == PCI_VENDOR_ID_SERVERWORKS) |
422 | return -EINVAL; |
404 | return -EINVAL; |
423 | 405 | ||
424 | pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); |
406 | pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); |
425 | pcie_capability_read_dword(root, PCI_EXP_LNKCAP2, &lnkcap2); |
407 | pcie_capability_read_dword(root, PCI_EXP_LNKCAP2, &lnkcap2); |
426 | 408 | ||
427 | if (lnkcap2) { /* PCIe r3.0-compliant */ |
409 | if (lnkcap2) { /* PCIe r3.0-compliant */ |
428 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) |
410 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) |
429 | *mask |= DRM_PCIE_SPEED_25; |
411 | *mask |= DRM_PCIE_SPEED_25; |
430 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) |
412 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) |
431 | *mask |= DRM_PCIE_SPEED_50; |
413 | *mask |= DRM_PCIE_SPEED_50; |
432 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) |
414 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) |
433 | *mask |= DRM_PCIE_SPEED_80; |
415 | *mask |= DRM_PCIE_SPEED_80; |
434 | } else { /* pre-r3.0 */ |
416 | } else { /* pre-r3.0 */ |
435 | if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) |
417 | if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) |
436 | *mask |= DRM_PCIE_SPEED_25; |
418 | *mask |= DRM_PCIE_SPEED_25; |
437 | if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB) |
419 | if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB) |
438 | *mask |= (DRM_PCIE_SPEED_25 | DRM_PCIE_SPEED_50); |
420 | *mask |= (DRM_PCIE_SPEED_25 | DRM_PCIE_SPEED_50); |
439 | } |
421 | } |
440 | 422 | ||
441 | DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2); |
423 | DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2); |
442 | return 0; |
424 | return 0; |
443 | #endif |
425 | #endif |
444 | 426 | ||
445 | } |
427 | } |
446 | EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask);>>> |
428 | EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask);>>> |