1 /* BEGIN CSTYLED */ 2 3 /* 4 * i915_drv.c -- Intel i915 driver -*- linux-c -*- 5 * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com 6 */ 7 8 /* 9 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 10 * All Rights Reserved. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice (including the next 20 * paragraph) shall be included in all copies or substantial portions of the 21 * Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 27 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29 * OTHER DEALINGS IN THE SOFTWARE. 30 * 31 * Authors: 32 * Gareth Hughes <gareth@valinux.com> 33 * 34 */ 35 36 /* 37 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 38 * Use is subject to license terms. 39 */ 40 41 /* 42 * I915 DRM Driver for Solaris 43 * 44 * This driver provides the hardware 3D acceleration support for Intel 45 * integrated video devices (e.g. i8xx/i915/i945 series chipsets), under the 46 * DRI (Direct Rendering Infrastructure). DRM (Direct Rendering Manager) here 47 * means the kernel device driver in DRI. 48 * 49 * I915 driver is a device dependent driver only, it depends on a misc module 50 * named drm for generic DRM operations. 51 */ 52 #pragma ident "%Z%%M% %I% %E% SMI" 53 54 #include "drmP.h" 55 #include "i915_drm.h" 56 #include "i915_drv.h" 57 #include "drm_pciids.h" 58 59 #define i915_max_ioctl 0x20 /* changed from 15 */ 60 61 62 /* 63 * cb_ops entrypoint 64 */ 65 extern struct cb_ops drm_cb_ops; 66 67 /* 68 * module entrypoint 69 */ 70 static int i915_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 71 static int i915_attach(dev_info_t *, ddi_attach_cmd_t); 72 static int i915_detach(dev_info_t *, ddi_detach_cmd_t); 73 74 75 /* drv_PCI_IDs comes from drm_pciids.h */ 76 static drm_pci_id_list_t i915_pciidlist[] = { 77 i915_PCI_IDS 78 }; 79 80 drm_ioctl_desc_t i915_ioctls[i915_max_ioctl]; 81 82 extern void i915_init_ioctl_arrays(void); 83 84 /* 85 * Local routines 86 */ 87 static void i915_configure(drm_driver_t *); 88 89 /* 90 * DRM driver 91 */ 92 static drm_driver_t i915_driver = {0}; 93 94 95 static struct dev_ops i915_dev_ops = { 96 DEVO_REV, /* devo_rev */ 97 0, /* devo_refcnt */ 98 i915_info, /* devo_getinfo */ 99 nulldev, /* devo_identify */ 100 nulldev, /* devo_probe */ 101 i915_attach, /* devo_attach */ 102 i915_detach, /* devo_detach */ 103 nodev, /* devo_reset */ 104 &drm_cb_ops, /* devo_cb_ops */ 105 NULL, /* devo_bus_ops */ 106 NULL /* power */ 107 }; 108 109 static struct modldrv modldrv = { 110 &mod_driverops, /* drv_modops */ 111 "I915 DRM driver %I%", /* drv_linkinfo */ 112 &i915_dev_ops, /* drv_dev_ops */ 113 }; 114 115 static struct modlinkage modlinkage = { 116 MODREV_1, (void *) &modldrv, NULL 117 }; 118 119 120 /* 121 * softstate head 122 */ 123 static void *i915_statep; 124 125 int 126 _init(void) 127 { 128 int error; 129 130 i915_configure(&i915_driver); 131 132 if ((error = ddi_soft_state_init(&i915_statep, 133 sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0) 134 return (error); 135 136 if ((error = mod_install(&modlinkage)) != 0) { 137 ddi_soft_state_fini(&i915_statep); 138 return (error); 139 } 140 141 return (error); 142 143 } /* _init() */ 144 145 int 146 _fini(void) 147 { 148 int error; 149 150 if ((error = mod_remove(&modlinkage)) != 0) 151 return (error); 152 153 (void) ddi_soft_state_fini(&i915_statep); 154 155 return (0); 156 157 } /* _fini() */ 158 159 int 160 _info(struct modinfo *modinfop) 161 { 162 return (mod_info(&modlinkage, modinfop)); 163 164 } /* _info() */ 165 166 static int 167 i915_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 168 { 169 drm_device_t *statep; 170 void *handle; 171 int unit; 172 173 if (cmd != DDI_ATTACH) { 174 DRM_ERROR("i915_attach: only attach op supported"); 175 return (DDI_FAILURE); 176 } 177 178 unit = ddi_get_instance(dip); 179 if (ddi_soft_state_zalloc(i915_statep, unit) != DDI_SUCCESS) { 180 cmn_err(CE_WARN, "i915_attach: failed to alloc softstate"); 181 return (DDI_FAILURE); 182 } 183 statep = ddi_get_soft_state(i915_statep, unit); 184 statep->dip = dip; 185 statep->driver = &i915_driver; 186 187 /* 188 * Call drm_supp_register to create minor nodes for us 189 */ 190 handle = drm_supp_register(dip, statep); 191 if ( handle == NULL) { 192 DRM_ERROR("i915_attach: drm_supp_register failed"); 193 goto err_exit1; 194 } 195 statep->drm_handle = handle; 196 197 /* 198 * After drm_supp_register, we can call drm_xxx routine 199 */ 200 statep->drm_supported = DRM_UNSUPPORT; 201 if (drm_probe(statep, i915_pciidlist) != DDI_SUCCESS) { 202 DRM_ERROR("i915_open: " 203 "DRM current don't support this graphics card"); 204 goto err_exit2; 205 } 206 statep->drm_supported = DRM_SUPPORT; 207 208 /* call common attach code */ 209 if (drm_attach(statep) != DDI_SUCCESS) { 210 DRM_ERROR("i915_attach: drm_attach failed"); 211 goto err_exit2; 212 } 213 return (DDI_SUCCESS); 214 215 err_exit2: 216 (void) drm_supp_unregister(handle); 217 err_exit1: 218 (void) ddi_soft_state_free(i915_statep, unit); 219 return (DDI_FAILURE); 220 221 } /* i915_attach() */ 222 223 static int 224 i915_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 225 { 226 drm_device_t *statep; 227 int unit; 228 229 if (cmd != DDI_DETACH) 230 return (DDI_FAILURE); 231 232 unit = ddi_get_instance(dip); 233 statep = ddi_get_soft_state(i915_statep, unit); 234 if (statep == NULL) 235 return (DDI_FAILURE); 236 237 (void) drm_detach(statep); 238 (void) drm_supp_unregister(statep->drm_handle); 239 (void) ddi_soft_state_free(i915_statep, unit); 240 241 return (DDI_SUCCESS); 242 243 } /* i915_detach() */ 244 245 246 /*ARGSUSED*/ 247 static int 248 i915_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 249 { 250 drm_device_t *statep; 251 int error = DDI_SUCCESS; 252 int unit; 253 254 unit = drm_dev_to_instance((dev_t)arg); 255 switch (infocmd) { 256 case DDI_INFO_DEVT2DEVINFO: 257 statep = ddi_get_soft_state(i915_statep, unit); 258 if (statep == NULL || statep->dip == NULL) { 259 error = DDI_FAILURE; 260 } else { 261 *result = (void *) statep->dip; 262 error = DDI_SUCCESS; 263 } 264 break; 265 case DDI_INFO_DEVT2INSTANCE: 266 *result = (void *)(uintptr_t)unit; 267 error = DDI_SUCCESS; 268 break; 269 default: 270 error = DDI_FAILURE; 271 break; 272 } 273 return (error); 274 275 } /* i915_info() */ 276 277 278 static void i915_configure(drm_driver_t *driver) 279 { 280 i915_init_ioctl_arrays(); 281 282 driver->buf_priv_size = 1; /* No dev_priv */ 283 driver->load = i915_driver_load; 284 driver->unload = i915_driver_unload; 285 driver->preclose = i915_driver_preclose; 286 driver->lastclose = i915_driver_lastclose; 287 driver->device_is_agp = i915_driver_device_is_agp; 288 driver->vblank_wait = i915_driver_vblank_wait; 289 driver->vblank_wait2 = i915_driver_vblank_wait2; 290 driver->irq_preinstall = i915_driver_irq_preinstall; 291 driver->irq_postinstall = i915_driver_irq_postinstall; 292 driver->irq_uninstall = i915_driver_irq_uninstall; 293 driver->irq_handler = i915_driver_irq_handler; 294 295 driver->driver_ioctls = i915_ioctls; 296 driver->max_driver_ioctl = i915_max_ioctl; 297 298 driver->driver_name = DRIVER_NAME; 299 driver->driver_desc = DRIVER_DESC; 300 driver->driver_date = DRIVER_DATE; 301 driver->driver_major = DRIVER_MAJOR; 302 driver->driver_minor = DRIVER_MINOR; 303 driver->driver_patchlevel = DRIVER_PATCHLEVEL; 304 305 driver->use_agp = 1; 306 driver->require_agp = 1; 307 driver->use_irq = 1; 308 driver->use_vbl_irq = 1; 309 driver->use_vbl_irq2 = 1; 310 } 311