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