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