xref: /titanic_41/usr/src/uts/common/io/drm/drm_drv.c (revision 9404882939d18ddd3c94a5bd3da7a0449c195a5d)
1 /*
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.
8  * All Rights Reserved.
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice (including the next
18  * paragraph) shall be included in all copies or substantial portions of the
19  * Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27  * OTHER DEALINGS IN THE SOFTWARE.
28  *
29  * Authors:
30  *    Rickard E. (Rik) Faith <faith@valinux.com>
31  *    Gareth Hughes <gareth@valinux.com>
32  *
33  */
34 
35 /*
36  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
37  * Use is subject to license terms.
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 	mutex_init(&dev->drw_lock, NULL, MUTEX_DRIVER, NULL);
304 
305 	dev->pci_vendor = pci_get_vendor(dev);
306 	dev->pci_device = pci_get_device(dev);
307 
308 	dev->cloneopens = 0;
309 	dev->minordevs = NULL;
310 	TAILQ_INIT(&dev->maplist);
311 
312 	TAILQ_INIT(&dev->files);
313 	if (dev->load != NULL) {
314 		retcode = dev->load(dev, 0);
315 		if (retcode != 0) {
316 			DRM_ERROR("drm_load: dev->load failed\n");
317 			goto error;
318 		}
319 	}
320 
321 	if (dev->use_agp) {
322 		DRM_DEBUG("drm_load: dev->use_agp=%d", dev->use_agp);
323 		if (drm_device_is_agp(dev))
324 			dev->agp = drm_agp_init();
325 		if (dev->require_agp && dev->agp == NULL) {
326 			DRM_ERROR("drm_load: Card isn't AGP,\
327 			    or couldn't initialize AGP");
328 			retcode = DRM_ERR(ENOMEM);
329 			goto error;
330 		}
331 	}
332 
333 	retcode = drm_ctxbitmap_init(dev);
334 	if (retcode != 0) {
335 		DRM_ERROR("drm_load: Cannot allocate memory for ctx bitmap");
336 		goto error;
337 	}
338 
339 	if (drm_init_kstats(dev)) {
340 		DRM_ERROR("drm_attach => drm_load: init kstats error");
341 		retcode = DRM_ERR(EFAULT);
342 		goto error;
343 	}
344 
345 	DRM_INFO("!drm: Initialized %s %d.%d.%d %s ",
346 		dev->driver_name,
347 		dev->driver_major,
348 		dev->driver_minor,
349 		dev->driver_patchlevel,
350 		dev->driver_date);
351 	return (DDI_SUCCESS);
352 
353 error:
354 	DRM_LOCK();
355 	(void) drm_lastclose(dev);
356 	DRM_UNLOCK();
357 	cv_destroy(&(dev->lock.lock_cv));
358 	mutex_destroy(&(dev->lock.lock_mutex));
359 	mutex_destroy(&(dev->dev_lock));
360 	mutex_destroy(&dev->drw_lock);
361 
362 	return (retcode);
363 }
364 
365 /* called when cleanup this module */
366 static void
367 drm_unload(drm_softstate_t *dev)
368 {
369 	drm_local_map_t *map;
370 
371 	drm_ctxbitmap_cleanup(dev);
372 
373 	DRM_LOCK();
374 	(void) drm_lastclose(dev);
375 	DRM_UNLOCK();
376 
377 	while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) {
378 		drm_rmmap(dev, map);
379 	}
380 
381 	if (dev->agp) {
382 		drm_agp_uninit(dev->agp);
383 	}
384 
385 	if (dev->unload != NULL)
386 		dev->unload(dev);
387 
388 	drm_mem_uninit();
389 	cv_destroy(&dev->lock.lock_cv);
390 	mutex_destroy(&dev->lock.lock_mutex);
391 	mutex_destroy(&dev->dev_lock);
392 	mutex_destroy(&dev->drw_lock);
393 
394 	DRM_INFO("!drm: drm_unload: cleanup the resource");
395 }
396 
397 
398 /*ARGSUSED*/
399 int
400 drm_open(drm_softstate_t *dev, dev_t *kdev, int openflags,
401     int otyp, cred_t *credp)
402 {
403 	int retcode;
404 	DRM_DEBUG("drm_open: open_count = %d", dev->open_count);
405 
406 	retcode = drm_open_helper(dev, openflags, otyp, credp);
407 
408 	if (!retcode) {
409 		atomic_inc_32(&dev->counts[_DRM_STAT_OPENS]);
410 		DRM_LOCK();
411 		if (!dev->open_count ++)
412 			retcode = drm_firstopen(dev);
413 		DRM_UNLOCK();
414 	}
415 
416 	return (retcode);
417 }
418 
419 /*ARGSUSED*/
420 int
421 drm_close(drm_softstate_t *dev, dev_t kdev, int flag, int otyp,
422     cred_t *credp)
423 {
424 	drm_file_t *priv;
425 	int retcode = 0;
426 	DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID);
427 
428 	DRM_DEBUG("drm_close: open_count = %d", dev->open_count);
429 
430 	DRM_LOCK();
431 	priv = drm_find_file_by_proc(dev, credp);
432 	if (!priv) {
433 		DRM_UNLOCK();
434 		DRM_ERROR("drm_close: can't find authenticator");
435 		return (DRM_ERR(EINVAL));
436 	}
437 	DRM_UNLOCK();
438 
439 	/*
440 	 * Free memory allocated by drm_add_magic
441 	 */
442 	if ((drm_find_file(dev, priv->magic))) {
443 		(void) drm_remove_magic(dev, priv->magic);
444 	}
445 
446 	DRM_LOCK();
447 	if (dev->preclose != NULL)
448 		dev->preclose(dev, filp);
449 
450 	/*
451 	 * Begin inline drm_release
452 	 */
453 	DRM_DEBUG("drm_close :pid = %d , open_count = %d",
454 		    DRM_CURRENTPID, dev->open_count);
455 
456 	if (dev->lock.hw_lock &&
457 		_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
458 	dev->lock.filp == filp) {
459 		DRM_DEBUG("Process %d dead, freeing lock for context %d",
460 		    DRM_CURRENTPID,
461 		    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
462 		if (dev->reclaim_buffers_locked != NULL)
463 			dev->reclaim_buffers_locked(dev, filp);
464 		(void) drm_lock_free(dev, &dev->lock.hw_lock->lock,
465 		    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
466 	} else if (dev->reclaim_buffers_locked != NULL &&
467 	    dev->lock.hw_lock != NULL) {
468 		DRM_ERROR("drm_close: "
469 		    "retake lock not implemented yet");
470 	}
471 
472 	if (dev->use_dma)
473 		drm_reclaim_buffers(dev, (void *)(uintptr_t)priv->pid);
474 
475 
476 	if (--priv->refs == 0) {
477 		if (dev->postclose != NULL)
478 			dev->postclose(dev, priv);
479 		TAILQ_REMOVE(&dev->files, priv, link);
480 		drm_free(priv, sizeof (*priv), DRM_MEM_FILES);
481 	}
482 
483 	/*
484 	 * End inline drm_release
485 	 */
486 	atomic_inc_32(&dev->counts[_DRM_STAT_CLOSES]);
487 
488 	if (--dev->open_count == 0) {
489 		retcode = drm_lastclose(dev);
490 	}
491 	DRM_UNLOCK();
492 
493 	return (retcode);
494 }
495 
496 
497 /*ARGSUSED*/
498 int
499 drm_ioctl(dev_t kdev, int cmd, intptr_t intarg, int flags,
500     cred_t *credp, int *rvalp)
501 {
502 	return (DDI_SUCCESS);
503 }
504 
505 /*ARGSUSED*/
506 int
507 drm_segmap(dev_t kdev, off_t off, struct as *asp,
508     caddr_t *addrp, off_t len, unsigned int prot,
509     unsigned int maxprot, unsigned int flags, cred_t *credp)
510 {
511 	return (DDI_SUCCESS);
512 }
513 
514 /*ARGSUSED*/
515 int
516 drm_devmap(dev_t dev, devmap_cookie_t cookie, offset_t offset, size_t len,
517     size_t *mappedlen, uint_t model)
518 {
519 	return (DDI_SUCCESS);
520 }
521 
522 /*ARGSUSED*/
523 int
524 drm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
525     void **resultp)
526 {
527 	return (DDI_SUCCESS);
528 }
529 
530 int
531 drm_attach(drm_softstate_t *dev)
532 {
533 	drm_init_ioctl_arrays();
534 	return (drm_load(dev));
535 }
536 
537 int
538 drm_detach(drm_softstate_t *dev)
539 {
540 	drm_unload(dev);
541 	drm_fini_kstats(dev);
542 	return (DDI_SUCCESS);
543 }
544 
545 static int
546 drm_get_businfo(drm_softstate_t *dev)
547 {
548 	dev->irq = pci_get_irq(dev);
549 	if (dev->irq == -1) {
550 		DRM_ERROR("drm_get_businfo: get irq error");
551 		return (DDI_FAILURE);
552 	}
553 	/* XXX Fix domain number (alpha hoses) */
554 	dev->pci_domain = 0;
555 	if (pci_get_info(dev, &dev->pci_bus,
556 	    &dev->pci_slot, &dev->pci_func) != DDI_SUCCESS) {
557 		DRM_ERROR("drm_get_businfo: get bus slot func error ");
558 		return (DDI_FAILURE);
559 	}
560 	DRM_DEBUG("drm_get_businfo: pci bus: %d, pci slot :%d pci func %d",
561 	    dev->pci_bus, dev->pci_slot, dev->pci_func);
562 	return (DDI_SUCCESS);
563 }
564 
565 int
566 drm_probe(drm_softstate_t *dev, drm_pci_id_list_t *idlist)
567 {
568 	const char *s = NULL;
569 	int vendor, device;
570 
571 	vendor = pci_get_vendor(dev);
572 	device = pci_get_device(dev);
573 	DRM_DEBUG("drm_probe: vendor is 0x%x, device is 0x%x",
574 	    vendor, device);
575 
576 	s = drm_find_description(vendor, device, idlist);
577 	if (s != NULL) {
578 		dev->desc = s;
579 		DRM_DEBUG("drm_probe: probe %s exist",
580 			dev->desc);
581 		if (drm_get_businfo(dev) != DDI_SUCCESS) {
582 			DRM_ERROR("drm_probe: drm get bus info error");
583 			return (DDI_FAILURE);
584 		}
585 		return (DDI_SUCCESS);
586 	}
587 	return (DDI_FAILURE);
588 }
589