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 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 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 142 _info(struct modinfo *modinfop) 143 { 144 return (mod_info(&modlinkage, modinfop)); 145 146 } /* _info() */ 147 148 149 static int 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 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 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 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() */