xref: /gfx-drm/usr/src/uts/intel/io/radeon/radeon_drv.c (revision 47dc10d7)
1829150b0SGordon Ross /*
2829150b0SGordon Ross  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3829150b0SGordon Ross  * Use is subject to license terms.
4829150b0SGordon Ross  */
5829150b0SGordon Ross /*
6829150b0SGordon Ross  * radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
7829150b0SGordon Ross  * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
8829150b0SGordon Ross  */
9829150b0SGordon Ross /*
10829150b0SGordon Ross  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
11829150b0SGordon Ross  * All Rights Reserved.
12829150b0SGordon Ross  *
13829150b0SGordon Ross  * Permission is hereby granted, free of charge, to any person obtaining a
14829150b0SGordon Ross  * copy of this software and associated documentation files (the "Software"),
15829150b0SGordon Ross  * to deal in the Software without restriction, including without limitation
16829150b0SGordon Ross  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17829150b0SGordon Ross  * and/or sell copies of the Software, and to permit persons to whom the
18829150b0SGordon Ross  * Software is furnished to do so, subject to the following conditions:
19829150b0SGordon Ross  *
20829150b0SGordon Ross  * The above copyright notice and this permission notice (including the next
21829150b0SGordon Ross  * paragraph) shall be included in all copies or substantial portions of the
22829150b0SGordon Ross  * Software.
23829150b0SGordon Ross  *
24829150b0SGordon Ross  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25829150b0SGordon Ross  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26829150b0SGordon Ross  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27829150b0SGordon Ross  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28829150b0SGordon Ross  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29829150b0SGordon Ross  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30829150b0SGordon Ross  * OTHER DEALINGS IN THE SOFTWARE.
31829150b0SGordon Ross  *
32829150b0SGordon Ross  * Authors:
33829150b0SGordon Ross  *    Gareth Hughes <gareth@valinux.com>
34829150b0SGordon Ross  *
35829150b0SGordon Ross  */
36829150b0SGordon Ross 
37829150b0SGordon Ross #include "drmP.h"
38829150b0SGordon Ross #include "drm.h"
39829150b0SGordon Ross #include "radeon_drm.h"
40829150b0SGordon Ross #include "radeon_drv.h"
41829150b0SGordon Ross #include "drm_pciids.h"
42829150b0SGordon Ross 
43829150b0SGordon Ross int radeon_no_wb = 1;
44829150b0SGordon Ross 
45829150b0SGordon Ross /*
46829150b0SGordon Ross  * cb_ops entrypoint
47829150b0SGordon Ross  */
48829150b0SGordon Ross extern struct cb_ops drm_cb_ops;
49829150b0SGordon Ross 
50829150b0SGordon Ross /* drv_PCI_IDs comes from drm_pciids.h */
51829150b0SGordon Ross static drm_pci_id_list_t radeon_pciidlist[] = {
52829150b0SGordon Ross 	radeon_PCI_IDS
53829150b0SGordon Ross };
54829150b0SGordon Ross 
55829150b0SGordon Ross /*
56829150b0SGordon Ross  * module entrypoint
57829150b0SGordon Ross  */
58829150b0SGordon Ross static int radeon_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
59829150b0SGordon Ross static int radeon_attach(dev_info_t *, ddi_attach_cmd_t);
60829150b0SGordon Ross static int radeon_detach(dev_info_t *, ddi_detach_cmd_t);
61829150b0SGordon Ross 
62829150b0SGordon Ross extern void radeon_init_ioctl_arrays(void);
63829150b0SGordon Ross extern uint_t radeon_driver_irq_handler(caddr_t);
64829150b0SGordon Ross extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
65829150b0SGordon Ross 
66829150b0SGordon Ross /*
67829150b0SGordon Ross  * Local routines
68829150b0SGordon Ross  */
69829150b0SGordon Ross static void radeon_configure(drm_driver_t *);
70829150b0SGordon Ross 
71829150b0SGordon Ross /*
72829150b0SGordon Ross  * DRM driver
73829150b0SGordon Ross  */
74829150b0SGordon Ross static drm_driver_t	radeon_driver = {0};
75829150b0SGordon Ross 
76829150b0SGordon Ross static struct dev_ops radeon_dev_ops = {
77829150b0SGordon Ross 	DEVO_REV,			/* devo_rev */
78829150b0SGordon Ross 	0,				/* devo_refcnt */
79829150b0SGordon Ross 	radeon_info,			/* devo_getinfo */
80829150b0SGordon Ross 	nulldev,			/* devo_identify */
81829150b0SGordon Ross 	nulldev,			/* devo_probe */
82829150b0SGordon Ross 	radeon_attach,			/* devo_attach */
83829150b0SGordon Ross 	radeon_detach,			/* devo_detach */
84829150b0SGordon Ross 	nodev,				/* devo_reset */
85829150b0SGordon Ross 	&drm_cb_ops,			/* devo_cb_ops */
86829150b0SGordon Ross 	NULL,				/* devo_bus_ops */
87829150b0SGordon Ross 	NULL,				/* power */
88829150b0SGordon Ross 	ddi_quiesce_not_supported,	/* devo_quiesce */
89829150b0SGordon Ross };
90829150b0SGordon Ross 
91829150b0SGordon Ross static struct modldrv modldrv = {
92829150b0SGordon Ross 	&mod_driverops,			/* drv_modops */
93829150b0SGordon Ross 	"radeon DRM driver",		/* drv_linkinfo */
94829150b0SGordon Ross 	&radeon_dev_ops,			/* drv_dev_ops */
95829150b0SGordon Ross };
96829150b0SGordon Ross 
97829150b0SGordon Ross static struct modlinkage modlinkage = {
98829150b0SGordon Ross 	MODREV_1, (void *) &modldrv, NULL
99829150b0SGordon Ross };
100829150b0SGordon Ross 
101829150b0SGordon Ross 
102829150b0SGordon Ross /*
103829150b0SGordon Ross  * softstate head
104829150b0SGordon Ross  */
105829150b0SGordon Ross static void 	*radeon_statep;
106829150b0SGordon Ross 
107829150b0SGordon Ross int
_init(void)108829150b0SGordon Ross _init(void)
109829150b0SGordon Ross {
110829150b0SGordon Ross 	int error;
111829150b0SGordon Ross 
112829150b0SGordon Ross 	radeon_configure(&radeon_driver);
113829150b0SGordon Ross 
114829150b0SGordon Ross 	if ((error = ddi_soft_state_init(&radeon_statep,
115829150b0SGordon Ross 	    sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
116829150b0SGordon Ross 		return (error);
117829150b0SGordon Ross 
118829150b0SGordon Ross 	if ((error = mod_install(&modlinkage)) != 0) {
119829150b0SGordon Ross 		ddi_soft_state_fini(&radeon_statep);
120829150b0SGordon Ross 		return (error);
121829150b0SGordon Ross 	}
122829150b0SGordon Ross 
123829150b0SGordon Ross 	return (error);
124829150b0SGordon Ross 
125829150b0SGordon Ross }	/* _init() */
126829150b0SGordon Ross 
127829150b0SGordon Ross int
_fini(void)128829150b0SGordon Ross _fini(void)
129829150b0SGordon Ross {
130829150b0SGordon Ross 	int error;
131829150b0SGordon Ross 
132829150b0SGordon Ross 	if ((error = mod_remove(&modlinkage)) != 0)
133829150b0SGordon Ross 		return (error);
134829150b0SGordon Ross 
135829150b0SGordon Ross 	(void) ddi_soft_state_fini(&radeon_statep);
136829150b0SGordon Ross 
137829150b0SGordon Ross 	return (0);
138829150b0SGordon Ross 
139829150b0SGordon Ross }	/* _fini() */
140829150b0SGordon Ross 
141829150b0SGordon Ross int
_info(struct modinfo * modinfop)142829150b0SGordon Ross _info(struct modinfo *modinfop)
143829150b0SGordon Ross {
144829150b0SGordon Ross 	return (mod_info(&modlinkage, modinfop));
145829150b0SGordon Ross 
146829150b0SGordon Ross }	/* _info() */
147829150b0SGordon Ross 
148829150b0SGordon Ross 
149829150b0SGordon Ross static int
radeon_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)150829150b0SGordon Ross radeon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
151829150b0SGordon Ross {
152829150b0SGordon Ross 	drm_device_t	*statep;
153829150b0SGordon Ross 	void		*handle;
154829150b0SGordon Ross 	int		unit;
155829150b0SGordon Ross 
156829150b0SGordon Ross 	if (cmd != DDI_ATTACH) {
157829150b0SGordon Ross 		DRM_ERROR("radeon_attach: only attach op supported");
158829150b0SGordon Ross 		return (DDI_FAILURE);
159829150b0SGordon Ross 	}
160829150b0SGordon Ross 
161829150b0SGordon Ross 	unit =  ddi_get_instance(dip);
162829150b0SGordon Ross 	if (ddi_soft_state_zalloc(radeon_statep, unit) != DDI_SUCCESS) {
163829150b0SGordon Ross 		cmn_err(CE_WARN,
164829150b0SGordon Ross 		    "radeon_attach: alloc softstate failed unit=%d", unit);
165829150b0SGordon Ross 		return (DDI_FAILURE);
166829150b0SGordon Ross 	}
167829150b0SGordon Ross 	statep = ddi_get_soft_state(radeon_statep, unit);
168829150b0SGordon Ross 	statep->dip = dip;
169829150b0SGordon Ross 	statep->driver = &radeon_driver;
170829150b0SGordon Ross 
171829150b0SGordon Ross 	/*
172829150b0SGordon Ross 	 * Call drm_supp_register to create minor nodes for us
173829150b0SGordon Ross 	 */
174829150b0SGordon Ross 	handle = drm_supp_register(dip, statep);
175829150b0SGordon Ross 	if (handle == NULL) {
176829150b0SGordon Ross 		DRM_ERROR("radeon_attach: drm_supp_register failed");
177829150b0SGordon Ross 		goto err_exit1;
178829150b0SGordon Ross 	}
179829150b0SGordon Ross 	statep->drm_handle = handle;
180829150b0SGordon Ross 
181829150b0SGordon Ross 	/*
182829150b0SGordon Ross 	 * After drm_supp_register, we can call drm_xxx routine
183829150b0SGordon Ross 	 */
184829150b0SGordon Ross 	statep->drm_supported = DRM_UNSUPPORT;
185829150b0SGordon Ross 	if (drm_probe(statep, radeon_pciidlist) != DDI_SUCCESS) {
186829150b0SGordon Ross 		DRM_ERROR("radeon_open: "
187829150b0SGordon Ross 		    "DRM current don't support this graphics card");
188829150b0SGordon Ross 		goto err_exit2;
189829150b0SGordon Ross 	}
190829150b0SGordon Ross 	statep->drm_supported = DRM_SUPPORT;
191829150b0SGordon Ross 
192829150b0SGordon Ross 	/* call common attach code */
193829150b0SGordon Ross 	if (drm_attach(statep) != DDI_SUCCESS) {
194829150b0SGordon Ross 		DRM_ERROR("radeon_attach: drm_attach failed");
195829150b0SGordon Ross 		goto err_exit2;
196829150b0SGordon Ross 	}
197829150b0SGordon Ross 	return (DDI_SUCCESS);
198829150b0SGordon Ross 
199829150b0SGordon Ross err_exit2:
200829150b0SGordon Ross 	(void) drm_supp_unregister(handle);
201829150b0SGordon Ross err_exit1:
202829150b0SGordon Ross 	(void) ddi_soft_state_free(radeon_statep, unit);
203829150b0SGordon Ross 	return (DDI_FAILURE);
204829150b0SGordon Ross 
205829150b0SGordon Ross }	/* radeon_attach() */
206829150b0SGordon Ross 
207829150b0SGordon Ross static int
radeon_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)208829150b0SGordon Ross radeon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
209829150b0SGordon Ross {
210829150b0SGordon Ross 	drm_device_t	*statep;
211829150b0SGordon Ross 	int			unit;
212829150b0SGordon Ross 
213829150b0SGordon Ross 	if (cmd != DDI_DETACH)
214829150b0SGordon Ross 		return (DDI_FAILURE);
215829150b0SGordon Ross 
216829150b0SGordon Ross 	unit =  ddi_get_instance(dip);
217829150b0SGordon Ross 	statep = ddi_get_soft_state(radeon_statep, unit);
218829150b0SGordon Ross 	if (statep == NULL)
219829150b0SGordon Ross 		return (DDI_FAILURE);
220829150b0SGordon Ross 
221829150b0SGordon Ross 	(void) drm_detach(statep);
222829150b0SGordon Ross 	(void) drm_supp_unregister(statep->drm_handle);
223829150b0SGordon Ross 	(void) ddi_soft_state_free(radeon_statep, unit);
224829150b0SGordon Ross 
225829150b0SGordon Ross 	return (DDI_SUCCESS);
226829150b0SGordon Ross 
227829150b0SGordon Ross }	/* radeon_detach() */
228829150b0SGordon Ross 
229829150b0SGordon Ross /*ARGSUSED*/
230829150b0SGordon Ross static int
radeon_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)231829150b0SGordon Ross radeon_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
232829150b0SGordon Ross {
233829150b0SGordon Ross 	drm_device_t	*statep;
234829150b0SGordon Ross 	int 		error = DDI_SUCCESS;
235829150b0SGordon Ross 	int 		unit;
236829150b0SGordon Ross 
237829150b0SGordon Ross 	unit = drm_dev_to_instance((dev_t)arg);
238829150b0SGordon Ross 	switch (infocmd) {
239829150b0SGordon Ross 	case DDI_INFO_DEVT2DEVINFO:
240829150b0SGordon Ross 		statep = ddi_get_soft_state(radeon_statep, unit);
241829150b0SGordon Ross 		if (statep == NULL || statep->dip == NULL) {
242829150b0SGordon Ross 			error = DDI_FAILURE;
243829150b0SGordon Ross 		} else {
244829150b0SGordon Ross 			*result = (void *) statep->dip;
245829150b0SGordon Ross 			error = DDI_SUCCESS;
246829150b0SGordon Ross 		}
247829150b0SGordon Ross 		break;
248829150b0SGordon Ross 	case DDI_INFO_DEVT2INSTANCE:
249829150b0SGordon Ross 		*result = (void *)(uintptr_t)unit;
250829150b0SGordon Ross 		error = DDI_SUCCESS;
251829150b0SGordon Ross 		break;
252829150b0SGordon Ross 	default:
253829150b0SGordon Ross 		error = DDI_FAILURE;
254829150b0SGordon Ross 		break;
255829150b0SGordon Ross 	}
256829150b0SGordon Ross 	return (error);
257829150b0SGordon Ross 
258829150b0SGordon Ross }	/* radeon_info() */
259829150b0SGordon Ross 
260829150b0SGordon Ross static void
radeon_configure(drm_driver_t * driver)261829150b0SGordon Ross radeon_configure(drm_driver_t *driver)
262829150b0SGordon Ross {
263829150b0SGordon Ross 	driver->buf_priv_size = sizeof (drm_radeon_buf_priv_t);
264829150b0SGordon Ross 	driver->load			= radeon_driver_load;
265829150b0SGordon Ross 	driver->unload		= radeon_driver_unload;
266829150b0SGordon Ross 	driver->firstopen		= radeon_driver_firstopen;
267829150b0SGordon Ross 	driver->open			= radeon_driver_open;
268829150b0SGordon Ross 	driver->preclose		= radeon_driver_preclose;
269829150b0SGordon Ross 	driver->postclose		= radeon_driver_postclose;
270829150b0SGordon Ross 	driver->lastclose		= radeon_driver_lastclose;
271829150b0SGordon Ross 	driver->vblank_wait		= radeon_driver_vblank_wait;
272829150b0SGordon Ross 	driver->vblank_wait2		= radeon_driver_vblank_wait2;
273829150b0SGordon Ross 	driver->irq_preinstall	= radeon_driver_irq_preinstall;
274829150b0SGordon Ross 	driver->irq_postinstall	= radeon_driver_irq_postinstall;
275829150b0SGordon Ross 	driver->irq_uninstall	= radeon_driver_irq_uninstall;
276829150b0SGordon Ross 	driver->irq_handler		= radeon_driver_irq_handler;
277829150b0SGordon Ross 	driver->dma_ioctl		= radeon_cp_buffers;
278829150b0SGordon Ross 
279829150b0SGordon Ross 	driver->driver_ioctls	= radeon_ioctls;
280829150b0SGordon Ross 	driver->max_driver_ioctl	= radeon_max_ioctl;
281829150b0SGordon Ross 
282829150b0SGordon Ross 	driver->driver_name		= DRIVER_NAME;
283829150b0SGordon Ross 	driver->driver_desc		= DRIVER_DESC;
284829150b0SGordon Ross 	driver->driver_date		= DRIVER_DATE;
285829150b0SGordon Ross 	driver->driver_major		= DRIVER_MAJOR;
286829150b0SGordon Ross 	driver->driver_minor		= DRIVER_MINOR;
287829150b0SGordon Ross 	driver->driver_patchlevel	= DRIVER_PATCHLEVEL;
288829150b0SGordon Ross 
289829150b0SGordon Ross 	driver->use_agp		= 1;
290829150b0SGordon Ross 	driver->use_mtrr		= 1;
291829150b0SGordon Ross 	driver->use_pci_dma		= 1;
292829150b0SGordon Ross 	driver->use_sg		= 1;
293829150b0SGordon Ross 	driver->use_dma		= 1;
294829150b0SGordon Ross 	driver->use_irq		= 1;
295829150b0SGordon Ross 	driver->use_vbl_irq		= 1;
296829150b0SGordon Ross 	driver->use_vbl_irq2		= 1;
297829150b0SGordon Ross 
298829150b0SGordon Ross }	/* radeon_configure() */
299