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