xref: /titanic_50/usr/src/uts/intel/io/drm/i915_drv.c (revision 15d9d0b528387242011cdcc6190c9e598cfe3a07)
1 /* BEGIN CSTYLED */
2 
3 /*
4  * i915_drv.c -- Intel i915 driver -*- linux-c -*-
5  * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
6  */
7 
8 /*
9  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
10  * All Rights Reserved.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice (including the next
20  * paragraph) shall be included in all copies or substantial portions of the
21  * Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29  * OTHER DEALINGS IN THE SOFTWARE.
30  *
31  * Authors:
32  *    Gareth Hughes <gareth@valinux.com>
33  *
34  */
35 
36 /*
37  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
38  * Use is subject to license terms.
39  */
40 
41 /*
42  * I915 DRM Driver for Solaris
43  *
44  * This driver provides the hardware 3D acceleration support for Intel
45  * integrated video devices (e.g. i8xx/i915/i945 series chipsets), under the
46  * DRI (Direct Rendering Infrastructure). DRM (Direct Rendering Manager) here
47  * means the kernel device driver in DRI.
48  *
49  * I915 driver is a device dependent driver only, it depends on a misc module
50  * named drm for generic DRM operations.
51  */
52 #pragma ident	"%Z%%M%	%I%	%E% SMI"
53 
54 #include "drmP.h"
55 #include "i915_drm.h"
56 #include "i915_drv.h"
57 #include "drm_pciids.h"
58 
59 #define	i915_max_ioctl  15
60 
61 
62 /*
63  * cb_ops entrypoint
64  */
65 extern struct cb_ops drm_cb_ops;
66 
67 /*
68  * module entrypoint
69  */
70 static int i915_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
71 static int i915_attach(dev_info_t *, ddi_attach_cmd_t);
72 static int i915_detach(dev_info_t *, ddi_detach_cmd_t);
73 
74 
75 /* drv_PCI_IDs comes from drm_pciids.h */
76 static drm_pci_id_list_t i915_pciidlist[] = {
77 	i915_PCI_IDS
78 };
79 
80 drm_ioctl_desc_t i915_ioctls[i915_max_ioctl];
81 
82 extern void i915_init_ioctl_arrays(void);
83 
84 /*
85  * Local routines
86  */
87 static void i915_configure(drm_driver_t *);
88 
89 /*
90  * DRM driver
91  */
92 static drm_driver_t	i915_driver = {0};
93 
94 
95 static struct dev_ops i915_dev_ops = {
96 	DEVO_REV,			/* devo_rev */
97 	0,				/* devo_refcnt */
98 	i915_info,			/* devo_getinfo */
99 	nulldev,			/* devo_identify */
100 	nulldev,			/* devo_probe */
101 	i915_attach,			/* devo_attach */
102 	i915_detach,			/* devo_detach */
103 	nodev,				/* devo_reset */
104 	&drm_cb_ops,		/* devo_cb_ops */
105 	NULL,				/* devo_bus_ops */
106 	NULL				/* power */
107 };
108 
109 static struct modldrv modldrv = {
110 	&mod_driverops,			/* drv_modops */
111 	"I915 DRM driver 1.2",	/* drv_linkinfo */
112 	&i915_dev_ops,			/* drv_dev_ops */
113 };
114 
115 static struct modlinkage modlinkage = {
116 	MODREV_1, (void *) &modldrv, NULL
117 };
118 
119 
120 /*
121  * softstate head
122  */
123 static void 	*i915_statep;
124 
125 int
126 _init(void)
127 {
128 	int error;
129 
130 	i915_configure(&i915_driver);
131 
132 	if ((error = ddi_soft_state_init(&i915_statep,
133 	    sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
134 		return (error);
135 
136 	if ((error = mod_install(&modlinkage)) != 0) {
137 		ddi_soft_state_fini(&i915_statep);
138 		return (error);
139 	}
140 
141 	return (error);
142 
143 }	/* _init() */
144 
145 int
146 _fini(void)
147 {
148 	int error;
149 
150 	if ((error = mod_remove(&modlinkage)) != 0)
151 		return (error);
152 
153 	(void) ddi_soft_state_fini(&i915_statep);
154 
155 	return (0);
156 
157 }	/* _fini() */
158 
159 int
160 _info(struct modinfo *modinfop)
161 {
162 	return (mod_info(&modlinkage, modinfop));
163 
164 }	/* _info() */
165 
166 static int
167 i915_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
168 {
169 	drm_device_t		*statep;
170 	void		*handle;
171 	int			unit;
172 
173 	if (cmd != DDI_ATTACH) {
174 		DRM_ERROR("i915_attach: only attach op supported");
175 		return (DDI_FAILURE);
176 	}
177 
178 	unit =  ddi_get_instance(dip);
179 	if (ddi_soft_state_zalloc(i915_statep, unit) != DDI_SUCCESS) {
180 		cmn_err(CE_WARN, "i915_attach: failed to alloc softstate");
181 		return (DDI_FAILURE);
182 	}
183 	statep = ddi_get_soft_state(i915_statep, unit);
184 	statep->dip = dip;
185 	statep->driver = &i915_driver;
186 
187 	/*
188 	 * Call drm_supp_register to create minor nodes for us
189 	 */
190 	handle = drm_supp_register(dip, statep);
191 	if ( handle == NULL) {
192 		DRM_ERROR("i915_attach: drm_supp_register failed");
193 		goto err_exit1;
194 	}
195 	statep->drm_handle = handle;
196 
197 	/*
198 	 * After drm_supp_register, we can call drm_xxx routine
199 	 */
200 	statep->drm_supported = DRM_UNSUPPORT;
201 	if (drm_probe(statep, i915_pciidlist) != DDI_SUCCESS) {
202 		DRM_ERROR("i915_open: "
203 		    "DRM current don't support this graphics card");
204 		goto err_exit2;
205 	}
206 	statep->drm_supported = DRM_SUPPORT;
207 
208 	/* call common attach code */
209 	if (drm_attach(statep) != DDI_SUCCESS) {
210 		DRM_ERROR("i915_attach: drm_attach failed");
211 		goto err_exit2;
212 	}
213 	return (DDI_SUCCESS);
214 
215 err_exit2:
216 	(void) drm_supp_unregister(handle);
217 err_exit1:
218 	(void) ddi_soft_state_free(i915_statep, unit);
219 	return (DDI_FAILURE);
220 
221 }	/* i915_attach() */
222 
223 static int
224 i915_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
225 {
226 	drm_device_t		*statep;
227 	int		unit;
228 
229 	if (cmd != DDI_DETACH)
230 		return (DDI_FAILURE);
231 
232 	unit =  ddi_get_instance(dip);
233 	statep = ddi_get_soft_state(i915_statep, unit);
234 	if (statep == NULL)
235 		return (DDI_FAILURE);
236 
237 	(void) drm_detach(statep);
238 	(void) drm_supp_unregister(statep->drm_handle);
239 	(void) ddi_soft_state_free(i915_statep, unit);
240 
241 	return (DDI_SUCCESS);
242 
243 }	/* i915_detach() */
244 
245 
246 /*ARGSUSED*/
247 static int
248 i915_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
249 {
250 	drm_device_t		*statep;
251 	int 	error = DDI_SUCCESS;
252 	int 	unit;
253 
254 	unit = drm_dev_to_instance((dev_t)arg);
255 	switch (infocmd) {
256 	case DDI_INFO_DEVT2DEVINFO:
257 		statep = ddi_get_soft_state(i915_statep, unit);
258 		if (statep == NULL || statep->dip == NULL) {
259 			error = DDI_FAILURE;
260 		} else {
261 			*result = (void *) statep->dip;
262 			error = DDI_SUCCESS;
263 		}
264 		break;
265 	case DDI_INFO_DEVT2INSTANCE:
266 		*result = (void *)(uintptr_t)unit;
267 		error = DDI_SUCCESS;
268 		break;
269 	default:
270 		error = DDI_FAILURE;
271 		break;
272 	}
273 	return (error);
274 
275 }	/* i915_info() */
276 
277 
278 static void i915_configure(drm_driver_t *driver)
279 {
280 	i915_init_ioctl_arrays();
281 
282 	driver->buf_priv_size	=	1;	/* No dev_priv */
283 	driver->load	=	i915_driver_load;
284 	driver->preclose	=	i915_driver_preclose;
285 	driver->lastclose	=	i915_driver_lastclose;
286 	driver->device_is_agp	=	i915_driver_device_is_agp;
287 	driver->vblank_wait		=	i915_driver_vblank_wait;
288 	driver->irq_preinstall	=	i915_driver_irq_preinstall;
289 	driver->irq_postinstall	=	i915_driver_irq_postinstall;
290 	driver->irq_uninstall	=	i915_driver_irq_uninstall;
291 	driver->irq_handler 		=	i915_driver_irq_handler;
292 
293 	driver->driver_ioctls	=	i915_ioctls;
294 	driver->max_driver_ioctl	=	i915_max_ioctl;
295 
296 	driver->driver_name	=	DRIVER_NAME;
297 	driver->driver_desc	=	DRIVER_DESC;
298 	driver->driver_date	=	DRIVER_DATE;
299 	driver->driver_major	=	DRIVER_MAJOR;
300 	driver->driver_minor	=	DRIVER_MINOR;
301 	driver->driver_patchlevel	=	DRIVER_PATCHLEVEL;
302 
303 	driver->use_agp	=	1;
304 	driver->require_agp	=	1;
305 	driver->use_irq	=	1;
306 	driver->use_vbl_irq	=	1;
307 }
308