4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Common misc module interfaces of DRM under Solaris
32 * This module calls into gfx and agpmaster misc modules respectively
33 * for generic graphics operations and AGP master device support.
36 #include "drm_sunmod.h"
37 #include <sys/modctl.h>
39 #include <vm/seg_kmem.h>
41 static struct modlmisc modlmisc
= {
42 &mod_miscops
, "DRM common interfaces"
45 static struct modlinkage modlinkage
= {
46 MODREV_1
, (void *)&modlmisc
, NULL
49 static drm_inst_list_t
*drm_inst_head
;
50 static kmutex_t drm_inst_list_lock
;
52 static int drm_sun_open(dev_t
*, int, int, cred_t
*);
53 static int drm_sun_close(dev_t
, int, int, cred_t
*);
54 static int drm_sun_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
55 static int drm_sun_devmap(dev_t
, devmap_cookie_t
, offset_t
, size_t,
59 * devmap callbacks for AGP and PCI GART
61 static int drm_devmap_map(devmap_cookie_t
, dev_t
,
62 uint_t
, offset_t
, size_t, void **);
63 static int drm_devmap_dup(devmap_cookie_t
, void *,
64 devmap_cookie_t
, void **);
65 static void drm_devmap_unmap(devmap_cookie_t
, void *,
66 offset_t
, size_t, devmap_cookie_t
, void **, devmap_cookie_t
, void **);
68 static drm_inst_list_t
*drm_supp_alloc_drv_entry(dev_info_t
*);
69 static drm_inst_state_t
*drm_sup_devt_to_state(dev_t
);
70 static void drm_supp_free_drv_entry(dev_info_t
*);
72 static struct devmap_callback_ctl drm_devmap_callbacks
= {
73 DEVMAP_OPS_REV
, /* devmap_rev */
74 drm_devmap_map
, /* devmap_map */
75 NULL
, /* devmap_access */
76 drm_devmap_dup
, /* devmap_dup */
77 drm_devmap_unmap
/* devmap_unmap */
81 * Common device operations structure for all DRM drivers
83 struct cb_ops drm_cb_ops
= {
84 drm_sun_open
, /* cb_open */
85 drm_sun_close
, /* cb_close */
86 nodev
, /* cb_strategy */
91 drm_sun_ioctl
, /* cb_ioctl */
92 drm_sun_devmap
, /* cb_devmap */
95 nochpoll
, /* cb_chpoll */
96 ddi_prop_op
, /* cb_prop_op */
98 D_NEW
| D_MTSAFE
|D_DEVMAP
/* cb_flag */
106 if ((error
= mod_install(&modlinkage
)) != 0) {
110 /* initialize the instance list lock */
111 mutex_init(&drm_inst_list_lock
, NULL
, MUTEX_DRIVER
, NULL
);
120 if ((err
= mod_remove(&modlinkage
)) != 0)
123 mutex_destroy(&drm_inst_list_lock
);
128 _info(struct modinfo
*modinfop
)
130 return (mod_info(&modlinkage
, modinfop
));
134 drm_supp_register(dev_info_t
*dip
, drm_device_t
*dp
)
138 int instance
= ddi_get_instance(dip
);
139 ddi_acc_handle_t pci_cfg_handle
;
140 agp_master_softc_t
*agpm
;
141 drm_inst_state_t
*mstate
;
142 drm_inst_list_t
*entry
;
143 gfxp_vgatext_softc_ptr_t gfxp
;
144 struct dev_ops
*devop
;
148 entry
= drm_supp_alloc_drv_entry(dip
);
150 cmn_err(CE_WARN
, "drm_supp_register: failed to get softstate");
153 mstate
= &entry
->disl_state
;
156 * DRM drivers are required to use common cb_ops
158 devop
= ddi_get_driver(dip
);
159 if (devop
->devo_cb_ops
!= &drm_cb_ops
) {
160 devop
->devo_cb_ops
= &drm_cb_ops
;
163 /* Generic graphics initialization */
164 gfxp
= gfxp_vgatext_softc_alloc();
165 error
= gfxp_vgatext_attach(dip
, DDI_ATTACH
, gfxp
);
166 if (error
!= DDI_SUCCESS
) {
167 DRM_ERROR("drm_supp_regiter: failed to init gfx");
171 /* create a minor node for common graphics ops */
172 (void) sprintf(buf
, "%s%d", GFX_NAME
, instance
);
173 error
= ddi_create_minor_node(dip
, buf
, S_IFCHR
,
174 INST2NODE0(instance
), DDI_NT_DISPLAY
, 0);
175 if (error
!= DDI_SUCCESS
) {
176 DRM_ERROR("drm_supp_regiter: "
177 "failed to create minor node for gfx");
181 /* setup mapping for later PCI config space access */
182 error
= pci_config_setup(dip
, &pci_cfg_handle
);
183 if (error
!= DDI_SUCCESS
) {
184 DRM_ERROR("drm_supp_regiter: "
185 "PCI configuration space setup failed");
189 /* AGP master attach */
191 if (dp
->driver
->use_agp
) {
192 DRM_DEBUG("drm_supp_regiter: driver use AGP\n");
193 error
= agpmaster_attach(dip
, &agpm
,
194 pci_cfg_handle
, INST2NODE1(instance
));
195 if ((error
!= DDI_SUCCESS
) && (dp
->driver
->require_agp
)) {
196 DRM_ERROR("drm_supp_regiter: "
197 "AGP master support not available");
202 mutex_enter(&mstate
->mis_lock
);
203 mstate
->mis_major
= ddi_driver_major(dip
);
204 mstate
->mis_dip
= dip
;
205 mstate
->mis_gfxp
= gfxp
;
206 mstate
->mis_agpm
= agpm
;
207 mstate
->mis_cfg_hdl
= pci_cfg_handle
;
208 mstate
->mis_devp
= dp
;
209 mutex_exit(&mstate
->mis_lock
);
211 /* create minor node for DRM access */
212 (void) sprintf(buf
, "%s%d", DRM_DEVNODE
, instance
);
213 if (ddi_create_minor_node(dip
, buf
, S_IFCHR
,
214 INST2NODE2(instance
), DDI_NT_DISPLAY_DRM
, 0)) {
215 DRM_ERROR("supp_regiter: faled to create minor node for drm");
219 return ((void *)mstate
);
222 if ((dp
->driver
->use_agp
) && agpm
)
223 agpmaster_detach(&agpm
);
225 pci_config_teardown(&pci_cfg_handle
);
227 (void) gfxp_vgatext_detach(dip
, DDI_DETACH
, gfxp
);
229 gfxp_vgatext_softc_free(gfxp
);
230 drm_supp_free_drv_entry(dip
);
231 ddi_remove_minor_node(dip
, NULL
);
238 drm_supp_unregister(void *handle
)
240 drm_inst_list_t
*list
;
241 drm_inst_state_t
*mstate
;
243 list
= (drm_inst_list_t
*)handle
;
244 mstate
= &list
->disl_state
;
245 mutex_enter(&mstate
->mis_lock
);
247 /* AGP master detach */
248 if (mstate
->mis_agpm
!= NULL
)
249 agpmaster_detach(&mstate
->mis_agpm
);
251 /* free PCI config access handle */
252 if (mstate
->mis_cfg_hdl
)
253 pci_config_teardown(&mstate
->mis_cfg_hdl
);
255 /* graphics misc module detach */
256 if (mstate
->mis_gfxp
) {
257 (void) gfxp_vgatext_detach(mstate
->mis_dip
, DDI_DETACH
,
259 gfxp_vgatext_softc_free(mstate
->mis_gfxp
);
262 mstate
->mis_devp
= NULL
;
264 /* remove all minor nodes */
265 ddi_remove_minor_node(mstate
->mis_dip
, NULL
);
266 mutex_exit(&mstate
->mis_lock
);
267 drm_supp_free_drv_entry(mstate
->mis_dip
);
269 return (DDI_SUCCESS
);
275 drm_sun_open(dev_t
*devp
, int flag
, int otyp
, cred_t
*credp
)
277 drm_inst_state_t
*mstate
;
278 drm_cminor_t
*mp
, *newp
;
285 mstate
= drm_sup_devt_to_state(*devp
);
287 * return ENXIO for deferred attach so that system can
294 * The lest significant 15 bits are used for minor_number, and
295 * the mid 3 bits are used for instance number. All minor numbers
296 * are used as follows:
300 * (3, MAX_CLONE_MINOR) -- drm minor node for clone open.
302 minor
= DEV2MINOR(*devp
);
303 instance
= DEV2INST(*devp
);
304 ASSERT(minor
<= MAX_CLONE_MINOR
);
307 * No operations for VGA & AGP mater devices, always return OK.
309 if ((minor
== GFX_MINOR
) || (minor
== AGPMASTER_MINOR
))
313 * From here, we start to process drm
316 dp
= mstate
->mis_devp
;
321 * Drm driver implements a software lock to serialize access
322 * to graphics hardware based on per-process granulation. Before
323 * operating graphics hardware, all clients, including kernel
324 * and applications, must acquire this lock via DRM_IOCTL_LOCK
325 * ioctl, and release it via DRM_IOCTL_UNLOCK after finishing
326 * operations. Drm driver will grant r/w permission to the
327 * process which acquires this lock (Kernel is assumed to have
330 * A process might be terminated without releasing drm lock, in
331 * this case, drm driver is responsible for clearing the holding.
332 * To be informed of process exiting, drm driver uses clone open
333 * to guarantee that each call to open(9e) have one corresponding
334 * call to close(9e). In most cases, a process will close drm
335 * during process termination, so that drm driver could have a
336 * chance to release drm lock.
338 * In fact, a driver cannot know exactly when a process exits.
339 * Clone open doesn't address this issue completely: Because of
340 * inheritance, child processes inherit file descriptors from
341 * their parent. As a result, if the parent exits before its
342 * children, drm close(9e) entrypoint won't be called until all
343 * of its children terminate.
345 * Another issue brought up by inhertance is the process PID
346 * that calls the drm close() entry point may not be the same
347 * as the one who called open(). Per-process struct is allocated
348 * when a process first open() drm, and released when the process
349 * last close() drm. Since open()/close() may be not the same
350 * process, PID cannot be used for key to lookup per-process
351 * struct. So, we associate minor number with per-process struct
352 * during open()'ing, and find corresponding process struct
353 * via minor number when close() is called.
355 newp
= kmem_zalloc(sizeof (drm_cminor_t
), KM_SLEEP
);
356 mutex_enter(&dp
->dev_lock
);
357 for (newminor
= DRM_MIN_CLONEMINOR
; newminor
< MAX_CLONE_MINOR
;
359 TAILQ_FOREACH(mp
, &dp
->minordevs
, link
) {
360 if (mp
->minor
== newminor
)
367 mutex_exit(&dp
->dev_lock
);
368 (void) kmem_free(newp
, sizeof (drm_cminor_t
));
372 TAILQ_INSERT_TAIL(&dp
->minordevs
, newp
, link
);
373 newp
->minor
= newminor
;
374 mutex_exit(&dp
->dev_lock
);
375 err
= drm_open(dp
, newp
, flag
, otyp
, credp
);
377 mutex_enter(&dp
->dev_lock
);
378 TAILQ_REMOVE(&dp
->minordevs
, newp
, link
);
379 (void) kmem_free(newp
, sizeof (drm_cminor_t
));
380 mutex_exit(&dp
->dev_lock
);
385 /* return a clone minor */
386 newminor
= newminor
| (instance
<< NBITSMNODE
);
387 *devp
= makedevice(getmajor(*devp
), newminor
);
393 drm_sun_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
395 drm_inst_state_t
*mstate
;
400 mstate
= drm_sup_devt_to_state(dev
);
404 minor
= DEV2MINOR(dev
);
405 ASSERT(minor
<= MAX_CLONE_MINOR
);
406 if ((minor
== GFX_MINOR
) || (minor
== AGPMASTER_MINOR
))
409 dp
= mstate
->mis_devp
;
411 DRM_ERROR("drm_sun_close: NULL soft state");
415 ret
= drm_close(dp
, minor
, flag
, otyp
, credp
);
422 drm_sun_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
,
423 cred_t
*credp
, int *rvalp
)
425 extern drm_ioctl_desc_t drm_ioctls
[];
427 drm_inst_state_t
*mstate
;
429 drm_ioctl_desc_t
*ioctl
;
436 if (cmd
== VIS_GETIDENTIFIER
) {
437 if (ddi_copyout(&text_ident
, (void *)arg
,
438 sizeof (struct vis_identifier
), mode
))
442 mstate
= drm_sup_devt_to_state(dev
);
443 if (mstate
== NULL
) {
447 minor
= DEV2MINOR(dev
);
448 ASSERT(minor
<= MAX_CLONE_MINOR
);
451 retval
= gfxp_vgatext_ioctl(dev
, cmd
, arg
,
452 mode
, credp
, rvalp
, mstate
->mis_gfxp
);
455 case AGPMASTER_MINOR
:
456 retval
= agpmaster_ioctl(dev
, cmd
, arg
, mode
,
457 credp
, rvalp
, mstate
->mis_agpm
);
461 default: /* DRM cloning minor nodes */
465 dp
= mstate
->mis_devp
;
468 nr
= DRM_IOCTL_NR(cmd
);
469 ioctl
= &drm_ioctls
[nr
];
470 atomic_inc_32(&dp
->counts
[_DRM_STAT_IOCTLS
]);
472 /* It's not a core DRM ioctl, try driver-specific. */
473 if (ioctl
->func
== NULL
&& nr
>= DRM_COMMAND_BASE
) {
474 /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
475 nr
-= DRM_COMMAND_BASE
;
476 if (nr
> dp
->driver
->max_driver_ioctl
) {
477 DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)",
478 nr
, dp
->driver
->max_driver_ioctl
);
481 ioctl
= &dp
->driver
->driver_ioctls
[nr
];
489 mutex_enter(&dp
->dev_lock
);
490 fpriv
= drm_find_file_by_proc(dp
, credp
);
491 mutex_exit(&dp
->dev_lock
);
493 DRM_ERROR("drm_sun_ioctl : can't find authenticator");
497 if (((ioctl
->flags
& DRM_ROOT_ONLY
) && !DRM_SUSER(credp
)) ||
498 ((ioctl
->flags
& DRM_AUTH
) && !fpriv
->authenticated
) ||
499 ((ioctl
->flags
& DRM_MASTER
) && !fpriv
->master
))
503 fpriv
->credp
= credp
;
505 retval
= func(dp
, arg
, fpriv
, mode
);
512 drm_sun_devmap(dev_t dev
, devmap_cookie_t dhp
, offset_t offset
,
513 size_t len
, size_t *maplen
, uint_t model
)
515 extern int drm_get_pci_index_reg(dev_info_t
*, uint_t
, uint_t
, off_t
*);
517 drm_inst_state_t
*mstate
;
519 ddi_umem_cookie_t cookie
;
520 drm_local_map_t
*map
= NULL
;
521 unsigned long aperbase
;
529 static ddi_device_acc_attr_t dev_attr
= {
534 static ddi_device_acc_attr_t gem_dev_attr
= {
540 mstate
= drm_sup_devt_to_state(dev
);
544 minor
= DEV2MINOR(dev
);
547 ret
= gfxp_vgatext_devmap(dev
, dhp
, offset
, len
, maplen
, model
,
551 case AGPMASTER_MINOR
:
558 /* DRM cloning nodes */
559 if (minor
> MAX_CLONE_MINOR
)
565 dp
= mstate
->mis_devp
;
567 DRM_ERROR("drm_sun_devmap: NULL soft state");
571 mutex_enter(&dp
->dev_lock
);
573 if (dp
->driver
->use_gem
== 1) {
574 struct idr_list
*entry
;
577 mp
= drm_find_file_by_minor(dp
, minor
);
579 mutex_exit(&dp
->dev_lock
);
580 DRM_ERROR("drm_sun_devmap: can't find authenticator");
584 spin_lock(&dp
->struct_mutex
);
585 idr_list_for_each(entry
, &(mp
->fpriv
->object_idr
)) {
586 if ((uintptr_t)entry
->obj
== (uoff_t
)offset
) {
587 map
= entry
->obj
->map
;
592 spin_unlock(&dp
->struct_mutex
);
597 * We will solve 32-bit application on 64-bit kernel
598 * issue later, now, we just use low 32-bit
600 handle
= (uoff_t
)offset
;
601 handle
&= 0xffffffff;
603 TAILQ_FOREACH(map
, &dp
->maplist
, link
) {
605 ((uoff_t
)((uintptr_t)map
->handle
) & 0xffffffff))
610 * Temporarily, because offset is phys_addr for register
611 * and framebuffer, is kernel virtual_addr for others
612 * Maybe we will use hash table to solve this issue later.
615 TAILQ_FOREACH(map
, &dp
->maplist
, link
) {
616 if (handle
== (map
->offset
& 0xffffffff))
625 mutex_exit(&dp
->dev_lock
);
626 cmn_err(CE_WARN
, "Can't find map, offset=0x%llx, len=%x\n",
628 cmn_err(CE_WARN
, "Current mapping:\n");
629 TAILQ_FOREACH(map
, &dp
->maplist
, link
) {
630 tmp
= (uoff_t
)((uintptr_t)map
->handle
) & 0xffffffff;
631 cmn_err(CE_WARN
, "map(handle=0x%p, size=0x%lx,type=%d,"
632 "offset=0x%lx), handle=%llx, tmp=%lld", map
->handle
,
633 map
->size
, map
->type
, map
->offset
, handle
, tmp
);
637 if (map
->flags
& _DRM_RESTRICTED
) {
638 mutex_exit(&dp
->dev_lock
);
639 cmn_err(CE_WARN
, "restricted map\n");
643 mutex_exit(&dp
->dev_lock
);
645 case _DRM_FRAME_BUFFER
:
651 regno
= drm_get_pci_index_reg(dp
->dip
,
652 map
->offset
, (uint_t
)len
, ®off
);
654 DRM_ERROR("devmap: failed to get register"
655 " offset=0x%llx, len=0x%x", handle
, len
);
659 ret
= devmap_devmem_setup(dhp
, dp
->dip
, NULL
,
660 regno
, (offset_t
)regoff
, len
, PROT_ALL
,
664 DRM_ERROR("devmap: failed, regno=%d,type=%d,"
665 " handle=0x%x, offset=0x%llx, len=0x%x",
666 regno
, map
->type
, handle
, offset
, len
);
674 if (map
->drm_umem_cookie
== NULL
)
676 length
= ptob(btopr(map
->size
));
677 ret
= devmap_umem_setup(dhp
, dp
->dip
, NULL
,
678 map
->drm_umem_cookie
, 0, length
,
679 PROT_ALL
, IOMEM_DATA_CACHED
, NULL
);
686 return (DDI_SUCCESS
);
689 if (dp
->agp
== NULL
) {
690 cmn_err(CE_WARN
, "drm_sun_devmap: attempted to mmap AGP"
691 "memory before AGP support is enabled");
692 return (DDI_FAILURE
);
695 aperbase
= dp
->agp
->base
;
696 koff
= map
->offset
- aperbase
;
697 length
= ptob(btopr(len
));
699 cookie
= gfxp_umem_cookie_init(kva
, length
);
700 if (cookie
== NULL
) {
701 cmn_err(CE_WARN
, "devmap:failed to get umem_cookie");
702 return (DDI_FAILURE
);
705 if ((ret
= devmap_umem_setup(dhp
, dp
->dip
,
706 &drm_devmap_callbacks
, cookie
, 0, length
, PROT_ALL
,
707 IOMEM_DATA_UNCACHED
| DEVMAP_ALLOW_REMAP
, &dev_attr
)) < 0) {
708 gfxp_umem_cookie_destroy(cookie
);
709 cmn_err(CE_WARN
, "devmap:failed, retval=%d", ret
);
710 return (DDI_FAILURE
);
715 case _DRM_SCATTER_GATHER
:
716 koff
= map
->offset
- (unsigned long)(caddr_t
)dp
->sg
->virtual;
717 kva
= map
->dev_addr
+ koff
;
718 length
= ptob(btopr(len
));
719 if (length
> map
->size
) {
720 cmn_err(CE_WARN
, "offset=0x%lx, virtual=0x%p,"
721 "mapsize=0x%lx,len=0x%lx", map
->offset
,
722 dp
->sg
->virtual, map
->size
, len
);
723 return (DDI_FAILURE
);
725 cookie
= gfxp_umem_cookie_init(kva
, length
);
726 if (cookie
== NULL
) {
727 cmn_err(CE_WARN
, "devmap:failed to get umem_cookie");
728 return (DDI_FAILURE
);
730 ret
= devmap_umem_setup(dhp
, dp
->dip
,
731 &drm_devmap_callbacks
, cookie
, 0, length
, PROT_ALL
,
732 IOMEM_DATA_UNCACHED
| DEVMAP_ALLOW_REMAP
, &dev_attr
);
734 cmn_err(CE_WARN
, "sun_devmap: umem_setup fail");
735 gfxp_umem_cookie_destroy(cookie
);
736 return (DDI_FAILURE
);
742 if (map
->drm_umem_cookie
== NULL
)
745 if (gfxp_devmap_umem_setup(dhp
, dp
->dip
,
746 NULL
, map
->drm_umem_cookie
, 0, map
->size
, PROT_ALL
,
747 IOMEM_DATA_UC_WR_COMBINE
| DEVMAP_ALLOW_REMAP
,
749 cmn_err(CE_WARN
, "devmap:failed, retval=%d", ret
);
750 return (DDI_FAILURE
);
753 return (DDI_SUCCESS
);
756 return (DDI_FAILURE
);
758 return (DDI_SUCCESS
);
764 drm_devmap_map(devmap_cookie_t dhc
, dev_t dev
, uint_t flags
,
765 offset_t offset
, size_t len
, void **new_priv
)
767 devmap_handle_t
*dhp
;
768 drm_inst_state_t
*statep
;
769 struct ddi_umem_cookie
*cp
;
771 statep
= drm_sup_devt_to_state(dev
);
772 ASSERT(statep
!= NULL
);
775 * This driver only supports MAP_SHARED,
776 * and doesn't support MAP_PRIVATE
778 if (flags
& MAP_PRIVATE
) {
779 cmn_err(CE_WARN
, "!DRM driver doesn't support MAP_PRIVATE");
783 mutex_enter(&statep
->dis_ctxlock
);
784 dhp
= (devmap_handle_t
*)dhc
;
785 cp
= (struct ddi_umem_cookie
*)dhp
->dh_cookie
;
787 mutex_exit(&statep
->dis_ctxlock
);
795 drm_devmap_unmap(devmap_cookie_t dhc
, void *pvtp
, offset_t off
, size_t len
,
796 devmap_cookie_t new_dhp1
, void **new_pvtp1
, devmap_cookie_t new_dhp2
,
799 devmap_handle_t
*dhp
;
800 devmap_handle_t
*ndhp
;
801 drm_inst_state_t
*statep
;
802 struct ddi_umem_cookie
*cp
;
803 struct ddi_umem_cookie
*ncp
;
805 dhp
= (devmap_handle_t
*)dhc
;
806 statep
= (drm_inst_state_t
*)pvtp
;
808 mutex_enter(&statep
->dis_ctxlock
);
809 cp
= (struct ddi_umem_cookie
*)dhp
->dh_cookie
;
810 if (new_dhp1
!= NULL
) {
811 ndhp
= (devmap_handle_t
*)new_dhp1
;
812 ncp
= (struct ddi_umem_cookie
*)ndhp
->dh_cookie
;
818 if (new_dhp2
!= NULL
) {
819 ndhp
= (devmap_handle_t
*)new_dhp2
;
820 ncp
= (struct ddi_umem_cookie
*)ndhp
->dh_cookie
;
827 if (cp
->cook_refcnt
== 0) {
828 gfxp_umem_cookie_destroy(dhp
->dh_cookie
);
829 dhp
->dh_cookie
= NULL
;
831 mutex_exit(&statep
->dis_ctxlock
);
837 drm_devmap_dup(devmap_cookie_t dhc
, void *pvtp
, devmap_cookie_t new_dhc
,
840 devmap_handle_t
*dhp
;
841 drm_inst_state_t
*statep
;
842 struct ddi_umem_cookie
*cp
;
844 statep
= (drm_inst_state_t
*)pvtp
;
845 mutex_enter(&statep
->dis_ctxlock
);
846 dhp
= (devmap_handle_t
*)dhc
;
847 cp
= (struct ddi_umem_cookie
*)dhp
->dh_cookie
;
849 mutex_exit(&statep
->dis_ctxlock
);
856 drm_dev_to_instance(dev_t dev
)
858 return (DEV2INST(dev
));
862 * drm_supp_alloc_drv_entry()
865 * Create a DRM entry and add it into the instance list (drm_inst_head).
866 * Note that we don't allow a duplicated entry
868 static drm_inst_list_t
*
869 drm_supp_alloc_drv_entry(dev_info_t
*dip
)
871 drm_inst_list_t
**plist
;
872 drm_inst_list_t
*list
;
873 drm_inst_list_t
*entry
;
875 /* protect the driver list */
876 mutex_enter(&drm_inst_list_lock
);
877 plist
= &drm_inst_head
;
880 if (list
->disl_state
.mis_dip
== dip
) {
881 mutex_exit(&drm_inst_list_lock
);
882 cmn_err(CE_WARN
, "%s%d already registered",
883 ddi_driver_name(dip
), ddi_get_instance(dip
));
886 plist
= &list
->disl_next
;
887 list
= list
->disl_next
;
890 /* "dip" is not registered, create new one and add to list */
891 entry
= kmem_zalloc(sizeof (*entry
), KM_SLEEP
);
893 entry
->disl_state
.mis_dip
= dip
;
894 mutex_init(&entry
->disl_state
.mis_lock
, NULL
, MUTEX_DRIVER
, NULL
);
895 mutex_init(&entry
->disl_state
.dis_ctxlock
, NULL
, MUTEX_DRIVER
, NULL
);
896 mutex_exit(&drm_inst_list_lock
);
900 } /* drm_supp_alloc_drv_entry */
903 * drm_supp_free_drv_entry()
906 drm_supp_free_drv_entry(dev_info_t
*dip
)
908 drm_inst_list_t
*list
;
909 drm_inst_list_t
**plist
;
910 drm_inst_state_t
*mstate
;
912 /* protect the driver list */
913 mutex_enter(&drm_inst_list_lock
);
914 plist
= &drm_inst_head
;
917 if (list
->disl_state
.mis_dip
== dip
) {
918 *plist
= list
->disl_next
;
919 mstate
= &list
->disl_state
;
920 mutex_destroy(&mstate
->mis_lock
);
921 mutex_destroy(&mstate
->dis_ctxlock
);
922 kmem_free(list
, sizeof (*list
));
923 mutex_exit(&drm_inst_list_lock
);
926 plist
= &list
->disl_next
;
927 list
= list
->disl_next
;
929 mutex_exit(&drm_inst_list_lock
);
931 } /* drm_supp_free_drv_entry() */
934 * drm_sup_devt_to_state()
937 * Get the soft state of DRM instance by device number
939 static drm_inst_state_t
*
940 drm_sup_devt_to_state(dev_t dev
)
942 drm_inst_list_t
*list
;
943 drm_inst_state_t
*mstate
;
944 major_t major
= getmajor(dev
);
945 int instance
= DEV2INST(dev
);
947 mutex_enter(&drm_inst_list_lock
);
948 list
= drm_inst_head
;
950 mstate
= &list
->disl_state
;
951 mutex_enter(&mstate
->mis_lock
);
953 if ((mstate
->mis_major
== major
) &&
954 (ddi_get_instance(mstate
->mis_dip
) == instance
)) {
955 mutex_exit(&mstate
->mis_lock
);
956 mutex_exit(&drm_inst_list_lock
);
960 list
= list
->disl_next
;
961 mutex_exit(&mstate
->mis_lock
);
964 mutex_exit(&drm_inst_list_lock
);
967 } /* drm_sup_devt_to_state() */
970 drm_supp_get_irq(void *handle
)
972 drm_inst_list_t
*list
;
973 drm_inst_state_t
*mstate
;
976 list
= (drm_inst_list_t
*)handle
;
977 mstate
= &list
->disl_state
;
978 ASSERT(mstate
!= NULL
);
979 irq
= pci_config_get8(mstate
->mis_cfg_hdl
, PCI_CONF_ILINE
);
984 drm_supp_device_capability(void *handle
, int capid
)
986 drm_inst_list_t
*list
;
987 drm_inst_state_t
*mstate
;
991 list
= (drm_inst_list_t
*)handle
;
992 mstate
= &list
->disl_state
;
993 ASSERT(mstate
!= NULL
);
995 /* has capabilities list ? */
996 if ((pci_config_get16(mstate
->mis_cfg_hdl
, PCI_CONF_STAT
) &
997 PCI_CONF_CAP_MASK
) == 0)
1000 caps_ptr
= pci_config_get8(mstate
->mis_cfg_hdl
, PCI_CONF_CAP_PTR
);
1001 while (caps_ptr
!= PCI_CAP_NEXT_PTR_NULL
) {
1002 cap
= pci_config_get32(mstate
->mis_cfg_hdl
, caps_ptr
);
1003 if ((cap
& PCI_CONF_CAPID_MASK
) == capid
)
1005 caps_ptr
= pci_config_get8(mstate
->mis_cfg_hdl
,
1006 caps_ptr
+ PCI_CAP_NEXT_PTR
);