kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 1 | /* |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 2 | * drm_drv.h -- Generic driver template -*- linux-c -*- |
| 3 | * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com |
| 4 | */ |
| 5 | /* |
| 6 | * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. |
| 7 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 8 | * Copyright (c) 2009, Intel Corporation. |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 9 | * All Rights Reserved. |
| 10 | * |
| 11 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 12 | * copy of this software and associated documentation files (the "Software"), |
| 13 | * to deal in the Software without restriction, including without limitation |
| 14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 15 | * and/or sell copies of the Software, and to permit persons to whom the |
| 16 | * Software is furnished to do so, subject to the following conditions: |
| 17 | * |
| 18 | * The above copyright notice and this permission notice (including the next |
| 19 | * paragraph) shall be included in all copies or substantial portions of the |
| 20 | * Software. |
| 21 | * |
| 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 25 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 26 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 27 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 28 | * OTHER DEALINGS IN THE SOFTWARE. |
| 29 | * |
| 30 | * Authors: |
| 31 | * Rickard E. (Rik) Faith <faith@valinux.com> |
| 32 | * Gareth Hughes <gareth@valinux.com> |
| 33 | * |
| 34 | */ |
| 35 | |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 36 | /* |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 37 | * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 38 | * Use is subject to license terms. |
| 39 | */ |
| 40 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 41 | #include "drmP.h" |
| 42 | #include "drm.h" |
| 43 | #include "drm_sarea.h" |
| 44 | |
| 45 | int drm_debug_flag = 1; |
| 46 | |
| 47 | #define DRIVER_IOCTL_COUNT 256 |
miao chen - Sun Microsystems - Beijing China | ee33b1b | 2008-11-06 13:34:06 +0800 | [diff] [blame] | 48 | drm_ioctl_desc_t drm_ioctls[DRIVER_IOCTL_COUNT] = { |
| 49 | [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = |
| 50 | {drm_version, 0}, |
| 51 | [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = |
| 52 | {drm_getunique, 0}, |
| 53 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = |
| 54 | {drm_getmagic, 0}, |
| 55 | [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = |
| 56 | {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY}, |
| 57 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = |
| 58 | {drm_getmap, 0}, |
| 59 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = |
| 60 | {drm_getclient, 0}, |
| 61 | [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = |
| 62 | {drm_getstats, 0}, |
| 63 | [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = |
| 64 | {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY}, |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 65 | [DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL)] = |
| 66 | {drm_modeset_ctl, 0}, |
| 67 | [DRM_IOCTL_NR(DRM_IOCTL_GEM_CLOSE)] = |
| 68 | {drm_gem_close_ioctl, 0}, |
| 69 | [DRM_IOCTL_NR(DRM_IOCTL_GEM_FLINK)] = |
| 70 | {drm_gem_flink_ioctl, DRM_AUTH}, |
| 71 | [DRM_IOCTL_NR(DRM_IOCTL_GEM_OPEN)] = |
| 72 | {drm_gem_open_ioctl, DRM_AUTH}, |
miao chen - Sun Microsystems - Beijing China | ee33b1b | 2008-11-06 13:34:06 +0800 | [diff] [blame] | 73 | [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = |
| 74 | {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 75 | [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = |
| 76 | {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 77 | [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = |
| 78 | {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 79 | [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = |
| 80 | {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 81 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = |
| 82 | {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 83 | [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = |
| 84 | {drm_rmmap_ioctl, DRM_AUTH}, |
| 85 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = |
| 86 | {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 87 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = |
| 88 | {drm_getsareactx, DRM_AUTH}, |
| 89 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = |
| 90 | {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 91 | [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = |
| 92 | {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 93 | [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = |
| 94 | {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 95 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = |
| 96 | {drm_getctx, DRM_AUTH}, |
| 97 | [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = |
| 98 | {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 99 | [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = |
| 100 | {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 101 | [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = |
| 102 | {drm_resctx, DRM_AUTH}, |
| 103 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = |
| 104 | {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 105 | [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = |
| 106 | {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 107 | [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = |
| 108 | {drm_lock, DRM_AUTH}, |
| 109 | [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = |
| 110 | {drm_unlock, DRM_AUTH}, |
| 111 | [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = |
| 112 | {drm_noop, DRM_AUTH}, |
| 113 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = |
| 114 | {drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 115 | [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = |
| 116 | {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 117 | [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = |
| 118 | {drm_infobufs, DRM_AUTH}, |
| 119 | [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = |
| 120 | {drm_mapbufs, DRM_AUTH}, |
| 121 | [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = |
| 122 | {drm_freebufs, DRM_AUTH}, |
| 123 | [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = |
| 124 | {drm_dma, DRM_AUTH}, |
| 125 | [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = |
| 126 | {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 127 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = |
| 128 | {drm_agp_acquire, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 129 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = |
| 130 | {drm_agp_release, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 131 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = |
| 132 | {drm_agp_enable, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 133 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = |
| 134 | {drm_agp_info, DRM_AUTH}, |
| 135 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = |
| 136 | {drm_agp_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 137 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = |
| 138 | {drm_agp_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 139 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = |
| 140 | {drm_agp_bind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 141 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = |
| 142 | {drm_agp_unbind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 143 | [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = |
| 144 | {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 145 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = |
| 146 | {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 147 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = |
| 148 | {drm_wait_vblank, 0}, |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 149 | [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = |
| 150 | {drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
miao chen - Sun Microsystems - Beijing China | ee33b1b | 2008-11-06 13:34:06 +0800 | [diff] [blame] | 151 | }; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 152 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 153 | extern void idr_list_free(struct idr_list *head); |
| 154 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 155 | const char * |
| 156 | drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist) |
| 157 | { |
| 158 | int i = 0; |
| 159 | for (i = 0; idlist[i].vendor != 0; i++) { |
| 160 | if ((idlist[i].vendor == vendor) && |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 161 | (idlist[i].device == device)) { |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 162 | return (idlist[i].name); |
| 163 | } |
| 164 | } |
| 165 | return ((char *)NULL); |
| 166 | } |
| 167 | |
| 168 | static int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 169 | drm_firstopen(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 170 | { |
| 171 | int i; |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 172 | int retval; |
| 173 | drm_local_map_t *map; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 174 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 175 | /* prebuild the SAREA */ |
| 176 | retval = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, |
| 177 | _DRM_CONTAINS_LOCK, &map); |
| 178 | if (retval != 0) { |
| 179 | DRM_ERROR("firstopen: failed to prebuild SAREA"); |
| 180 | return (retval); |
| 181 | } |
| 182 | |
| 183 | if (dev->driver->use_agp) { |
| 184 | DRM_DEBUG("drm_firstopen: use_agp=%d", dev->driver->use_agp); |
| 185 | if (drm_device_is_agp(dev)) |
| 186 | dev->agp = drm_agp_init(dev); |
| 187 | if (dev->driver->require_agp && dev->agp == NULL) { |
| 188 | DRM_ERROR("couldn't initialize AGP"); |
| 189 | return (EIO); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | if (dev->driver->firstopen) |
| 194 | retval = dev->driver->firstopen(dev); |
| 195 | |
| 196 | if (retval != 0) { |
| 197 | DRM_ERROR("drm_firstopen: driver-specific firstopen failed"); |
| 198 | return (retval); |
| 199 | } |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 200 | |
| 201 | dev->buf_use = 0; |
| 202 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 203 | if (dev->driver->use_dma) { |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 204 | i = drm_dma_setup(dev); |
| 205 | if (i != 0) |
| 206 | return (i); |
| 207 | } |
| 208 | dev->counters = 6; |
| 209 | dev->types[0] = _DRM_STAT_LOCK; |
| 210 | dev->types[1] = _DRM_STAT_OPENS; |
| 211 | dev->types[2] = _DRM_STAT_CLOSES; |
| 212 | dev->types[3] = _DRM_STAT_IOCTLS; |
| 213 | dev->types[4] = _DRM_STAT_LOCKS; |
| 214 | dev->types[5] = _DRM_STAT_UNLOCKS; |
| 215 | |
| 216 | for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) |
| 217 | *(&dev->counts[i]) = 0; |
| 218 | |
| 219 | for (i = 0; i < DRM_HASH_SIZE; i++) { |
| 220 | dev->magiclist[i].head = NULL; |
| 221 | dev->magiclist[i].tail = NULL; |
| 222 | } |
| 223 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 224 | dev->irq_enabled = 0; |
| 225 | dev->context_flag = 0; |
| 226 | dev->last_context = 0; |
| 227 | dev->if_version = 0; |
| 228 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 229 | return (0); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | /* Free resources associated with the DRM on the last close. */ |
| 233 | static int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 234 | drm_lastclose(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 235 | { |
| 236 | drm_magic_entry_t *pt, *next; |
| 237 | drm_local_map_t *map, *mapsave; |
| 238 | int i; |
| 239 | |
| 240 | DRM_SPINLOCK_ASSERT(&dev->dev_lock); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 241 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 242 | if (dev->driver->lastclose != NULL) |
| 243 | dev->driver->lastclose(dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 244 | |
| 245 | if (dev->irq_enabled) |
| 246 | (void) drm_irq_uninstall(dev); |
| 247 | |
| 248 | if (dev->unique) { |
| 249 | drm_free(dev->unique, dev->unique_len + 1, DRM_MEM_DRIVER); |
| 250 | dev->unique = NULL; |
| 251 | dev->unique_len = 0; |
| 252 | } |
| 253 | |
| 254 | /* Clear pid list */ |
| 255 | for (i = 0; i < DRM_HASH_SIZE; i++) { |
| 256 | for (pt = dev->magiclist[i].head; pt; pt = next) { |
| 257 | next = pt->next; |
| 258 | drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC); |
| 259 | } |
| 260 | dev->magiclist[i].head = dev->magiclist[i].tail = NULL; |
| 261 | } |
| 262 | |
| 263 | /* Clear AGP information */ |
| 264 | if (dev->agp) { |
| 265 | drm_agp_mem_t *entry; |
| 266 | drm_agp_mem_t *nexte; |
| 267 | |
| 268 | /* |
| 269 | * Remove AGP resources, but leave dev->agp |
| 270 | * intact until drm_cleanup is called. |
| 271 | */ |
| 272 | for (entry = dev->agp->memory; entry; entry = nexte) { |
| 273 | nexte = entry->next; |
| 274 | if (entry->bound) |
| 275 | (void) drm_agp_unbind_memory( |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 276 | (unsigned long)entry->handle, dev); |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 277 | (void) drm_agp_free_memory(entry->handle, dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 278 | drm_free(entry, sizeof (*entry), DRM_MEM_AGPLISTS); |
| 279 | } |
| 280 | dev->agp->memory = NULL; |
| 281 | |
| 282 | if (dev->agp->acquired) |
| 283 | (void) drm_agp_do_release(dev); |
| 284 | |
| 285 | dev->agp->acquired = 0; |
| 286 | dev->agp->enabled = 0; |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 287 | drm_agp_fini(dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 288 | } |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 289 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 290 | if (dev->sg != NULL) { |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 291 | drm_sg_mem_t *entry; |
| 292 | entry = dev->sg; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 293 | dev->sg = NULL; |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 294 | drm_sg_cleanup(dev, entry); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 295 | } |
| 296 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 297 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 298 | /* Clean up maps that weren't set up by the driver. */ |
| 299 | TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) { |
| 300 | if (!map->kernel_owned) |
| 301 | drm_rmmap(dev, map); |
| 302 | } |
| 303 | |
| 304 | drm_dma_takedown(dev); |
| 305 | if (dev->lock.hw_lock) { |
| 306 | dev->lock.hw_lock = NULL; /* SHM removed */ |
| 307 | dev->lock.filp = NULL; |
| 308 | |
| 309 | mutex_enter(&(dev->lock.lock_mutex)); |
| 310 | cv_broadcast(&(dev->lock.lock_cv)); |
| 311 | mutex_exit(&(dev->lock.lock_mutex)); |
| 312 | } |
| 313 | |
| 314 | return (0); |
| 315 | } |
| 316 | |
| 317 | static int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 318 | drm_load(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 319 | { |
| 320 | int retcode; |
| 321 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 322 | cv_init(&(dev->lock.lock_cv), NULL, CV_DRIVER, NULL); |
| 323 | mutex_init(&(dev->lock.lock_mutex), NULL, MUTEX_DRIVER, NULL); |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 324 | mutex_init(&(dev->dev_lock), "drmdev", MUTEX_DRIVER, NULL); |
| 325 | mutex_init(&dev->irq_lock, "drmirq", MUTEX_DRIVER, |
| 326 | (void *)dev->intr_block); |
| 327 | mutex_init(&dev->drw_lock, "drmdrw", MUTEX_DRIVER, NULL); |
| 328 | mutex_init(&dev->tasklet_lock, "drmtsk", MUTEX_DRIVER, NULL); |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 329 | |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 330 | dev->irq = pci_get_irq(dev); |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 331 | dev->pci_vendor = pci_get_vendor(dev); |
| 332 | dev->pci_device = pci_get_device(dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 333 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 334 | TAILQ_INIT(&dev->maplist); |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 335 | TAILQ_INIT(&dev->minordevs); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 336 | TAILQ_INIT(&dev->files); |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 337 | if (dev->driver->load != NULL) { |
| 338 | retcode = dev->driver->load(dev, 0); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 339 | if (retcode != 0) { |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 340 | DRM_ERROR("drm_load: failed\n"); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 341 | goto error; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | retcode = drm_ctxbitmap_init(dev); |
| 346 | if (retcode != 0) { |
| 347 | DRM_ERROR("drm_load: Cannot allocate memory for ctx bitmap"); |
| 348 | goto error; |
| 349 | } |
| 350 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 351 | if (dev->driver->use_gem == 1) { |
| 352 | retcode = drm_gem_init(dev); |
| 353 | if (retcode) { |
| 354 | DRM_ERROR("Cannot initialize graphics execution " |
| 355 | "manager (GEM)\n"); |
| 356 | goto error; |
| 357 | } |
| 358 | } |
| 359 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 360 | if (drm_init_kstats(dev)) { |
| 361 | DRM_ERROR("drm_attach => drm_load: init kstats error"); |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 362 | retcode = EFAULT; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 363 | goto error; |
| 364 | } |
| 365 | |
| 366 | DRM_INFO("!drm: Initialized %s %d.%d.%d %s ", |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 367 | dev->driver->driver_name, |
| 368 | dev->driver->driver_major, |
| 369 | dev->driver->driver_minor, |
| 370 | dev->driver->driver_patchlevel, |
| 371 | dev->driver->driver_date); |
| 372 | return (0); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 373 | |
| 374 | error: |
| 375 | DRM_LOCK(); |
| 376 | (void) drm_lastclose(dev); |
| 377 | DRM_UNLOCK(); |
| 378 | cv_destroy(&(dev->lock.lock_cv)); |
| 379 | mutex_destroy(&(dev->lock.lock_mutex)); |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 380 | mutex_destroy(&dev->irq_lock); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 381 | mutex_destroy(&(dev->dev_lock)); |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 382 | mutex_destroy(&dev->drw_lock); |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 383 | mutex_destroy(&dev->tasklet_lock); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 384 | |
| 385 | return (retcode); |
| 386 | } |
| 387 | |
| 388 | /* called when cleanup this module */ |
| 389 | static void |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 390 | drm_unload(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 391 | { |
| 392 | drm_local_map_t *map; |
| 393 | |
Edward Shu | 8566479 | 2009-03-30 08:56:42 +0800 | [diff] [blame] | 394 | drm_vblank_cleanup(dev); |
| 395 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 396 | drm_ctxbitmap_cleanup(dev); |
| 397 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 398 | if (dev->driver->use_gem == 1) { |
| 399 | idr_list_free(&dev->object_name_idr); |
| 400 | mutex_destroy(&dev->object_name_lock); |
| 401 | } |
| 402 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 403 | DRM_LOCK(); |
| 404 | (void) drm_lastclose(dev); |
| 405 | DRM_UNLOCK(); |
| 406 | |
| 407 | while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) { |
| 408 | drm_rmmap(dev, map); |
| 409 | } |
| 410 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 411 | if (dev->driver->unload != NULL) |
| 412 | dev->driver->unload(dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 413 | |
| 414 | drm_mem_uninit(); |
| 415 | cv_destroy(&dev->lock.lock_cv); |
| 416 | mutex_destroy(&dev->lock.lock_mutex); |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 417 | mutex_destroy(&dev->irq_lock); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 418 | mutex_destroy(&dev->dev_lock); |
zw161486 | e92e3a8 | 2007-05-09 19:58:49 -0700 | [diff] [blame] | 419 | mutex_destroy(&dev->drw_lock); |
miao chen - Sun Microsystems - Beijing China | d023107 | 2009-02-17 16:22:10 +0800 | [diff] [blame] | 420 | mutex_destroy(&dev->tasklet_lock); |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 421 | |
| 422 | dev->gtt_total = 0; |
| 423 | atomic_set(&dev->pin_memory, 0); |
| 424 | DRM_ERROR("drm_unload"); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 425 | } |
| 426 | |
| 427 | |
| 428 | /*ARGSUSED*/ |
| 429 | int |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 430 | drm_open(drm_device_t *dev, drm_cminor_t *mp, int openflags, |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 431 | int otyp, cred_t *credp) |
| 432 | { |
| 433 | int retcode; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 434 | |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 435 | retcode = drm_open_helper(dev, mp, openflags, otyp, credp); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 436 | |
| 437 | if (!retcode) { |
| 438 | atomic_inc_32(&dev->counts[_DRM_STAT_OPENS]); |
| 439 | DRM_LOCK(); |
| 440 | if (!dev->open_count ++) |
| 441 | retcode = drm_firstopen(dev); |
| 442 | DRM_UNLOCK(); |
| 443 | } |
| 444 | |
| 445 | return (retcode); |
| 446 | } |
| 447 | |
| 448 | /*ARGSUSED*/ |
| 449 | int |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 450 | drm_close(drm_device_t *dev, int minor, int flag, int otyp, |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 451 | cred_t *credp) |
| 452 | { |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 453 | drm_cminor_t *mp; |
| 454 | drm_file_t *fpriv; |
| 455 | int retcode = 0; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 456 | |
| 457 | DRM_LOCK(); |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 458 | mp = drm_find_file_by_minor(dev, minor); |
| 459 | if (!mp) { |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 460 | DRM_UNLOCK(); |
| 461 | DRM_ERROR("drm_close: can't find authenticator"); |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 462 | return (EACCES); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 463 | } |
| 464 | |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 465 | fpriv = mp->fpriv; |
| 466 | ASSERT(fpriv); |
| 467 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 468 | if (--fpriv->refs != 0) |
| 469 | goto done; |
| 470 | |
| 471 | if (dev->driver->preclose != NULL) |
| 472 | dev->driver->preclose(dev, fpriv); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 473 | |
| 474 | /* |
| 475 | * Begin inline drm_release |
| 476 | */ |
| 477 | DRM_DEBUG("drm_close :pid = %d , open_count = %d", |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 478 | DRM_CURRENTPID, dev->open_count); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 479 | |
| 480 | if (dev->lock.hw_lock && |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 481 | _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && |
| 482 | dev->lock.filp == fpriv) { |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 483 | DRM_DEBUG("Process %d dead, freeing lock for context %d", |
| 484 | DRM_CURRENTPID, |
| 485 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 486 | if (dev->driver->reclaim_buffers_locked != NULL) |
| 487 | dev->driver->reclaim_buffers_locked(dev, fpriv); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 488 | (void) drm_lock_free(dev, &dev->lock.hw_lock->lock, |
| 489 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 490 | } else if (dev->driver->reclaim_buffers_locked != NULL && |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 491 | dev->lock.hw_lock != NULL) { |
| 492 | DRM_ERROR("drm_close: " |
| 493 | "retake lock not implemented yet"); |
| 494 | } |
| 495 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 496 | if (dev->driver->use_dma) { |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 497 | drm_reclaim_buffers(dev, fpriv); |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 498 | } |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 499 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 500 | if (dev->driver->use_gem == 1) { |
| 501 | drm_gem_release(dev, fpriv); |
| 502 | } |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 503 | |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 504 | if (dev->driver->postclose != NULL) { |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 505 | dev->driver->postclose(dev, fpriv); |
miao chen - Sun Microsystems - Beijing China | 0035d21 | 2009-12-05 13:25:40 +0800 | [diff] [blame] | 506 | } |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 507 | TAILQ_REMOVE(&dev->files, fpriv, link); |
| 508 | drm_free(fpriv, sizeof (*fpriv), DRM_MEM_FILES); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 509 | |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 510 | done: |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 511 | atomic_inc_32(&dev->counts[_DRM_STAT_CLOSES]); |
| 512 | |
cg149915 | fca314a | 2008-02-28 20:09:48 -0800 | [diff] [blame] | 513 | TAILQ_REMOVE(&dev->minordevs, mp, link); |
| 514 | drm_free(mp, sizeof (*mp), DRM_MEM_FILES); |
| 515 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 516 | if (--dev->open_count == 0) { |
| 517 | retcode = drm_lastclose(dev); |
| 518 | } |
| 519 | DRM_UNLOCK(); |
| 520 | |
| 521 | return (retcode); |
| 522 | } |
| 523 | |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 524 | int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 525 | drm_attach(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 526 | { |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 527 | return (drm_load(dev)); |
| 528 | } |
| 529 | |
| 530 | int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 531 | drm_detach(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 532 | { |
| 533 | drm_unload(dev); |
| 534 | drm_fini_kstats(dev); |
| 535 | return (DDI_SUCCESS); |
| 536 | } |
| 537 | |
| 538 | static int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 539 | drm_get_businfo(drm_device_t *dev) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 540 | { |
| 541 | dev->irq = pci_get_irq(dev); |
| 542 | if (dev->irq == -1) { |
| 543 | DRM_ERROR("drm_get_businfo: get irq error"); |
| 544 | return (DDI_FAILURE); |
| 545 | } |
| 546 | /* XXX Fix domain number (alpha hoses) */ |
| 547 | dev->pci_domain = 0; |
| 548 | if (pci_get_info(dev, &dev->pci_bus, |
| 549 | &dev->pci_slot, &dev->pci_func) != DDI_SUCCESS) { |
| 550 | DRM_ERROR("drm_get_businfo: get bus slot func error "); |
| 551 | return (DDI_FAILURE); |
| 552 | } |
| 553 | DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d", |
| 554 | dev->pci_bus, dev->pci_slot, dev->pci_func); |
| 555 | return (DDI_SUCCESS); |
| 556 | } |
| 557 | |
| 558 | int |
cg149915 | d0538f6 | 2008-01-09 19:45:15 -0800 | [diff] [blame] | 559 | drm_probe(drm_device_t *dev, drm_pci_id_list_t *idlist) |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 560 | { |
| 561 | const char *s = NULL; |
| 562 | int vendor, device; |
| 563 | |
| 564 | vendor = pci_get_vendor(dev); |
| 565 | device = pci_get_device(dev); |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 566 | |
| 567 | s = drm_find_description(vendor, device, idlist); |
| 568 | if (s != NULL) { |
| 569 | dev->desc = s; |
kz151634 | 60405de | 2006-09-28 01:41:18 -0700 | [diff] [blame] | 570 | if (drm_get_businfo(dev) != DDI_SUCCESS) { |
| 571 | DRM_ERROR("drm_probe: drm get bus info error"); |
| 572 | return (DDI_FAILURE); |
| 573 | } |
| 574 | return (DDI_SUCCESS); |
| 575 | } |
| 576 | return (DDI_FAILURE); |
| 577 | } |