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