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 #include "drmP.h"
38 #include "drm.h"
39 #include "radeon_drm.h"
40 #include "radeon_drv.h"
41 #include "drm_pciids.h"
42
43 int radeon_no_wb = 1;
44
45 /*
46 * cb_ops entrypoint
47 */
48 extern struct cb_ops drm_cb_ops;
49
50 /* drv_PCI_IDs comes from drm_pciids.h */
51 static drm_pci_id_list_t radeon_pciidlist[] = {
52 radeon_PCI_IDS
53 };
54
55 /*
56 * module entrypoint
57 */
58 static int radeon_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
59 static int radeon_attach(dev_info_t *, ddi_attach_cmd_t);
60 static int radeon_detach(dev_info_t *, ddi_detach_cmd_t);
61
62 extern void radeon_init_ioctl_arrays(void);
63 extern uint_t radeon_driver_irq_handler(caddr_t);
64 extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
65
66 /*
67 * Local routines
68 */
69 static void radeon_configure(drm_driver_t *);
70
71 /*
72 * DRM driver
73 */
74 static drm_driver_t radeon_driver = {0};
75
76 static struct dev_ops radeon_dev_ops = {
77 DEVO_REV, /* devo_rev */
78 0, /* devo_refcnt */
79 radeon_info, /* devo_getinfo */
80 nulldev, /* devo_identify */
81 nulldev, /* devo_probe */
82 radeon_attach, /* devo_attach */
83 radeon_detach, /* devo_detach */
84 nodev, /* devo_reset */
85 &drm_cb_ops, /* devo_cb_ops */
86 NULL, /* devo_bus_ops */
87 NULL, /* power */
88 ddi_quiesce_not_supported, /* devo_quiesce */
89 };
90
91 static struct modldrv modldrv = {
92 &mod_driverops, /* drv_modops */
93 "radeon DRM driver", /* drv_linkinfo */
94 &radeon_dev_ops, /* drv_dev_ops */
95 };
96
97 static struct modlinkage modlinkage = {
98 MODREV_1, (void *) &modldrv, NULL
99 };
100
101
102 /*
103 * softstate head
104 */
105 static void *radeon_statep;
106
107 int
_init(void)108 _init(void)
109 {
110 int error;
111
112 radeon_configure(&radeon_driver);
113
114 if ((error = ddi_soft_state_init(&radeon_statep,
115 sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
116 return (error);
117
118 if ((error = mod_install(&modlinkage)) != 0) {
119 ddi_soft_state_fini(&radeon_statep);
120 return (error);
121 }
122
123 return (error);
124
125 } /* _init() */
126
127 int
_fini(void)128 _fini(void)
129 {
130 int error;
131
132 if ((error = mod_remove(&modlinkage)) != 0)
133 return (error);
134
135 (void) ddi_soft_state_fini(&radeon_statep);
136
137 return (0);
138
139 } /* _fini() */
140
141 int
_info(struct modinfo * modinfop)142 _info(struct modinfo *modinfop)
143 {
144 return (mod_info(&modlinkage, modinfop));
145
146 } /* _info() */
147
148
149 static int
radeon_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)150 radeon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
151 {
152 drm_device_t *statep;
153 void *handle;
154 int unit;
155
156 if (cmd != DDI_ATTACH) {
157 DRM_ERROR("radeon_attach: only attach op supported");
158 return (DDI_FAILURE);
159 }
160
161 unit = ddi_get_instance(dip);
162 if (ddi_soft_state_zalloc(radeon_statep, unit) != DDI_SUCCESS) {
163 cmn_err(CE_WARN,
164 "radeon_attach: alloc softstate failed unit=%d", unit);
165 return (DDI_FAILURE);
166 }
167 statep = ddi_get_soft_state(radeon_statep, unit);
168 statep->dip = dip;
169 statep->driver = &radeon_driver;
170
171 /*
172 * Call drm_supp_register to create minor nodes for us
173 */
174 handle = drm_supp_register(dip, statep);
175 if (handle == NULL) {
176 DRM_ERROR("radeon_attach: drm_supp_register failed");
177 goto err_exit1;
178 }
179 statep->drm_handle = handle;
180
181 /*
182 * After drm_supp_register, we can call drm_xxx routine
183 */
184 statep->drm_supported = DRM_UNSUPPORT;
185 if (drm_probe(statep, radeon_pciidlist) != DDI_SUCCESS) {
186 DRM_ERROR("radeon_open: "
187 "DRM current don't support this graphics card");
188 goto err_exit2;
189 }
190 statep->drm_supported = DRM_SUPPORT;
191
192 /* call common attach code */
193 if (drm_attach(statep) != DDI_SUCCESS) {
194 DRM_ERROR("radeon_attach: drm_attach failed");
195 goto err_exit2;
196 }
197 return (DDI_SUCCESS);
198
199 err_exit2:
200 (void) drm_supp_unregister(handle);
201 err_exit1:
202 (void) ddi_soft_state_free(radeon_statep, unit);
203 return (DDI_FAILURE);
204
205 } /* radeon_attach() */
206
207 static int
radeon_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)208 radeon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
209 {
210 drm_device_t *statep;
211 int unit;
212
213 if (cmd != DDI_DETACH)
214 return (DDI_FAILURE);
215
216 unit = ddi_get_instance(dip);
217 statep = ddi_get_soft_state(radeon_statep, unit);
218 if (statep == NULL)
219 return (DDI_FAILURE);
220
221 (void) drm_detach(statep);
222 (void) drm_supp_unregister(statep->drm_handle);
223 (void) ddi_soft_state_free(radeon_statep, unit);
224
225 return (DDI_SUCCESS);
226
227 } /* radeon_detach() */
228
229 /*ARGSUSED*/
230 static int
radeon_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)231 radeon_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
232 {
233 drm_device_t *statep;
234 int error = DDI_SUCCESS;
235 int unit;
236
237 unit = drm_dev_to_instance((dev_t)arg);
238 switch (infocmd) {
239 case DDI_INFO_DEVT2DEVINFO:
240 statep = ddi_get_soft_state(radeon_statep, unit);
241 if (statep == NULL || statep->dip == NULL) {
242 error = DDI_FAILURE;
243 } else {
244 *result = (void *) statep->dip;
245 error = DDI_SUCCESS;
246 }
247 break;
248 case DDI_INFO_DEVT2INSTANCE:
249 *result = (void *)(uintptr_t)unit;
250 error = DDI_SUCCESS;
251 break;
252 default:
253 error = DDI_FAILURE;
254 break;
255 }
256 return (error);
257
258 } /* radeon_info() */
259
260 static void
radeon_configure(drm_driver_t * driver)261 radeon_configure(drm_driver_t *driver)
262 {
263 driver->buf_priv_size = sizeof (drm_radeon_buf_priv_t);
264 driver->load = radeon_driver_load;
265 driver->unload = radeon_driver_unload;
266 driver->firstopen = radeon_driver_firstopen;
267 driver->open = radeon_driver_open;
268 driver->preclose = radeon_driver_preclose;
269 driver->postclose = radeon_driver_postclose;
270 driver->lastclose = radeon_driver_lastclose;
271 driver->vblank_wait = radeon_driver_vblank_wait;
272 driver->vblank_wait2 = radeon_driver_vblank_wait2;
273 driver->irq_preinstall = radeon_driver_irq_preinstall;
274 driver->irq_postinstall = radeon_driver_irq_postinstall;
275 driver->irq_uninstall = radeon_driver_irq_uninstall;
276 driver->irq_handler = radeon_driver_irq_handler;
277 driver->dma_ioctl = radeon_cp_buffers;
278
279 driver->driver_ioctls = radeon_ioctls;
280 driver->max_driver_ioctl = radeon_max_ioctl;
281
282 driver->driver_name = DRIVER_NAME;
283 driver->driver_desc = DRIVER_DESC;
284 driver->driver_date = DRIVER_DATE;
285 driver->driver_major = DRIVER_MAJOR;
286 driver->driver_minor = DRIVER_MINOR;
287 driver->driver_patchlevel = DRIVER_PATCHLEVEL;
288
289 driver->use_agp = 1;
290 driver->use_mtrr = 1;
291 driver->use_pci_dma = 1;
292 driver->use_sg = 1;
293 driver->use_dma = 1;
294 driver->use_irq = 1;
295 driver->use_vbl_irq = 1;
296 driver->use_vbl_irq2 = 1;
297
298 } /* radeon_configure() */
299