1 /*	$NetBSD: drm_pci.c,v 1.13 2015/04/29 04:38:55 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 2013 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Taylor R. Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: drm_pci.c,v 1.13 2015/04/29 04:38:55 riastradh Exp $");
34 
35 #include <sys/types.h>
36 #include <sys/errno.h>
37 #include <sys/systm.h>
38 
39 #include <dev/pci/pcivar.h>
40 
41 #include <drm/drmP.h>
42 
43 static int	drm_pci_get_irq(struct drm_device *);
44 static int	drm_pci_irq_install(struct drm_device *,
45 		    irqreturn_t (*)(void *), int, const char *, void *,
46 		    struct drm_bus_irq_cookie **);
47 static void	drm_pci_irq_uninstall(struct drm_device *,
48 		    struct drm_bus_irq_cookie *);
49 static const char *
50 		drm_pci_get_name(struct drm_device *);
51 static int	drm_pci_set_busid(struct drm_device *, struct drm_master *);
52 static int	drm_pci_set_unique(struct drm_device *, struct drm_master *,
53 		    struct drm_unique *);
54 static int	drm_pci_irq_by_busid(struct drm_device *,
55 		    struct drm_irq_busid *);
56 
57 const struct drm_bus drm_pci_bus = {
58 	.bus_type = DRIVER_BUS_PCI,
59 	.get_irq = drm_pci_get_irq,
60 	.irq_install = drm_pci_irq_install,
61 	.irq_uninstall = drm_pci_irq_uninstall,
62 	.get_name = drm_pci_get_name,
63 	.set_busid = drm_pci_set_busid,
64 	.set_unique = drm_pci_set_unique,
65 	.irq_by_busid = drm_pci_irq_by_busid,
66 };
67 
68 static const struct pci_attach_args *
drm_pci_attach_args(struct drm_device * dev)69 drm_pci_attach_args(struct drm_device *dev)
70 {
71 	return &dev->pdev->pd_pa;
72 }
73 
74 int
drm_pci_init(struct drm_driver * driver,struct pci_driver * pdriver __unused)75 drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver __unused)
76 {
77 
78 	driver->bus = &drm_pci_bus;
79 	return 0;
80 }
81 
82 void
drm_pci_exit(struct drm_driver * driver __unused,struct pci_driver * pdriver __unused)83 drm_pci_exit(struct drm_driver *driver __unused,
84     struct pci_driver *pdriver __unused)
85 {
86 }
87 
88 int
drm_pci_attach(device_t self,const struct pci_attach_args * pa,struct pci_dev * pdev,struct drm_driver * driver,unsigned long cookie,struct drm_device ** devp)89 drm_pci_attach(device_t self, const struct pci_attach_args *pa,
90     struct pci_dev *pdev, struct drm_driver *driver, unsigned long cookie,
91     struct drm_device **devp)
92 {
93 	struct drm_device *dev;
94 	unsigned int unit;
95 	int ret;
96 
97 	/* Ensure the drm agp hooks are installed.  */
98 	/* XXX errno NetBSD->Linux */
99 	ret = -drmkms_pci_agp_guarantee_initialized();
100 	if (ret)
101 		goto fail0;
102 
103 	/* Initialize the Linux PCI device descriptor.  */
104 	linux_pci_dev_init(pdev, self, pa, 0);
105 
106 	/* Create a DRM device.  */
107 	dev = drm_dev_alloc(driver, self);
108 	if (dev == NULL) {
109 		ret = -ENOMEM;
110 		goto fail0;
111 	}
112 
113 	dev->pdev = pdev;
114 	pdev->pd_drm_dev = dev;	/* XXX Nouveau kludge.  */
115 
116 	/* XXX Set the power state to D0?  */
117 
118 	/* Set up the bus space and bus DMA tags.  */
119 	dev->bst = pa->pa_memt;
120 	/* XXX Let the driver say something about 32-bit vs 64-bit DMA?  */
121 	dev->bus_dmat = (pci_dma64_available(pa)? pa->pa_dmat64 : pa->pa_dmat);
122 	dev->dmat = dev->bus_dmat;
123 	dev->dmat_subregion_p = false;
124 
125 	/* Find all the memory maps.  */
126 	CTASSERT(PCI_NUM_RESOURCES < (SIZE_MAX / sizeof(dev->bus_maps[0])));
127 	dev->bus_maps = kmem_zalloc(PCI_NUM_RESOURCES *
128 	    sizeof(dev->bus_maps[0]), KM_SLEEP);
129 	dev->bus_nmaps = PCI_NUM_RESOURCES;
130 	for (unit = 0; unit < PCI_NUM_RESOURCES; unit++) {
131 		struct drm_bus_map *const bm = &dev->bus_maps[unit];
132 		const int reg = PCI_BAR(unit);
133 		const pcireg_t type =
134 		    pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg);
135 
136 		/* Reject non-memory mappings.  */
137 		if ((type & PCI_MAPREG_TYPE_MEM) != PCI_MAPREG_TYPE_MEM) {
138 			aprint_debug_dev(self, "map %u has non-memory type:"
139 			    " 0x%"PRIxMAX"\n", unit, (uintmax_t)type);
140 			continue;
141 		}
142 
143 		/* Inquire about it.  We'll map it in drm_core_ioremap.  */
144 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg, type,
145 			&bm->bm_base, &bm->bm_size, &bm->bm_flags) != 0) {
146 			aprint_debug_dev(self, "map %u failed\n", unit);
147 			continue;
148 		}
149 
150 		/* Assume since it is a memory mapping it can be linear.  */
151 		bm->bm_flags |= BUS_SPACE_MAP_LINEAR;
152 	}
153 
154 	/* Set up AGP stuff if requested.  */
155 	if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
156 		if (drm_pci_device_is_agp(dev))
157 			dev->agp = drm_agp_init(dev);
158 		if (dev->agp)
159 			dev->agp->agp_mtrr = arch_phys_wc_add(dev->agp->base,
160 				dev->agp->agp_info.aki_info.ai_aperture_size);
161 	}
162 
163 	/* Register the DRM device and do driver-specific initialization.  */
164 	ret = drm_dev_register(dev, cookie);
165 	if (ret)
166 		goto fail1;
167 
168 	/* Success!  */
169 	*devp = dev;
170 	return 0;
171 
172 fail2: __unused
173 	drm_dev_unregister(dev);
174 fail1:	drm_pci_agp_destroy(dev);
175 	dev->bus_nmaps = 0;
176 	kmem_free(dev->bus_maps, PCI_NUM_RESOURCES * sizeof(dev->bus_maps[0]));
177 	if (dev->dmat_subregion_p)
178 		bus_dmatag_destroy(dev->dmat);
179 	drm_dev_unref(dev);
180 fail0:	return ret;
181 }
182 
183 int
drm_pci_detach(struct drm_device * dev,int flags __unused)184 drm_pci_detach(struct drm_device *dev, int flags __unused)
185 {
186 
187 	/* Do driver-specific detachment and unregister the device.  */
188 	drm_dev_unregister(dev);
189 
190 	/* Tear down AGP stuff if necessary.  */
191 	drm_pci_agp_destroy(dev);
192 
193 	/* Free the record of available bus space mappings.  */
194 	dev->bus_nmaps = 0;
195 	kmem_free(dev->bus_maps, PCI_NUM_RESOURCES * sizeof(dev->bus_maps[0]));
196 
197 	/* Tear down bus space and bus DMA tags.  */
198 	if (dev->dmat_subregion_p)
199 		bus_dmatag_destroy(dev->dmat);
200 
201 	drm_dev_unref(dev);
202 
203 	return 0;
204 }
205 
206 void
drm_pci_agp_destroy(struct drm_device * dev)207 drm_pci_agp_destroy(struct drm_device *dev)
208 {
209 
210 	if (dev->agp) {
211 		arch_phys_wc_del(dev->agp->agp_mtrr);
212 		drm_agp_clear(dev);
213 		kfree(dev->agp); /* XXX Should go in drm_agp_clear...  */
214 		dev->agp = NULL;
215 	}
216 }
217 
218 static int
drm_pci_get_irq(struct drm_device * dev)219 drm_pci_get_irq(struct drm_device *dev)
220 {
221 
222 	/*
223 	 * Caller expects a nonzero int, and doesn't really use it for
224 	 * anything, so no need to pci_intr_map here.
225 	 */
226 	return dev->pdev->pd_pa.pa_intrpin;
227 }
228 
229 static int
drm_pci_irq_install(struct drm_device * dev,irqreturn_t (* handler)(void *),int flags,const char * name,void * arg,struct drm_bus_irq_cookie ** cookiep)230 drm_pci_irq_install(struct drm_device *dev, irqreturn_t (*handler)(void *),
231     int flags, const char *name, void *arg,
232     struct drm_bus_irq_cookie **cookiep)
233 {
234 	const struct pci_attach_args *const pa = drm_pci_attach_args(dev);
235 	pci_intr_handle_t ih;
236 	const char *intrstr;
237 	void *ih_cookie;
238 	char intrbuf[PCI_INTRSTR_LEN];
239 
240 	if (pci_intr_map(pa, &ih))
241 		return -ENOENT;
242 
243 	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
244 	ih_cookie = pci_intr_establish(pa->pa_pc, ih, IPL_DRM, handler, arg);
245 	if (ih_cookie == NULL) {
246 		aprint_error_dev(dev->dev,
247 		    "couldn't establish interrupt at %s (%s)\n",
248 		    intrstr, name);
249 		return -ENOENT;
250 	}
251 
252 	aprint_normal_dev(dev->dev, "interrupting at %s (%s)\n",
253 	    intrstr, name);
254 	*cookiep = (struct drm_bus_irq_cookie *)ih_cookie;
255 	return 0;
256 }
257 
258 static void
drm_pci_irq_uninstall(struct drm_device * dev,struct drm_bus_irq_cookie * cookie)259 drm_pci_irq_uninstall(struct drm_device *dev,
260     struct drm_bus_irq_cookie *cookie)
261 {
262 	const struct pci_attach_args *pa = drm_pci_attach_args(dev);
263 
264 	pci_intr_disestablish(pa->pa_pc, (void *)cookie);
265 }
266 
267 static const char *
drm_pci_get_name(struct drm_device * dev)268 drm_pci_get_name(struct drm_device *dev)
269 {
270 	return "pci";		/* XXX PCI bus names?  */
271 }
272 
273 static int
drm_pci_format_unique(struct drm_device * dev,char * buf,size_t size)274 drm_pci_format_unique(struct drm_device *dev, char *buf, size_t size)
275 {
276 	const unsigned int domain = device_unit(device_parent(dev->dev));
277 	const unsigned int bus = dev->pdev->pd_pa.pa_bus;
278 	const unsigned int device = dev->pdev->pd_pa.pa_device;
279 	const unsigned int function = dev->pdev->pd_pa.pa_function;
280 
281 	return snprintf(buf, size, "pci:%04x:%02x:%02x.%d",
282 	    domain, bus, device, function);
283 }
284 
285 static int
drm_pci_format_devname(struct drm_device * dev,const char * unique,char * buf,size_t size)286 drm_pci_format_devname(struct drm_device *dev, const char *unique,
287     char *buf, size_t size)
288 {
289 
290 	return snprintf(buf, size, "%s@%s",
291 	    device_xname(device_parent(dev->dev)),
292 	    unique);
293 }
294 
295 static int
drm_pci_set_busid(struct drm_device * dev,struct drm_master * master)296 drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
297 {
298 	int n;
299 	char *buf;
300 
301 	n = drm_pci_format_unique(dev, NULL, 0);
302 	if (n < 0)
303 		return -ENOSPC;	/* XXX */
304 	if (0xff < n)
305 		n = 0xff;
306 
307 	buf = kzalloc(n + 1, GFP_KERNEL);
308 	(void)drm_pci_format_unique(dev, buf, n + 1);
309 
310 	if (master->unique)
311 		kfree(master->unique);
312 	master->unique = buf;
313 	master->unique_len = n;
314 	master->unique_size = n + 1;
315 
316 	n = drm_pci_format_devname(dev, master->unique, NULL, 0);
317 	if (n < 0)
318 		return -ENOSPC;	/* XXX back out? */
319 	if (0xff < n)
320 		n = 0xff;
321 
322 	buf = kzalloc(n + 1, GFP_KERNEL);
323 	(void)drm_pci_format_devname(dev, master->unique, buf, n + 1);
324 
325 	if (dev->devname)
326 		kfree(dev->devname);
327 	dev->devname = buf;
328 
329 	return 0;
330 }
331 
332 static int
drm_pci_set_unique(struct drm_device * dev,struct drm_master * master,struct drm_unique * unique __unused)333 drm_pci_set_unique(struct drm_device *dev, struct drm_master *master,
334     struct drm_unique *unique __unused)
335 {
336 
337 	/*
338 	 * XXX This is silly.  We're supposed to reject unique names
339 	 * that don't match the ones we would generate anyway.  For
340 	 * expedience, we'll just generate the one we would and ignore
341 	 * whatever userland threw at us...
342 	 */
343 	return drm_pci_set_busid(dev, master);
344 }
345 
346 static int
drm_pci_irq_by_busid(struct drm_device * dev,struct drm_irq_busid * busid)347 drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *busid)
348 {
349 	return -ENOSYS;		/* XXX */
350 }
351