160405de4Skz151634 /*
260405de4Skz151634 * drm_drv.h -- Generic driver template -*- linux-c -*-
360405de4Skz151634 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
460405de4Skz151634 */
560405de4Skz151634 /*
660405de4Skz151634 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
760405de4Skz151634 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8*0035d21cSmiao chen - Sun Microsystems - Beijing China * Copyright (c) 2009, Intel Corporation.
960405de4Skz151634 * All Rights Reserved.
1060405de4Skz151634 *
1160405de4Skz151634 * Permission is hereby granted, free of charge, to any person obtaining a
1260405de4Skz151634 * copy of this software and associated documentation files (the "Software"),
1360405de4Skz151634 * to deal in the Software without restriction, including without limitation
1460405de4Skz151634 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1560405de4Skz151634 * and/or sell copies of the Software, and to permit persons to whom the
1660405de4Skz151634 * Software is furnished to do so, subject to the following conditions:
1760405de4Skz151634 *
1860405de4Skz151634 * The above copyright notice and this permission notice (including the next
1960405de4Skz151634 * paragraph) shall be included in all copies or substantial portions of the
2060405de4Skz151634 * Software.
2160405de4Skz151634 *
2260405de4Skz151634 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2360405de4Skz151634 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2460405de4Skz151634 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2560405de4Skz151634 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2660405de4Skz151634 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2760405de4Skz151634 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2860405de4Skz151634 * OTHER DEALINGS IN THE SOFTWARE.
2960405de4Skz151634 *
3060405de4Skz151634 * Authors:
3160405de4Skz151634 * Rickard E. (Rik) Faith <faith@valinux.com>
3260405de4Skz151634 * Gareth Hughes <gareth@valinux.com>
3360405de4Skz151634 *
3460405de4Skz151634 */
3560405de4Skz151634
36e92e3a86Szw161486 /*
37d0231070Smiao chen - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
38e92e3a86Szw161486 * Use is subject to license terms.
39e92e3a86Szw161486 */
40e92e3a86Szw161486
4160405de4Skz151634 #include "drmP.h"
4260405de4Skz151634 #include "drm.h"
4360405de4Skz151634 #include "drm_sarea.h"
4460405de4Skz151634
4560405de4Skz151634 int drm_debug_flag = 1;
4660405de4Skz151634
4760405de4Skz151634 #define DRIVER_IOCTL_COUNT 256
48ee33b1b8Smiao chen - Sun Microsystems - Beijing China drm_ioctl_desc_t drm_ioctls[DRIVER_IOCTL_COUNT] = {
49ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] =
50ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_version, 0},
51ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] =
52ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getunique, 0},
53ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] =
54ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getmagic, 0},
55ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] =
56ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
57ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] =
58ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getmap, 0},
59ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] =
60ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getclient, 0},
61ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] =
62ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getstats, 0},
63ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] =
64ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
65*0035d21cSmiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_MODESET_CTL)] =
66*0035d21cSmiao chen - Sun Microsystems - Beijing China {drm_modeset_ctl, 0},
67*0035d21cSmiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GEM_CLOSE)] =
68*0035d21cSmiao chen - Sun Microsystems - Beijing China {drm_gem_close_ioctl, 0},
69*0035d21cSmiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GEM_FLINK)] =
70*0035d21cSmiao chen - Sun Microsystems - Beijing China {drm_gem_flink_ioctl, DRM_AUTH},
71*0035d21cSmiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GEM_OPEN)] =
72*0035d21cSmiao chen - Sun Microsystems - Beijing China {drm_gem_open_ioctl, DRM_AUTH},
73ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] =
74ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
75ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] =
76ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
77ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] =
78ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
79ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] =
80ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
81ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] =
82ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
83ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] =
84ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_rmmap_ioctl, DRM_AUTH},
85ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] =
86ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
87ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] =
88ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getsareactx, DRM_AUTH},
89ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] =
90ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
91ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] =
92ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
93ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] =
94ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
95ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] =
96ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_getctx, DRM_AUTH},
97ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] =
98ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
99ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] =
100ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
101ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] =
102ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_resctx, DRM_AUTH},
103ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] =
104ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
105ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] =
106ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
107ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] =
108ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_lock, DRM_AUTH},
109ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] =
110ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_unlock, DRM_AUTH},
111ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] =
112ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_noop, DRM_AUTH},
113ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] =
114ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
115ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] =
116ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
117ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] =
118ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_infobufs, DRM_AUTH},
119ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] =
120ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_mapbufs, DRM_AUTH},
121ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] =
122ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_freebufs, DRM_AUTH},
123ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_DMA)] =
124ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_dma, DRM_AUTH},
125ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] =
126ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
127ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] =
128ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_acquire, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
129ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] =
130ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_release, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
131ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] =
132ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_enable, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
133ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] =
134ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_info, DRM_AUTH},
135ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] =
136ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
137ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] =
138ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
139ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] =
140ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_bind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
141ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] =
142ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_agp_unbind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
143ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] =
144ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
145ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] =
146ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
147ee33b1b8Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] =
148ee33b1b8Smiao chen - Sun Microsystems - Beijing China {drm_wait_vblank, 0},
149d0231070Smiao chen - Sun Microsystems - Beijing China [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] =
150d0231070Smiao chen - Sun Microsystems - Beijing China {drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
151ee33b1b8Smiao chen - Sun Microsystems - Beijing China };
15260405de4Skz151634
153*0035d21cSmiao chen - Sun Microsystems - Beijing China extern void idr_list_free(struct idr_list *head);
154*0035d21cSmiao chen - Sun Microsystems - Beijing China
15560405de4Skz151634 const char *
drm_find_description(int vendor,int device,drm_pci_id_list_t * idlist)15660405de4Skz151634 drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist)
15760405de4Skz151634 {
15860405de4Skz151634 int i = 0;
15960405de4Skz151634 for (i = 0; idlist[i].vendor != 0; i++) {
16060405de4Skz151634 if ((idlist[i].vendor == vendor) &&
16160405de4Skz151634 (idlist[i].device == device)) {
16260405de4Skz151634 return (idlist[i].name);
16360405de4Skz151634 }
16460405de4Skz151634 }
16560405de4Skz151634 return ((char *)NULL);
16660405de4Skz151634 }
16760405de4Skz151634
16860405de4Skz151634 static int
drm_firstopen(drm_device_t * dev)169d0538f66Scg149915 drm_firstopen(drm_device_t *dev)
17060405de4Skz151634 {
17160405de4Skz151634 int i;
172d0538f66Scg149915 int retval;
173d0538f66Scg149915 drm_local_map_t *map;
17460405de4Skz151634
175d0538f66Scg149915 /* prebuild the SAREA */
176d0538f66Scg149915 retval = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
177d0538f66Scg149915 _DRM_CONTAINS_LOCK, &map);
178d0538f66Scg149915 if (retval != 0) {
179d0538f66Scg149915 DRM_ERROR("firstopen: failed to prebuild SAREA");
180d0538f66Scg149915 return (retval);
181d0538f66Scg149915 }
182d0538f66Scg149915
183d0538f66Scg149915 if (dev->driver->use_agp) {
184d0538f66Scg149915 DRM_DEBUG("drm_firstopen: use_agp=%d", dev->driver->use_agp);
185d0538f66Scg149915 if (drm_device_is_agp(dev))
186d0538f66Scg149915 dev->agp = drm_agp_init(dev);
187d0538f66Scg149915 if (dev->driver->require_agp && dev->agp == NULL) {
188d0538f66Scg149915 DRM_ERROR("couldn't initialize AGP");
189d0538f66Scg149915 return (EIO);
190d0538f66Scg149915 }
191d0538f66Scg149915 }
192d0538f66Scg149915
193d0538f66Scg149915 if (dev->driver->firstopen)
194d0538f66Scg149915 retval = dev->driver->firstopen(dev);
195d0538f66Scg149915
196d0538f66Scg149915 if (retval != 0) {
197d0538f66Scg149915 DRM_ERROR("drm_firstopen: driver-specific firstopen failed");
198d0538f66Scg149915 return (retval);
199d0538f66Scg149915 }
20060405de4Skz151634
20160405de4Skz151634 dev->buf_use = 0;
20260405de4Skz151634
203d0538f66Scg149915 if (dev->driver->use_dma) {
20460405de4Skz151634 i = drm_dma_setup(dev);
20560405de4Skz151634 if (i != 0)
20660405de4Skz151634 return (i);
20760405de4Skz151634 }
20860405de4Skz151634 dev->counters = 6;
20960405de4Skz151634 dev->types[0] = _DRM_STAT_LOCK;
21060405de4Skz151634 dev->types[1] = _DRM_STAT_OPENS;
21160405de4Skz151634 dev->types[2] = _DRM_STAT_CLOSES;
21260405de4Skz151634 dev->types[3] = _DRM_STAT_IOCTLS;
21360405de4Skz151634 dev->types[4] = _DRM_STAT_LOCKS;
21460405de4Skz151634 dev->types[5] = _DRM_STAT_UNLOCKS;
21560405de4Skz151634
21660405de4Skz151634 for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
21760405de4Skz151634 *(&dev->counts[i]) = 0;
21860405de4Skz151634
21960405de4Skz151634 for (i = 0; i < DRM_HASH_SIZE; i++) {
22060405de4Skz151634 dev->magiclist[i].head = NULL;
22160405de4Skz151634 dev->magiclist[i].tail = NULL;
22260405de4Skz151634 }
22360405de4Skz151634
22460405de4Skz151634 dev->irq_enabled = 0;
22560405de4Skz151634 dev->context_flag = 0;
22660405de4Skz151634 dev->last_context = 0;
22760405de4Skz151634 dev->if_version = 0;
22860405de4Skz151634
229d0538f66Scg149915 return (0);
23060405de4Skz151634 }
23160405de4Skz151634
23260405de4Skz151634 /* Free resources associated with the DRM on the last close. */
23360405de4Skz151634 static int
drm_lastclose(drm_device_t * dev)234d0538f66Scg149915 drm_lastclose(drm_device_t *dev)
23560405de4Skz151634 {
23660405de4Skz151634 drm_magic_entry_t *pt, *next;
23760405de4Skz151634 drm_local_map_t *map, *mapsave;
23860405de4Skz151634 int i;
23960405de4Skz151634
24060405de4Skz151634 DRM_SPINLOCK_ASSERT(&dev->dev_lock);
24160405de4Skz151634
242d0538f66Scg149915 if (dev->driver->lastclose != NULL)
243d0538f66Scg149915 dev->driver->lastclose(dev);
24460405de4Skz151634
24560405de4Skz151634 if (dev->irq_enabled)
24660405de4Skz151634 (void) drm_irq_uninstall(dev);
24760405de4Skz151634
24860405de4Skz151634 if (dev->unique) {
24960405de4Skz151634 drm_free(dev->unique, dev->unique_len + 1, DRM_MEM_DRIVER);
25060405de4Skz151634 dev->unique = NULL;
25160405de4Skz151634 dev->unique_len = 0;
25260405de4Skz151634 }
25360405de4Skz151634
25460405de4Skz151634 /* Clear pid list */
25560405de4Skz151634 for (i = 0; i < DRM_HASH_SIZE; i++) {
25660405de4Skz151634 for (pt = dev->magiclist[i].head; pt; pt = next) {
25760405de4Skz151634 next = pt->next;
25860405de4Skz151634 drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC);
25960405de4Skz151634 }
26060405de4Skz151634 dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
26160405de4Skz151634 }
26260405de4Skz151634
26360405de4Skz151634 /* Clear AGP information */
26460405de4Skz151634 if (dev->agp) {
26560405de4Skz151634 drm_agp_mem_t *entry;
26660405de4Skz151634 drm_agp_mem_t *nexte;
26760405de4Skz151634
26860405de4Skz151634 /*
26960405de4Skz151634 * Remove AGP resources, but leave dev->agp
27060405de4Skz151634 * intact until drm_cleanup is called.
27160405de4Skz151634 */
27260405de4Skz151634 for (entry = dev->agp->memory; entry; entry = nexte) {
27360405de4Skz151634 nexte = entry->next;
27460405de4Skz151634 if (entry->bound)
27560405de4Skz151634 (void) drm_agp_unbind_memory(
276d0538f66Scg149915 (unsigned long)entry->handle, dev);
277*0035d21cSmiao chen - Sun Microsystems - Beijing China (void) drm_agp_free_memory(entry->handle, dev);
27860405de4Skz151634 drm_free(entry, sizeof (*entry), DRM_MEM_AGPLISTS);
27960405de4Skz151634 }
28060405de4Skz151634 dev->agp->memory = NULL;
28160405de4Skz151634
28260405de4Skz151634 if (dev->agp->acquired)
28360405de4Skz151634 (void) drm_agp_do_release(dev);
28460405de4Skz151634
28560405de4Skz151634 dev->agp->acquired = 0;
28660405de4Skz151634 dev->agp->enabled = 0;
287d0538f66Scg149915 drm_agp_fini(dev);
28860405de4Skz151634 }
289d0538f66Scg149915
29060405de4Skz151634 if (dev->sg != NULL) {
291d0538f66Scg149915 drm_sg_mem_t *entry;
292d0538f66Scg149915 entry = dev->sg;
29360405de4Skz151634 dev->sg = NULL;
294d0538f66Scg149915 drm_sg_cleanup(dev, entry);
29560405de4Skz151634 }
29660405de4Skz151634
297d0538f66Scg149915
29860405de4Skz151634 /* Clean up maps that weren't set up by the driver. */
29960405de4Skz151634 TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
30060405de4Skz151634 if (!map->kernel_owned)
30160405de4Skz151634 drm_rmmap(dev, map);
30260405de4Skz151634 }
30360405de4Skz151634
30460405de4Skz151634 drm_dma_takedown(dev);
30560405de4Skz151634 if (dev->lock.hw_lock) {
30660405de4Skz151634 dev->lock.hw_lock = NULL; /* SHM removed */
30760405de4Skz151634 dev->lock.filp = NULL;
30860405de4Skz151634
30960405de4Skz151634 mutex_enter(&(dev->lock.lock_mutex));
31060405de4Skz151634 cv_broadcast(&(dev->lock.lock_cv));
31160405de4Skz151634 mutex_exit(&(dev->lock.lock_mutex));
31260405de4Skz151634 }
31360405de4Skz151634
31460405de4Skz151634 return (0);
31560405de4Skz151634 }
31660405de4Skz151634
31760405de4Skz151634 static int
drm_load(drm_device_t * dev)318d0538f66Scg149915 drm_load(drm_device_t *dev)
31960405de4Skz151634 {
32060405de4Skz151634 int retcode;
32160405de4Skz151634
32260405de4Skz151634 cv_init(&(dev->lock.lock_cv), NULL, CV_DRIVER, NULL);
32360405de4Skz151634 mutex_init(&(dev->lock.lock_mutex), NULL, MUTEX_DRIVER, NULL);
324d0231070Smiao chen - Sun Microsystems - Beijing China mutex_init(&(dev->dev_lock), "drmdev", MUTEX_DRIVER, NULL);
325d0231070Smiao chen - Sun Microsystems - Beijing China mutex_init(&dev->irq_lock, "drmirq", MUTEX_DRIVER,
326d0231070Smiao chen - Sun Microsystems - Beijing China (void *)dev->intr_block);
327d0231070Smiao chen - Sun Microsystems - Beijing China mutex_init(&dev->drw_lock, "drmdrw", MUTEX_DRIVER, NULL);
328d0231070Smiao chen - Sun Microsystems - Beijing China mutex_init(&dev->tasklet_lock, "drmtsk", MUTEX_DRIVER, NULL);
329e92e3a86Szw161486
330d0231070Smiao chen - Sun Microsystems - Beijing China dev->irq = pci_get_irq(dev);
331e92e3a86Szw161486 dev->pci_vendor = pci_get_vendor(dev);
332e92e3a86Szw161486 dev->pci_device = pci_get_device(dev);
33360405de4Skz151634
33460405de4Skz151634 TAILQ_INIT(&dev->maplist);
335fca314aaScg149915 TAILQ_INIT(&dev->minordevs);
33660405de4Skz151634 TAILQ_INIT(&dev->files);
337d0538f66Scg149915 if (dev->driver->load != NULL) {
338d0538f66Scg149915 retcode = dev->driver->load(dev, 0);
33960405de4Skz151634 if (retcode != 0) {
340d0538f66Scg149915 DRM_ERROR("drm_load: failed\n");
34160405de4Skz151634 goto error;
34260405de4Skz151634 }
34360405de4Skz151634 }
34460405de4Skz151634
34560405de4Skz151634 retcode = drm_ctxbitmap_init(dev);
34660405de4Skz151634 if (retcode != 0) {
34760405de4Skz151634 DRM_ERROR("drm_load: Cannot allocate memory for ctx bitmap");
34860405de4Skz151634 goto error;
34960405de4Skz151634 }
35060405de4Skz151634
351*0035d21cSmiao chen - Sun Microsystems - Beijing China if (dev->driver->use_gem == 1) {
352*0035d21cSmiao chen - Sun Microsystems - Beijing China retcode = drm_gem_init(dev);
353*0035d21cSmiao chen - Sun Microsystems - Beijing China if (retcode) {
354*0035d21cSmiao chen - Sun Microsystems - Beijing China DRM_ERROR("Cannot initialize graphics execution "
355*0035d21cSmiao chen - Sun Microsystems - Beijing China "manager (GEM)\n");
356*0035d21cSmiao chen - Sun Microsystems - Beijing China goto error;
357*0035d21cSmiao chen - Sun Microsystems - Beijing China }
358*0035d21cSmiao chen - Sun Microsystems - Beijing China }
359*0035d21cSmiao chen - Sun Microsystems - Beijing China
36060405de4Skz151634 if (drm_init_kstats(dev)) {
36160405de4Skz151634 DRM_ERROR("drm_attach => drm_load: init kstats error");
362d0538f66Scg149915 retcode = EFAULT;
36360405de4Skz151634 goto error;
36460405de4Skz151634 }
36560405de4Skz151634
36660405de4Skz151634 DRM_INFO("!drm: Initialized %s %d.%d.%d %s ",
367d0538f66Scg149915 dev->driver->driver_name,
368d0538f66Scg149915 dev->driver->driver_major,
369d0538f66Scg149915 dev->driver->driver_minor,
370d0538f66Scg149915 dev->driver->driver_patchlevel,
371d0538f66Scg149915 dev->driver->driver_date);
372d0538f66Scg149915 return (0);
37360405de4Skz151634
37460405de4Skz151634 error:
37560405de4Skz151634 DRM_LOCK();
37660405de4Skz151634 (void) drm_lastclose(dev);
37760405de4Skz151634 DRM_UNLOCK();
37860405de4Skz151634 cv_destroy(&(dev->lock.lock_cv));
37960405de4Skz151634 mutex_destroy(&(dev->lock.lock_mutex));
380d0231070Smiao chen - Sun Microsystems - Beijing China mutex_destroy(&dev->irq_lock);
38160405de4Skz151634 mutex_destroy(&(dev->dev_lock));
382e92e3a86Szw161486 mutex_destroy(&dev->drw_lock);
383d0231070Smiao chen - Sun Microsystems - Beijing China mutex_destroy(&dev->tasklet_lock);
38460405de4Skz151634
38560405de4Skz151634 return (retcode);
38660405de4Skz151634 }
38760405de4Skz151634
38860405de4Skz151634 /* called when cleanup this module */
38960405de4Skz151634 static void
drm_unload(drm_device_t * dev)390d0538f66Scg149915 drm_unload(drm_device_t *dev)
39160405de4Skz151634 {
39260405de4Skz151634 drm_local_map_t *map;
39360405de4Skz151634
3948566479dSEdward Shu drm_vblank_cleanup(dev);
3958566479dSEdward Shu
39660405de4Skz151634 drm_ctxbitmap_cleanup(dev);
39760405de4Skz151634
398*0035d21cSmiao chen - Sun Microsystems - Beijing China if (dev->driver->use_gem == 1) {
399*0035d21cSmiao chen - Sun Microsystems - Beijing China idr_list_free(&dev->object_name_idr);
400*0035d21cSmiao chen - Sun Microsystems - Beijing China mutex_destroy(&dev->object_name_lock);
401*0035d21cSmiao chen - Sun Microsystems - Beijing China }
402*0035d21cSmiao chen - Sun Microsystems - Beijing China
40360405de4Skz151634 DRM_LOCK();
40460405de4Skz151634 (void) drm_lastclose(dev);
40560405de4Skz151634 DRM_UNLOCK();
40660405de4Skz151634
40760405de4Skz151634 while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) {
40860405de4Skz151634 drm_rmmap(dev, map);
40960405de4Skz151634 }
41060405de4Skz151634
411d0538f66Scg149915 if (dev->driver->unload != NULL)
412d0538f66Scg149915 dev->driver->unload(dev);
41360405de4Skz151634
41460405de4Skz151634 drm_mem_uninit();
41560405de4Skz151634 cv_destroy(&dev->lock.lock_cv);
41660405de4Skz151634 mutex_destroy(&dev->lock.lock_mutex);
417d0231070Smiao chen - Sun Microsystems - Beijing China mutex_destroy(&dev->irq_lock);
41860405de4Skz151634 mutex_destroy(&dev->dev_lock);
419e92e3a86Szw161486 mutex_destroy(&dev->drw_lock);
420d0231070Smiao chen - Sun Microsystems - Beijing China mutex_destroy(&dev->tasklet_lock);
421*0035d21cSmiao chen - Sun Microsystems - Beijing China
422*0035d21cSmiao chen - Sun Microsystems - Beijing China dev->gtt_total = 0;
423*0035d21cSmiao chen - Sun Microsystems - Beijing China atomic_set(&dev->pin_memory, 0);
424*0035d21cSmiao chen - Sun Microsystems - Beijing China DRM_ERROR("drm_unload");
42560405de4Skz151634 }
42660405de4Skz151634
42760405de4Skz151634
42860405de4Skz151634 /*ARGSUSED*/
42960405de4Skz151634 int
drm_open(drm_device_t * dev,drm_cminor_t * mp,int openflags,int otyp,cred_t * credp)430fca314aaScg149915 drm_open(drm_device_t *dev, drm_cminor_t *mp, int openflags,
43160405de4Skz151634 int otyp, cred_t *credp)
43260405de4Skz151634 {
43360405de4Skz151634 int retcode;
43460405de4Skz151634
435fca314aaScg149915 retcode = drm_open_helper(dev, mp, openflags, otyp, credp);
43660405de4Skz151634
43760405de4Skz151634 if (!retcode) {
43860405de4Skz151634 atomic_inc_32(&dev->counts[_DRM_STAT_OPENS]);
43960405de4Skz151634 DRM_LOCK();
44060405de4Skz151634 if (!dev->open_count ++)
44160405de4Skz151634 retcode = drm_firstopen(dev);
44260405de4Skz151634 DRM_UNLOCK();
44360405de4Skz151634 }
44460405de4Skz151634
44560405de4Skz151634 return (retcode);
44660405de4Skz151634 }
44760405de4Skz151634
44860405de4Skz151634 /*ARGSUSED*/
44960405de4Skz151634 int
drm_close(drm_device_t * dev,int minor,int flag,int otyp,cred_t * credp)450fca314aaScg149915 drm_close(drm_device_t *dev, int minor, int flag, int otyp,
45160405de4Skz151634 cred_t *credp)
45260405de4Skz151634 {
453fca314aaScg149915 drm_cminor_t *mp;
454d0538f66Scg149915 drm_file_t *fpriv;
45560405de4Skz151634 int retcode = 0;
45660405de4Skz151634
45760405de4Skz151634 DRM_LOCK();
458fca314aaScg149915 mp = drm_find_file_by_minor(dev, minor);
459fca314aaScg149915 if (!mp) {
46060405de4Skz151634 DRM_UNLOCK();
46160405de4Skz151634 DRM_ERROR("drm_close: can't find authenticator");
462d0538f66Scg149915 return (EACCES);
46360405de4Skz151634 }
46460405de4Skz151634
465fca314aaScg149915 fpriv = mp->fpriv;
466fca314aaScg149915 ASSERT(fpriv);
467fca314aaScg149915
468d0538f66Scg149915 if (--fpriv->refs != 0)
469d0538f66Scg149915 goto done;
470d0538f66Scg149915
471d0538f66Scg149915 if (dev->driver->preclose != NULL)
472d0538f66Scg149915 dev->driver->preclose(dev, fpriv);
47360405de4Skz151634
47460405de4Skz151634 /*
47560405de4Skz151634 * Begin inline drm_release
47660405de4Skz151634 */
47760405de4Skz151634 DRM_DEBUG("drm_close :pid = %d , open_count = %d",
47860405de4Skz151634 DRM_CURRENTPID, dev->open_count);
47960405de4Skz151634
48060405de4Skz151634 if (dev->lock.hw_lock &&
48160405de4Skz151634 _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
482d0538f66Scg149915 dev->lock.filp == fpriv) {
48360405de4Skz151634 DRM_DEBUG("Process %d dead, freeing lock for context %d",
48460405de4Skz151634 DRM_CURRENTPID,
48560405de4Skz151634 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
486d0538f66Scg149915 if (dev->driver->reclaim_buffers_locked != NULL)
487d0538f66Scg149915 dev->driver->reclaim_buffers_locked(dev, fpriv);
48860405de4Skz151634 (void) drm_lock_free(dev, &dev->lock.hw_lock->lock,
48960405de4Skz151634 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
490d0538f66Scg149915 } else if (dev->driver->reclaim_buffers_locked != NULL &&
49160405de4Skz151634 dev->lock.hw_lock != NULL) {
49260405de4Skz151634 DRM_ERROR("drm_close: "
49360405de4Skz151634 "retake lock not implemented yet");
49460405de4Skz151634 }
49560405de4Skz151634
496*0035d21cSmiao chen - Sun Microsystems - Beijing China if (dev->driver->use_dma) {
497d0538f66Scg149915 drm_reclaim_buffers(dev, fpriv);
498*0035d21cSmiao chen - Sun Microsystems - Beijing China }
49960405de4Skz151634
500*0035d21cSmiao chen - Sun Microsystems - Beijing China if (dev->driver->use_gem == 1) {
501*0035d21cSmiao chen - Sun Microsystems - Beijing China drm_gem_release(dev, fpriv);
502*0035d21cSmiao chen - Sun Microsystems - Beijing China }
50360405de4Skz151634
504*0035d21cSmiao chen - Sun Microsystems - Beijing China if (dev->driver->postclose != NULL) {
505d0538f66Scg149915 dev->driver->postclose(dev, fpriv);
506*0035d21cSmiao chen - Sun Microsystems - Beijing China }
507d0538f66Scg149915 TAILQ_REMOVE(&dev->files, fpriv, link);
508d0538f66Scg149915 drm_free(fpriv, sizeof (*fpriv), DRM_MEM_FILES);
50960405de4Skz151634
510d0538f66Scg149915 done:
51160405de4Skz151634 atomic_inc_32(&dev->counts[_DRM_STAT_CLOSES]);
51260405de4Skz151634
513fca314aaScg149915 TAILQ_REMOVE(&dev->minordevs, mp, link);
514fca314aaScg149915 drm_free(mp, sizeof (*mp), DRM_MEM_FILES);
515fca314aaScg149915
51660405de4Skz151634 if (--dev->open_count == 0) {
51760405de4Skz151634 retcode = drm_lastclose(dev);
51860405de4Skz151634 }
51960405de4Skz151634 DRM_UNLOCK();
52060405de4Skz151634
52160405de4Skz151634 return (retcode);
52260405de4Skz151634 }
52360405de4Skz151634
52460405de4Skz151634 int
drm_attach(drm_device_t * dev)525d0538f66Scg149915 drm_attach(drm_device_t *dev)
52660405de4Skz151634 {
52760405de4Skz151634 return (drm_load(dev));
52860405de4Skz151634 }
52960405de4Skz151634
53060405de4Skz151634 int
drm_detach(drm_device_t * dev)531d0538f66Scg149915 drm_detach(drm_device_t *dev)
53260405de4Skz151634 {
53360405de4Skz151634 drm_unload(dev);
53460405de4Skz151634 drm_fini_kstats(dev);
53560405de4Skz151634 return (DDI_SUCCESS);
53660405de4Skz151634 }
53760405de4Skz151634
53860405de4Skz151634 static int
drm_get_businfo(drm_device_t * dev)539d0538f66Scg149915 drm_get_businfo(drm_device_t *dev)
54060405de4Skz151634 {
54160405de4Skz151634 dev->irq = pci_get_irq(dev);
54260405de4Skz151634 if (dev->irq == -1) {
54360405de4Skz151634 DRM_ERROR("drm_get_businfo: get irq error");
54460405de4Skz151634 return (DDI_FAILURE);
54560405de4Skz151634 }
54660405de4Skz151634 /* XXX Fix domain number (alpha hoses) */
54760405de4Skz151634 dev->pci_domain = 0;
54860405de4Skz151634 if (pci_get_info(dev, &dev->pci_bus,
54960405de4Skz151634 &dev->pci_slot, &dev->pci_func) != DDI_SUCCESS) {
55060405de4Skz151634 DRM_ERROR("drm_get_businfo: get bus slot func error ");
55160405de4Skz151634 return (DDI_FAILURE);
55260405de4Skz151634 }
55360405de4Skz151634 DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d",
55460405de4Skz151634 dev->pci_bus, dev->pci_slot, dev->pci_func);
55560405de4Skz151634 return (DDI_SUCCESS);
55660405de4Skz151634 }
55760405de4Skz151634
55860405de4Skz151634 int
drm_probe(drm_device_t * dev,drm_pci_id_list_t * idlist)559d0538f66Scg149915 drm_probe(drm_device_t *dev, drm_pci_id_list_t *idlist)
56060405de4Skz151634 {
56160405de4Skz151634 const char *s = NULL;
56260405de4Skz151634 int vendor, device;
56360405de4Skz151634
56460405de4Skz151634 vendor = pci_get_vendor(dev);
56560405de4Skz151634 device = pci_get_device(dev);
56660405de4Skz151634
56760405de4Skz151634 s = drm_find_description(vendor, device, idlist);
56860405de4Skz151634 if (s != NULL) {
56960405de4Skz151634 dev->desc = s;
57060405de4Skz151634 if (drm_get_businfo(dev) != DDI_SUCCESS) {
57160405de4Skz151634 DRM_ERROR("drm_probe: drm get bus info error");
57260405de4Skz151634 return (DDI_FAILURE);
57360405de4Skz151634 }
57460405de4Skz151634 return (DDI_SUCCESS);
57560405de4Skz151634 }
57660405de4Skz151634 return (DDI_FAILURE);
57760405de4Skz151634 }
578