summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/drm/drm_sunmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/drm/drm_sunmod.c')
-rw-r--r--usr/src/uts/common/io/drm/drm_sunmod.c1372
1 files changed, 578 insertions, 794 deletions
diff --git a/usr/src/uts/common/io/drm/drm_sunmod.c b/usr/src/uts/common/io/drm/drm_sunmod.c
index 2f69229..24971ba 100644
--- a/usr/src/uts/common/io/drm/drm_sunmod.c
+++ b/usr/src/uts/common/io/drm/drm_sunmod.c
@@ -1,27 +1,28 @@
/*
- * CDDL HEADER START
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved.
*/
/*
@@ -34,288 +35,427 @@
*/
#include "drm_sunmod.h"
+#include "drm_sun_idr.h"
#include <sys/modctl.h>
#include <sys/kmem.h>
#include <vm/seg_kmem.h>
-static struct modlmisc modlmisc = {
- &mod_miscops, "DRM common interfaces"
+int drm_debug_flag = 0;
+int mdb_track_enable = B_FALSE;
+
+/* Identifier of this driver */
+static struct vis_identifier text_ident = { "SUNWdrm" };
+
+static ddi_device_acc_attr_t dev_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_STRICTORDER_ACC,
+ DDI_FLAGERR_ACC
};
-static struct modlinkage modlinkage = {
- MODREV_1, (void *)&modlmisc, NULL
+static ddi_device_acc_attr_t gem_dev_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_MERGING_OK_ACC,
+ DDI_FLAGERR_ACC
};
-static drm_inst_list_t *drm_inst_head;
-static kmutex_t drm_inst_list_lock;
+extern int __init drm_core_init(void);
+extern void __exit drm_core_exit(void);
+extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
-static int drm_sun_open(dev_t *, int, int, cred_t *);
-static int drm_sun_close(dev_t, int, int, cred_t *);
-static int drm_sun_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-static int drm_sun_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
- size_t *, uint_t);
+struct find_gem_object {
+ offset_t offset;
+ struct drm_gem_object *obj;
+};
-/*
- * devmap callbacks for AGP and PCI GART
- */
-static int drm_devmap_map(devmap_cookie_t, dev_t,
- uint_t, offset_t, size_t, void **);
-static int drm_devmap_dup(devmap_cookie_t, void *,
- devmap_cookie_t, void **);
-static void drm_devmap_unmap(devmap_cookie_t, void *,
- offset_t, size_t, devmap_cookie_t, void **, devmap_cookie_t, void **);
+static int
+drm_devmap_map(devmap_cookie_t dhc, dev_t dev_id, uint_t flags,
+ offset_t offset, size_t len, void **new_priv)
+{
+ _NOTE(ARGUNUSED(offset, len))
-static drm_inst_list_t *drm_supp_alloc_drv_entry(dev_info_t *);
-static drm_inst_state_t *drm_sup_devt_to_state(dev_t);
-static void drm_supp_free_drv_entry(dev_info_t *);
+ devmap_handle_t *dhp;
+ struct ddi_umem_cookie *cp;
+ struct drm_minor *minor;
+ struct drm_device *dev;
+ int minor_id;
-static struct devmap_callback_ctl drm_devmap_callbacks = {
- DEVMAP_OPS_REV, /* devmap_rev */
- drm_devmap_map, /* devmap_map */
- NULL, /* devmap_access */
- drm_devmap_dup, /* devmap_dup */
- drm_devmap_unmap /* devmap_unmap */
-};
+ minor_id = DRM_DEV2MINOR(dev_id);
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ dev = minor->dev;
-/*
- * Common device operations structure for all DRM drivers
- */
-struct cb_ops drm_cb_ops = {
- drm_sun_open, /* cb_open */
- drm_sun_close, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- drm_sun_ioctl, /* cb_ioctl */
- drm_sun_devmap, /* cb_devmap */
- nodev, /* cb_mmap */
- NULL, /* cb_segmap */
- nochpoll, /* cb_chpoll */
- ddi_prop_op, /* cb_prop_op */
- 0, /* cb_stream */
- D_NEW | D_MTSAFE |D_DEVMAP /* cb_flag */
-};
+ /*
+ * This driver only supports MAP_SHARED,
+ * and doesn't support MAP_PRIVATE
+ */
+ if (flags & MAP_PRIVATE) {
+ DRM_ERROR("Not support MAP_PRIVATE");
+ return (EINVAL);
+ }
-int
-_init(void)
+ mutex_enter(&dev->struct_mutex);
+ dhp = (devmap_handle_t *)dhc;
+ cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
+ cp->cook_refcnt = 1;
+ mutex_exit(&dev->struct_mutex);
+
+ *new_priv = dev;
+ return (0);
+}
+
+static int
+drm_devmap_dup(devmap_cookie_t dhc, void *pvtp, devmap_cookie_t new_dhc,
+ void **new_pvtp)
{
- int error;
+ _NOTE(ARGUNUSED(new_dhc))
- if ((error = mod_install(&modlinkage)) != 0) {
- return (error);
- }
+ struct drm_device *dev = (struct drm_device *)pvtp;
+ devmap_handle_t *dhp;
+ struct ddi_umem_cookie *cp;
+
+ mutex_enter(&dev->struct_mutex);
+ dhp = (devmap_handle_t *)dhc;
+ cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
+ cp->cook_refcnt++;
+ mutex_exit(&dev->struct_mutex);
- /* initialize the instance list lock */
- mutex_init(&drm_inst_list_lock, NULL, MUTEX_DRIVER, NULL);
+ *new_pvtp = dev;
return (0);
}
-int
-_fini(void)
+static void
+drm_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len,
+ devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2,
+ void **new_pvtp2)
{
- int err;
+ _NOTE(ARGUNUSED(off, len))
- if ((err = mod_remove(&modlinkage)) != 0)
- return (err);
+ struct drm_device *dev;
+ devmap_handle_t *dhp;
+ devmap_handle_t *ndhp;
+ struct ddi_umem_cookie *cp;
+ struct ddi_umem_cookie *ncp;
- mutex_destroy(&drm_inst_list_lock);
- return (0);
+ dhp = (devmap_handle_t *)dhc;
+ dev = (struct drm_device *)pvtp;
+
+ mutex_enter(&dev->struct_mutex);
+
+ cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
+ if (new_dhp1 != NULL) {
+ ndhp = (devmap_handle_t *)new_dhp1;
+ ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
+ ncp->cook_refcnt++;
+ *new_pvtp1 = dev;
+ ASSERT(ncp == cp);
+ }
+
+ if (new_dhp2 != NULL) {
+ ndhp = (devmap_handle_t *)new_dhp2;
+ ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
+ ncp->cook_refcnt++;
+ *new_pvtp2 = dev;
+ ASSERT(ncp == cp);
+ }
+
+ /* FIXME: dh_cookie should not be released here. */
+#if 0
+ cp->cook_refcnt--;
+ if (cp->cook_refcnt == 0) {
+ gfxp_umem_cookie_destroy(dhp->dh_cookie);
+ dhp->dh_cookie = NULL;
+ }
+#endif
+
+ mutex_exit(&dev->struct_mutex);
}
-int
-_info(struct modinfo *modinfop)
+static struct devmap_callback_ctl drm_devmap_callbacks = {
+ DEVMAP_OPS_REV, /* devmap_rev */
+ drm_devmap_map, /* devmap_map */
+ NULL, /* devmap_access */
+ drm_devmap_dup, /* devmap_dup */
+ drm_devmap_unmap /* devmap_unmap */
+};
+
+static struct drm_local_map *
+__find_local_map(struct drm_device *dev, offset_t offset)
{
- return (mod_info(&modlinkage, modinfop));
+ struct drm_map_list *entry;
+
+ entry = idr_find(&dev->map_idr, offset >> PAGE_SHIFT);
+ if (entry)
+ return (entry->map);
+
+ return (NULL);
}
-void *
-drm_supp_register(dev_info_t *dip, drm_device_t *dp)
+static int
+drm_gem_map(devmap_cookie_t dhp, dev_t dev, uint_t flags, offset_t off,
+ size_t len, void **pvtp)
{
- int error;
- char buf[80];
- int instance = ddi_get_instance(dip);
- ddi_acc_handle_t pci_cfg_handle;
- agp_master_softc_t *agpm;
- drm_inst_state_t *mstate;
- drm_inst_list_t *entry;
- gfxp_vgatext_softc_ptr_t gfxp;
- struct dev_ops *devop;
-
- ASSERT(dip != NULL);
-
- entry = drm_supp_alloc_drv_entry(dip);
- if (entry == NULL) {
- cmn_err(CE_WARN, "drm_supp_register: failed to get softstate");
- return (NULL);
+ _NOTE(ARGUNUSED(dhp, flags, len))
+
+ struct drm_device *drm_dev;
+ struct drm_minor *minor;
+ int minor_id = DRM_DEV2MINOR(dev);
+ drm_local_map_t *map = NULL;
+
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
+
+ drm_dev = minor->dev;
+
+ mutex_enter(&drm_dev->struct_mutex);
+ map = __find_local_map(drm_dev, off);
+ if (!map) {
+ mutex_exit(&drm_dev->struct_mutex);
+ *pvtp = NULL;
+ return (DDI_EINVAL);
}
- mstate = &entry->disl_state;
- /*
- * DRM drivers are required to use common cb_ops
- */
- devop = ddi_get_driver(dip);
- if (devop->devo_cb_ops != &drm_cb_ops) {
- devop->devo_cb_ops = &drm_cb_ops;
+ mutex_exit(&drm_dev->struct_mutex);
+
+ *pvtp = map->handle;
+
+ return (DDI_SUCCESS);
+}
+
+static int
+drm_gem_map_access(devmap_cookie_t dhp, void *pvt, offset_t offset, size_t len,
+ uint_t type, uint_t rw)
+{
+ struct drm_device *dev;
+ struct drm_gem_object *obj;
+ struct gem_map_list *seg;
+
+ obj = (struct drm_gem_object *)pvt;
+ if (obj == NULL) {
+ goto next;
}
- /* Generic graphics initialization */
- gfxp = gfxp_vgatext_softc_alloc();
- error = gfxp_vgatext_attach(dip, DDI_ATTACH, gfxp);
- if (error != DDI_SUCCESS) {
- DRM_ERROR("drm_supp_regiter: failed to init gfx");
- goto exit1;
+ dev = obj->dev;
+ if (dev->driver->gem_fault != NULL)
+ dev->driver->gem_fault(obj);
+
+next:
+ if (devmap_load(dhp, offset, len, type, rw)) {
+ return (DDI_FAILURE);
+ }
+ if (obj != NULL) {
+ seg = drm_alloc(sizeof (struct gem_map_list), DRM_MEM_MAPS);
+ if (seg != NULL) {
+ mutex_lock(&dev->page_fault_lock);
+ seg->dhp = dhp;
+ seg->mapoffset = offset;
+ seg->maplen = len;
+ list_add_tail(&seg->head, &obj->seg_list, (caddr_t)seg);
+ mutex_unlock(&dev->page_fault_lock);
+ }
}
+ return (DDI_SUCCESS);
+}
+
+static void
+drm_gem_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off, size_t len,
+ devmap_cookie_t new_dhp1, void **newpvtp1,
+ devmap_cookie_t new_dhp2, void **newpvtp2)
+{
+ struct drm_device *dev;
+ struct drm_gem_object *obj;
+ struct gem_map_list *entry, *temp;
- /* create a minor node for common graphics ops */
- (void) sprintf(buf, "%s%d", GFX_NAME, instance);
- error = ddi_create_minor_node(dip, buf, S_IFCHR,
- INST2NODE0(instance), DDI_NT_DISPLAY, NULL);
- if (error != DDI_SUCCESS) {
- DRM_ERROR("drm_supp_regiter: "
- "failed to create minor node for gfx");
- goto exit2;
+ _NOTE(ARGUNUSED(dhp, pvtp, off, len, new_dhp1, newpvtp1))
+ _NOTE(ARGUNUSED(new_dhp2, newpvtp2))
+
+ obj = (struct drm_gem_object *)pvtp;
+ if (obj == NULL)
+ return;
+
+ dev = obj->dev;
+
+ mutex_lock(&dev->page_fault_lock);
+ if (list_empty(&obj->seg_list)) {
+ mutex_unlock(&dev->page_fault_lock);
+ return;
}
- /* setup mapping for later PCI config space access */
- error = pci_config_setup(dip, &pci_cfg_handle);
- if (error != DDI_SUCCESS) {
- DRM_ERROR("drm_supp_regiter: "
- "PCI configuration space setup failed");
- goto exit2;
+ list_for_each_entry_safe(entry, temp, struct gem_map_list,
+ &obj->seg_list, head) {
+ (void) devmap_unload(entry->dhp, entry->mapoffset,
+ entry->maplen);
+ list_del(&entry->head);
+ drm_free(entry, sizeof (struct gem_map_list), DRM_MEM_MAPS);
}
- /* AGP master attach */
- agpm = NULL;
- if (dp->driver->use_agp) {
- DRM_DEBUG("drm_supp_regiter: driver use AGP\n");
- error = agpmaster_attach(dip, &agpm,
- pci_cfg_handle, INST2NODE1(instance));
- if ((error != DDI_SUCCESS) && (dp->driver->require_agp)) {
- DRM_ERROR("drm_supp_regiter: "
- "AGP master support not available");
- goto exit3;
- }
+ mutex_unlock(&dev->page_fault_lock);
+}
+
+static struct devmap_callback_ctl drm_gem_map_ops = {
+ DEVMAP_OPS_REV, /* devmap_ops version number */
+ drm_gem_map, /* devmap_ops map routine */
+ drm_gem_map_access, /* devmap_ops access routine */
+ NULL, /* devmap_ops dup routine */
+ drm_gem_unmap, /* devmap_ops unmap routine */
+};
+
+static int
+__devmap_general(struct drm_device *dev, devmap_cookie_t dhp,
+ struct drm_local_map *map, size_t len, size_t *maplen)
+{
+ off_t regoff;
+ int regno, ret;
+
+ regno = drm_get_pci_index_reg(dev->devinfo,
+ map->offset, (uint_t)len, &regoff);
+ if (regno < 0) {
+ DRM_ERROR("drm_get_pci_index_reg() failed");
+ return (-EINVAL);
}
- mutex_enter(&mstate->mis_lock);
- mstate->mis_major = ddi_driver_major(dip);
- mstate->mis_dip = dip;
- mstate->mis_gfxp = gfxp;
- mstate->mis_agpm = agpm;
- mstate->mis_cfg_hdl = pci_cfg_handle;
- mstate->mis_devp = dp;
- mutex_exit(&mstate->mis_lock);
-
- /* create minor node for DRM access */
- (void) sprintf(buf, "%s%d", DRM_DEVNODE, instance);
- if (ddi_create_minor_node(dip, buf, S_IFCHR,
- INST2NODE2(instance), DDI_NT_DISPLAY_DRM, 0)) {
- DRM_ERROR("supp_regiter: faled to create minor node for drm");
- goto exit4;
+ ret = devmap_devmem_setup(dhp, dev->devinfo, NULL,
+ regno, (offset_t)regoff, len, PROT_ALL,
+ 0, &dev_attr);
+ if (ret != DDI_SUCCESS) {
+ DRM_ERROR("devmap_devmem_setup failed, ret=%d", ret);
+ return (-EFAULT);
}
- return ((void *)mstate);
+ *maplen = len;
+ return (0);
+}
-exit4:
- if ((dp->driver->use_agp) && agpm)
- agpmaster_detach(&agpm);
-exit3:
- pci_config_teardown(&pci_cfg_handle);
-exit2:
- (void) gfxp_vgatext_detach(dip, DDI_DETACH, gfxp);
-exit1:
- gfxp_vgatext_softc_free(gfxp);
- drm_supp_free_drv_entry(dip);
- ddi_remove_minor_node(dip, NULL);
+static int
+__devmap_shm(struct drm_device *dev, devmap_cookie_t dhp,
+ struct drm_local_map *map, size_t len, size_t *maplen)
+{
+ int ret;
- return (NULL);
-}
+ if (!map->umem_cookie)
+ return (-EINVAL);
+ len = ptob(btopr(map->size));
-int
-drm_supp_unregister(void *handle)
+ ret = devmap_umem_setup(dhp, dev->devinfo,
+ NULL, map->umem_cookie, 0, len, PROT_ALL,
+ IOMEM_DATA_CACHED, NULL);
+ if (ret != DDI_SUCCESS) {
+ DRM_ERROR("devmap_umem_setup failed, ret=%d", ret);
+ return (-EFAULT);
+ }
+
+ *maplen = len;
+ return (0);
+}
+
+static int
+__devmap_agp(struct drm_device *dev, devmap_cookie_t dhp,
+ struct drm_local_map *map, size_t len, size_t *maplen)
{
- drm_inst_list_t *list;
- drm_inst_state_t *mstate;
-
- list = (drm_inst_list_t *)handle;
- mstate = &list->disl_state;
- mutex_enter(&mstate->mis_lock);
-
- /* AGP master detach */
- if (mstate->mis_agpm != NULL)
- agpmaster_detach(&mstate->mis_agpm);
-
- /* free PCI config access handle */
- if (mstate->mis_cfg_hdl)
- pci_config_teardown(&mstate->mis_cfg_hdl);
-
- /* graphics misc module detach */
- if (mstate->mis_gfxp) {
- (void) gfxp_vgatext_detach(mstate->mis_dip, DDI_DETACH,
- mstate->mis_gfxp);
- gfxp_vgatext_softc_free(mstate->mis_gfxp);
+ int ret;
+
+ if (dev->agp == NULL) {
+ DRM_ERROR("attempted to mmap AGP"
+ "memory before AGP support is enabled");
+ return (-ENODEV);
}
- mstate->mis_devp = NULL;
+ len = ptob(btopr(len));
- /* remove all minor nodes */
- ddi_remove_minor_node(mstate->mis_dip, NULL);
- mutex_exit(&mstate->mis_lock);
- drm_supp_free_drv_entry(mstate->mis_dip);
+ ret = devmap_umem_setup(dhp, dev->devinfo,
+ &drm_devmap_callbacks, map->umem_cookie, 0, len, PROT_ALL,
+ IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr);
+ if (ret != DDI_SUCCESS) {
+ DRM_ERROR("devmap_umem_setup() failed, ret=%d", ret);
+ return (-EFAULT);
+ }
- return (DDI_SUCCESS);
+ *maplen = len;
+ return (0);
}
+static int
+__devmap_sg(struct drm_device *dev, devmap_cookie_t dhp,
+ struct drm_local_map *map, size_t len, size_t *maplen)
+{
+ int ret;
+
+ len = ptob(btopr(len));
+ if (len > map->size) {
+ DRM_ERROR("offset=0x%lx, virtual=0x%p, "
+ "mapsize=0x%lx, len=0x%lx",
+ map->offset, dev->sg->virtual, map->size, len);
+ return (-EINVAL);
+ }
+
+ ret = devmap_umem_setup(dhp, dev->devinfo,
+ &drm_devmap_callbacks, map->umem_cookie, 0, len, PROT_ALL,
+ IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr);
+ if (ret != DDI_SUCCESS) {
+ DRM_ERROR("devmap_umem_setup() fail");
+ return (-EFAULT);
+ }
+
+ *maplen = len;
+ return (0);
+}
-/*ARGSUSED*/
static int
-drm_sun_open(dev_t *devp, int flag, int otyp, cred_t *credp)
+__devmap_gem(struct drm_device *dev, devmap_cookie_t dhp,
+ struct drm_local_map *map, size_t *maplen)
{
- drm_inst_state_t *mstate;
- drm_cminor_t *mp, *newp;
- drm_device_t *dp;
- minor_t minor;
- int newminor;
- int instance;
- int err;
-
- mstate = drm_sup_devt_to_state(*devp);
- /*
- * return ENXIO for deferred attach so that system can
- * attach us again.
- */
- if (mstate == NULL)
- return (ENXIO);
+ struct devmap_callback_ctl *callbackops = NULL;
+ int ret;
- /*
- * The lest significant 15 bits are used for minor_number, and
- * the mid 3 bits are used for instance number. All minor numbers
- * are used as follows:
- * 0 -- gfx
- * 1 -- agpmaster
- * 2 -- drm
- * (3, MAX_CLONE_MINOR) -- drm minor node for clone open.
- */
- minor = DEV2MINOR(*devp);
- instance = DEV2INST(*devp);
- ASSERT(minor <= MAX_CLONE_MINOR);
+ if (map->callback == 1) {
+ callbackops = &drm_gem_map_ops;
+ }
+
+ if (!map->umem_cookie)
+ return (-EINVAL);
+
+ ret = gfxp_devmap_umem_setup(dhp, dev->devinfo, callbackops,
+ map->umem_cookie, 0, map->size, PROT_ALL,
+ IOMEM_DATA_UC_WR_COMBINE | DEVMAP_ALLOW_REMAP, &gem_dev_attr);
+ if (ret != DDI_SUCCESS) {
+ DRM_ERROR("gfxp_devmap_umem_setup failed, ret=%d", ret);
+ return (-EFAULT);
+ }
+
+ *maplen = map->size;
+ return (0);
+}
+
+static int
+drm_sun_open(dev_t *dev_id, int flag, int otyp, cred_t *credp)
+{
+ _NOTE(ARGUNUSED(otyp))
+
+ int minor_id = DRM_DEV2MINOR(*dev_id);
+ struct drm_minor *minor;
+ int clone_id;
+ int ret;
+
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
/*
* No operations for VGA & AGP mater devices, always return OK.
*/
- if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
return (0);
- /*
- * From here, we start to process drm
- */
-
- dp = mstate->mis_devp;
- if (!dp)
- return (ENXIO);
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
+ return (0);
/*
* Drm driver implements a software lock to serialize access
@@ -352,86 +492,79 @@ drm_sun_open(dev_t *devp, int flag, int otyp, cred_t *credp)
* during open()'ing, and find corresponding process struct
* via minor number when close() is called.
*/
- newp = kmem_zalloc(sizeof (drm_cminor_t), KM_SLEEP);
- mutex_enter(&dp->dev_lock);
- for (newminor = DRM_MIN_CLONEMINOR; newminor < MAX_CLONE_MINOR;
- newminor ++) {
- TAILQ_FOREACH(mp, &dp->minordevs, link) {
- if (mp->minor == newminor)
- break;
- }
- if (mp == NULL)
- goto gotminor;
+ ret = idr_get_new_above(&minor->clone_idr, NULL, 0, &clone_id);
+ if (ret)
+ return (EMFILE);
+
+ if (clone_id > DRM_CLONEID_MAX) {
+ (void) idr_remove(&minor->clone_idr, clone_id);
+ return (EMFILE);
}
- mutex_exit(&dp->dev_lock);
- (void) kmem_free(newp, sizeof (drm_cminor_t));
- return (EMFILE);
-
-gotminor:
- TAILQ_INSERT_TAIL(&dp->minordevs, newp, link);
- newp->minor = newminor;
- mutex_exit(&dp->dev_lock);
- err = drm_open(dp, newp, flag, otyp, credp);
- if (err) {
- mutex_enter(&dp->dev_lock);
- TAILQ_REMOVE(&dp->minordevs, newp, link);
- (void) kmem_free(newp, sizeof (drm_cminor_t));
- mutex_exit(&dp->dev_lock);
-
- return (err);
+ ret = drm_open(minor, clone_id, flag, credp);
+ if (ret) {
+ (void) idr_remove(&minor->clone_idr, clone_id);
+ return (-ret);
}
- /* return a clone minor */
- newminor = newminor | (instance << NBITSMNODE);
- *devp = makedevice(getmajor(*devp), newminor);
- return (err);
+ *dev_id = DRM_MAKEDEV(getmajor(*dev_id), minor_id, clone_id);
+
+ return (-ret);
}
-/*ARGSUSED*/
static int
-drm_sun_close(dev_t dev, int flag, int otyp, cred_t *credp)
+drm_sun_close(dev_t dev_id, int flag, int otyp, cred_t *credp)
{
- drm_inst_state_t *mstate;
- drm_device_t *dp;
- minor_t minor;
- int ret;
+ _NOTE(ARGUNUSED(flag, otyp, credp))
- mstate = drm_sup_devt_to_state(dev);
- if (mstate == NULL)
- return (EBADF);
+ struct drm_minor *minor;
+ struct drm_file *file_priv;
+ int minor_id = DRM_DEV2MINOR(dev_id);
+ int clone_id = DRM_DEV2CLONEID(dev_id);
+ int ret = 0;
+
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
- minor = DEV2MINOR(dev);
- ASSERT(minor <= MAX_CLONE_MINOR);
- if ((minor == GFX_MINOR) || (minor == AGPMASTER_MINOR))
+ /*
+ * No operations for VGA & AGP mater devices, always return OK.
+ */
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
return (0);
- dp = mstate->mis_devp;
- if (dp == NULL) {
- DRM_ERROR("drm_sun_close: NULL soft state");
- return (ENXIO);
- }
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
+ return (0);
- ret = drm_close(dp, minor, flag, otyp, credp);
+ file_priv = idr_find(&minor->clone_idr, clone_id);
+ if (!file_priv)
+ return (EBADF);
+
+ ret = drm_release(file_priv);
+ if (ret)
+ return (-ret);
+
+ (void) idr_remove(&minor->clone_idr, clone_id);
- return (ret);
+ return (0);
}
-/*ARGSUSED*/
static int
-drm_sun_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
- cred_t *credp, int *rvalp)
+drm_sun_ioctl(dev_t dev_id, int cmd, intptr_t arg, int mode, cred_t *credp,
+ int *rvalp)
{
- extern drm_ioctl_desc_t drm_ioctls[];
+ struct drm_minor *minor;
+ struct drm_file *file_priv;
+ int minor_id = DRM_DEV2MINOR(dev_id);
+ int clone_id = DRM_DEV2CLONEID(dev_id);
- drm_inst_state_t *mstate;
- drm_device_t *dp;
- drm_ioctl_desc_t *ioctl;
- drm_ioctl_t *func;
- drm_file_t *fpriv;
- minor_t minor;
- int retval;
- int nr;
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
if (cmd == VIS_GETIDENTIFIER) {
if (ddi_copyout(&text_ident, (void *)arg,
@@ -439,572 +572,223 @@ drm_sun_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
return (EFAULT);
}
- mstate = drm_sup_devt_to_state(dev);
- if (mstate == NULL) {
- return (EIO);
- }
-
- minor = DEV2MINOR(dev);
- ASSERT(minor <= MAX_CLONE_MINOR);
- switch (minor) {
- case GFX_MINOR:
- retval = gfxp_vgatext_ioctl(dev, cmd, arg,
- mode, credp, rvalp, mstate->mis_gfxp);
- return (retval);
-
- case AGPMASTER_MINOR:
- retval = agpmaster_ioctl(dev, cmd, arg, mode,
- credp, rvalp, mstate->mis_agpm);
- return (retval);
-
- case DRM_MINOR:
- default: /* DRM cloning minor nodes */
- break;
- }
-
- dp = mstate->mis_devp;
- ASSERT(dp != NULL);
-
- nr = DRM_IOCTL_NR(cmd);
- ioctl = &drm_ioctls[nr];
- atomic_inc_32(&dp->counts[_DRM_STAT_IOCTLS]);
-
- /* It's not a core DRM ioctl, try driver-specific. */
- if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
- /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
- nr -= DRM_COMMAND_BASE;
- if (nr > dp->driver->max_driver_ioctl) {
- DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)",
- nr, dp->driver->max_driver_ioctl);
- return (EINVAL);
- }
- ioctl = &dp->driver->driver_ioctls[nr];
- }
-
- func = ioctl->func;
- if (func == NULL) {
- return (ENOTSUP);
- }
-
- mutex_enter(&dp->dev_lock);
- fpriv = drm_find_file_by_proc(dp, credp);
- mutex_exit(&dp->dev_lock);
- if (fpriv == NULL) {
- DRM_ERROR("drm_sun_ioctl : can't find authenticator");
- return (EACCES);
- }
-
- if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(credp)) ||
- ((ioctl->flags & DRM_AUTH) && !fpriv->authenticated) ||
- ((ioctl->flags & DRM_MASTER) && !fpriv->master))
- return (EACCES);
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
+ return (gfxp_vgatext_ioctl(dev_id, cmd, arg, mode, credp,
+ rvalp, minor->private));
- fpriv->dev = dev;
- fpriv->credp = credp;
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
+ return (agpmaster_ioctl(dev_id, cmd, arg, mode, credp,
+ rvalp, minor->private));
- retval = func(dp, arg, fpriv, mode);
+ file_priv = idr_find(&minor->clone_idr, clone_id);
+ if (!file_priv)
+ return (EBADF);
- return (retval);
+ return (-(drm_ioctl(dev_id, file_priv, cmd, arg, mode, credp)));
}
-/*ARGSUSED*/
static int
-drm_sun_devmap(dev_t dev, devmap_cookie_t dhp, offset_t offset,
+drm_sun_devmap(dev_t dev_id, devmap_cookie_t dhp, offset_t offset,
size_t len, size_t *maplen, uint_t model)
{
- extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
-
- drm_inst_state_t *mstate;
- drm_device_t *dp;
- ddi_umem_cookie_t cookie;
- drm_local_map_t *map = NULL;
- unsigned long aperbase;
- u_offset_t handle;
- offset_t koff;
- caddr_t kva;
- minor_t minor;
- size_t length;
- int ret;
-
- static ddi_device_acc_attr_t dev_attr = {
- DDI_DEVICE_ATTR_V0,
- DDI_NEVERSWAP_ACC,
- DDI_STRICTORDER_ACC,
- };
- static ddi_device_acc_attr_t gem_dev_attr = {
- DDI_DEVICE_ATTR_V0,
- DDI_NEVERSWAP_ACC,
- DDI_MERGING_OK_ACC
- };
-
- mstate = drm_sup_devt_to_state(dev);
- if (mstate == NULL)
- return (ENXIO);
-
- minor = DEV2MINOR(dev);
- switch (minor) {
- case GFX_MINOR:
- ret = gfxp_vgatext_devmap(dev, dhp, offset, len, maplen, model,
- mstate->mis_gfxp);
- return (ret);
-
- case AGPMASTER_MINOR:
+ struct drm_device *dev;
+ struct drm_minor *minor;
+ struct drm_file *file_priv;
+ int minor_id = DRM_DEV2MINOR(dev_id);
+ int clone_id = DRM_DEV2CLONEID(dev_id);
+ drm_local_map_t *map = NULL;
+
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
+
+ dev = minor->dev;
+
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
+ return (gfxp_vgatext_devmap(dev_id, dhp, offset, len,
+ maplen, model, minor->private));
+
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
return (ENOTSUP);
- case DRM_MINOR:
- break;
-
- default:
- /* DRM cloning nodes */
- if (minor > MAX_CLONE_MINOR)
- return (EBADF);
- break;
- }
-
-
- dp = mstate->mis_devp;
- if (dp == NULL) {
- DRM_ERROR("drm_sun_devmap: NULL soft state");
- return (EINVAL);
- }
-
- mutex_enter(&dp->dev_lock);
-
- if (dp->driver->use_gem == 1) {
- struct idr_list *entry;
- drm_cminor_t *mp;
-
- mp = drm_find_file_by_minor(dp, minor);
- if (!mp) {
- mutex_exit(&dp->dev_lock);
- DRM_ERROR("drm_sun_devmap: can't find authenticator");
- return (EACCES);
- }
-
- spin_lock(&dp->struct_mutex);
- idr_list_for_each(entry, &(mp->fpriv->object_idr)) {
- if ((uintptr_t)entry->obj == (u_offset_t)offset) {
- map = entry->obj->map;
- goto goon;
- }
- }
-goon:
- spin_unlock(&dp->struct_mutex);
- }
-
- if (map == NULL) {
- /*
- * We will solve 32-bit application on 64-bit kernel
- * issue later, now, we just use low 32-bit
- */
- handle = (u_offset_t)offset;
- handle &= 0xffffffff;
-
- TAILQ_FOREACH(map, &dp->maplist, link) {
- if (handle ==
- ((u_offset_t)((uintptr_t)map->handle) & 0xffffffff))
- break;
- }
-
- /*
- * Temporarily, because offset is phys_addr for register
- * and framebuffer, is kernel virtual_addr for others
- * Maybe we will use hash table to solve this issue later.
- */
- if (map == NULL) {
- TAILQ_FOREACH(map, &dp->maplist, link) {
- if (handle == (map->offset & 0xffffffff))
- break;
- }
- }
- }
+ file_priv = idr_find(&minor->clone_idr, clone_id);
+ if (!file_priv)
+ return (EBADF);
- if (map == NULL) {
- u_offset_t tmp;
-
- mutex_exit(&dp->dev_lock);
- cmn_err(CE_WARN, "Can't find map, offset=0x%llx, len=%x\n",
- offset, (int)len);
- cmn_err(CE_WARN, "Current mapping:\n");
- TAILQ_FOREACH(map, &dp->maplist, link) {
- tmp = (u_offset_t)((uintptr_t)map->handle) & 0xffffffff;
- cmn_err(CE_WARN, "map(handle=0x%p, size=0x%lx,type=%d,"
- "offset=0x%lx), handle=%llx, tmp=%lld", map->handle,
- map->size, map->type, map->offset, handle, tmp);
- }
- return (-1);
+ mutex_enter(&dev->struct_mutex);
+ map = __find_local_map(dev, offset);
+ if (!map) {
+ mutex_exit(&dev->struct_mutex);
+ return (EFAULT);
}
if (map->flags & _DRM_RESTRICTED) {
- mutex_exit(&dp->dev_lock);
- cmn_err(CE_WARN, "restricted map\n");
- return (-1);
+ mutex_exit(&dev->struct_mutex);
+ return (ENOTSUP);
}
+ mutex_exit(&dev->struct_mutex);
- mutex_exit(&dp->dev_lock);
switch (map->type) {
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
- {
- int regno;
- off_t regoff;
-
- regno = drm_get_pci_index_reg(dp->dip,
- map->offset, (uint_t)len, &regoff);
- if (regno < 0) {
- DRM_ERROR("devmap: failed to get register"
- " offset=0x%llx, len=0x%x", handle, len);
- return (EINVAL);
- }
-
- ret = devmap_devmem_setup(dhp, dp->dip, NULL,
- regno, (offset_t)regoff, len, PROT_ALL,
- 0, &dev_attr);
- if (ret != 0) {
- *maplen = 0;
- DRM_ERROR("devmap: failed, regno=%d,type=%d,"
- " handle=0x%x, offset=0x%llx, len=0x%x",
- regno, map->type, handle, offset, len);
- return (ret);
- }
- *maplen = len;
- return (ret);
- }
+ return (__devmap_general(dev, dhp, map, len, maplen));
case _DRM_SHM:
- if (map->drm_umem_cookie == NULL)
- return (EINVAL);
- length = ptob(btopr(map->size));
- ret = devmap_umem_setup(dhp, dp->dip, NULL,
- map->drm_umem_cookie, 0, length,
- PROT_ALL, IOMEM_DATA_CACHED, NULL);
- if (ret != 0) {
- *maplen = 0;
- return (ret);
- }
- *maplen = length;
-
- return (DDI_SUCCESS);
+ return (__devmap_shm(dev, dhp, map, len, maplen));
case _DRM_AGP:
- if (dp->agp == NULL) {
- cmn_err(CE_WARN, "drm_sun_devmap: attempted to mmap AGP"
- "memory before AGP support is enabled");
- return (DDI_FAILURE);
- }
-
- aperbase = dp->agp->base;
- koff = map->offset - aperbase;
- length = ptob(btopr(len));
- kva = map->dev_addr;
- cookie = gfxp_umem_cookie_init(kva, length);
- if (cookie == NULL) {
- cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
- return (DDI_FAILURE);
- }
-
- if ((ret = devmap_umem_setup(dhp, dp->dip,
- &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
- IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr)) < 0) {
- gfxp_umem_cookie_destroy(cookie);
- cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
- return (DDI_FAILURE);
- }
- *maplen = length;
- break;
+ return (__devmap_agp(dev, dhp, map, len, maplen));
case _DRM_SCATTER_GATHER:
- koff = map->offset - (unsigned long)(caddr_t)dp->sg->virtual;
- kva = map->dev_addr + koff;
- length = ptob(btopr(len));
- if (length > map->size) {
- cmn_err(CE_WARN, "offset=0x%lx, virtual=0x%p,"
- "mapsize=0x%lx,len=0x%lx", map->offset,
- dp->sg->virtual, map->size, len);
- return (DDI_FAILURE);
- }
- cookie = gfxp_umem_cookie_init(kva, length);
- if (cookie == NULL) {
- cmn_err(CE_WARN, "devmap:failed to get umem_cookie");
- return (DDI_FAILURE);
- }
- ret = devmap_umem_setup(dhp, dp->dip,
- &drm_devmap_callbacks, cookie, 0, length, PROT_ALL,
- IOMEM_DATA_UNCACHED | DEVMAP_ALLOW_REMAP, &dev_attr);
- if (ret != 0) {
- cmn_err(CE_WARN, "sun_devmap: umem_setup fail");
- gfxp_umem_cookie_destroy(cookie);
- return (DDI_FAILURE);
- }
- *maplen = length;
- break;
-
- case _DRM_TTM:
- if (map->drm_umem_cookie == NULL)
- return (EINVAL);
-
- if (gfxp_devmap_umem_setup(dhp, dp->dip,
- NULL, map->drm_umem_cookie, 0, map->size, PROT_ALL,
- IOMEM_DATA_UC_WR_COMBINE | DEVMAP_ALLOW_REMAP,
- &gem_dev_attr)) {
- cmn_err(CE_WARN, "devmap:failed, retval=%d", ret);
- return (DDI_FAILURE);
- }
- *maplen = map->size;
- return (DDI_SUCCESS);
+ return (__devmap_sg(dev, dhp, map, len, maplen));
- default:
- return (DDI_FAILURE);
+ case _DRM_GEM:
+ return (__devmap_gem(dev, dhp, map, maplen));
}
- return (DDI_SUCCESS);
+ return (ENOTSUP);
}
-/*ARGSUSED*/
static int
-drm_devmap_map(devmap_cookie_t dhc, dev_t dev, uint_t flags,
- offset_t offset, size_t len, void **new_priv)
+drm_sun_read(dev_t dev_id, struct uio *uiop, cred_t *credp)
{
- devmap_handle_t *dhp;
- drm_inst_state_t *statep;
- struct ddi_umem_cookie *cp;
+ _NOTE(ARGUNUSED(credp))
+
+ struct drm_minor *minor;
+ struct drm_file *file_priv;
+ int minor_id = DRM_DEV2MINOR(dev_id);
+ int clone_id = DRM_DEV2CLONEID(dev_id);
- statep = drm_sup_devt_to_state(dev);
- ASSERT(statep != NULL);
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
/*
- * This driver only supports MAP_SHARED,
- * and doesn't support MAP_PRIVATE
+ * No operations for VGA & AGP master devices, always return OK.
*/
- if (flags & MAP_PRIVATE) {
- cmn_err(CE_WARN, "!DRM driver doesn't support MAP_PRIVATE");
- return (EINVAL);
- }
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
+ return (0);
- mutex_enter(&statep->dis_ctxlock);
- dhp = (devmap_handle_t *)dhc;
- cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
- cp->cook_refcnt = 1;
- mutex_exit(&statep->dis_ctxlock);
- *new_priv = statep;
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
+ return (0);
+ file_priv = idr_find(&minor->clone_idr, clone_id);
+ if (!file_priv)
+ return (EBADF);
+
+ (void) drm_read(file_priv, uiop);
return (0);
}
-/*ARGSUSED*/
-static void
-drm_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len,
- devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2,
- void **new_pvtp2)
+static int
+drm_sun_chpoll(dev_t dev_id, short events, int anyyet, short *reventsp,
+ struct pollhead **phpp)
{
- devmap_handle_t *dhp;
- devmap_handle_t *ndhp;
- drm_inst_state_t *statep;
- struct ddi_umem_cookie *cp;
- struct ddi_umem_cookie *ncp;
+ struct drm_minor *minor;
+ struct drm_file *file_priv;
+ int minor_id = DRM_DEV2MINOR(dev_id);
+ int clone_id = DRM_DEV2CLONEID(dev_id);
- dhp = (devmap_handle_t *)dhc;
- statep = (drm_inst_state_t *)pvtp;
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (!minor)
+ return (ENODEV);
+ if (!minor->dev)
+ return (ENODEV);
- mutex_enter(&statep->dis_ctxlock);
- cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
- if (new_dhp1 != NULL) {
- ndhp = (devmap_handle_t *)new_dhp1;
- ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
- ncp->cook_refcnt ++;
- *new_pvtp1 = statep;
- ASSERT(ncp == cp);
- }
-
- if (new_dhp2 != NULL) {
- ndhp = (devmap_handle_t *)new_dhp2;
- ncp = (struct ddi_umem_cookie *)ndhp->dh_cookie;
- ncp->cook_refcnt ++;
- *new_pvtp2 = statep;
- ASSERT(ncp == cp);
- }
-
- cp->cook_refcnt --;
- if (cp->cook_refcnt == 0) {
- gfxp_umem_cookie_destroy(dhp->dh_cookie);
- dhp->dh_cookie = NULL;
- }
- mutex_exit(&statep->dis_ctxlock);
-}
+ /*
+ * No operations for VGA & AGP master devices, always return OK.
+ */
+ if (DRM_MINOR_IS_VGATEXT(minor_id))
+ return (0);
+ if (DRM_MINOR_IS_AGPMASTER(minor_id))
+ return (0);
-/*ARGSUSED*/
-static int
-drm_devmap_dup(devmap_cookie_t dhc, void *pvtp, devmap_cookie_t new_dhc,
- void **new_pvtp)
-{
- devmap_handle_t *dhp;
- drm_inst_state_t *statep;
- struct ddi_umem_cookie *cp;
+ file_priv = idr_find(&minor->clone_idr, clone_id);
+ if (!file_priv)
+ return (EBADF);
- statep = (drm_inst_state_t *)pvtp;
- mutex_enter(&statep->dis_ctxlock);
- dhp = (devmap_handle_t *)dhc;
- cp = (struct ddi_umem_cookie *)dhp->dh_cookie;
- cp->cook_refcnt ++;
- mutex_exit(&statep->dis_ctxlock);
- *new_pvtp = statep;
+ if (!anyyet) {
+ *phpp = &file_priv->drm_pollhead;
+ }
+ *reventsp = drm_poll(file_priv, events);
return (0);
}
-int
-drm_dev_to_instance(dev_t dev)
-{
- return (DEV2INST(dev));
-}
-
/*
- * drm_supp_alloc_drv_entry()
- *
- * Description:
- * Create a DRM entry and add it into the instance list (drm_inst_head).
- * Note that we don't allow a duplicated entry
+ * Common device operations structure for all DRM drivers
*/
-static drm_inst_list_t *
-drm_supp_alloc_drv_entry(dev_info_t *dip)
-{
- drm_inst_list_t **plist;
- drm_inst_list_t *list;
- drm_inst_list_t *entry;
-
- /* protect the driver list */
- mutex_enter(&drm_inst_list_lock);
- plist = &drm_inst_head;
- list = *plist;
- while (list) {
- if (list->disl_state.mis_dip == dip) {
- mutex_exit(&drm_inst_list_lock);
- cmn_err(CE_WARN, "%s%d already registered",
- ddi_driver_name(dip), ddi_get_instance(dip));
- return (NULL);
- }
- plist = &list->disl_next;
- list = list->disl_next;
- }
-
- /* "dip" is not registered, create new one and add to list */
- entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
- *plist = entry;
- entry->disl_state.mis_dip = dip;
- mutex_init(&entry->disl_state.mis_lock, NULL, MUTEX_DRIVER, NULL);
- mutex_init(&entry->disl_state.dis_ctxlock, NULL, MUTEX_DRIVER, NULL);
- mutex_exit(&drm_inst_list_lock);
+struct cb_ops drm_cb_ops = {
+ drm_sun_open, /* cb_open */
+ drm_sun_close, /* cb_close */
+ nodev, /* cb_strategy */
+ nodev, /* cb_print */
+ nodev, /* cb_dump */
+ drm_sun_read, /* cb_read */
+ nodev, /* cb_write */
+ drm_sun_ioctl, /* cb_ioctl */
+ drm_sun_devmap, /* cb_devmap */
+ nodev, /* cb_mmap */
+ NULL, /* cb_segmap */
+ drm_sun_chpoll, /* cb_chpoll */
+ ddi_prop_op, /* cb_prop_op */
+ 0, /* cb_stream */
+ D_NEW | D_MTSAFE | D_DEVMAP /* cb_flag */
+};
- return (entry);
+static struct modlmisc modlmisc = {
+ &mod_miscops, "DRM common interfaces"
+};
-} /* drm_supp_alloc_drv_entry */
+static struct modlinkage modlinkage = {
+ MODREV_1, (void *)&modlmisc, NULL
+};
-/*
- * drm_supp_free_drv_entry()
- */
-static void
-drm_supp_free_drv_entry(dev_info_t *dip)
+int
+_init(void)
{
- drm_inst_list_t *list;
- drm_inst_list_t **plist;
- drm_inst_state_t *mstate;
-
- /* protect the driver list */
- mutex_enter(&drm_inst_list_lock);
- plist = &drm_inst_head;
- list = *plist;
- while (list) {
- if (list->disl_state.mis_dip == dip) {
- *plist = list->disl_next;
- mstate = &list->disl_state;
- mutex_destroy(&mstate->mis_lock);
- mutex_destroy(&mstate->dis_ctxlock);
- kmem_free(list, sizeof (*list));
- mutex_exit(&drm_inst_list_lock);
- return;
- }
- plist = &list->disl_next;
- list = list->disl_next;
- }
- mutex_exit(&drm_inst_list_lock);
+ int ret;
-} /* drm_supp_free_drv_entry() */
+ ret = mod_install(&modlinkage);
+ if (ret)
+ return (ret);
-/*
- * drm_sup_devt_to_state()
- *
- * description:
- * Get the soft state of DRM instance by device number
- */
-static drm_inst_state_t *
-drm_sup_devt_to_state(dev_t dev)
+ return (drm_core_init());
+}
+
+int
+_fini(void)
{
- drm_inst_list_t *list;
- drm_inst_state_t *mstate;
- major_t major = getmajor(dev);
- int instance = DEV2INST(dev);
-
- mutex_enter(&drm_inst_list_lock);
- list = drm_inst_head;
- while (list) {
- mstate = &list->disl_state;
- mutex_enter(&mstate->mis_lock);
-
- if ((mstate->mis_major == major) &&
- (ddi_get_instance(mstate->mis_dip) == instance)) {
- mutex_exit(&mstate->mis_lock);
- mutex_exit(&drm_inst_list_lock);
- return (mstate);
- }
+ int ret;
- list = list->disl_next;
- mutex_exit(&mstate->mis_lock);
- }
+ ret = mod_remove(&modlinkage);
+ if (ret)
+ return (ret);
- mutex_exit(&drm_inst_list_lock);
- return (NULL);
+ drm_core_exit();
-} /* drm_sup_devt_to_state() */
+ return (0);
+}
int
-drm_supp_get_irq(void *handle)
+_info(struct modinfo *modinfop)
{
- drm_inst_list_t *list;
- drm_inst_state_t *mstate;
- int irq;
-
- list = (drm_inst_list_t *)handle;
- mstate = &list->disl_state;
- ASSERT(mstate != NULL);
- irq = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_ILINE);
- return (irq);
+ return (mod_info(&modlinkage, modinfop));
}
-int
-drm_supp_device_capability(void *handle, int capid)
+struct drm_local_map *
+drm_core_findmap(struct drm_device *dev, unsigned int token)
{
- drm_inst_list_t *list;
- drm_inst_state_t *mstate;
- uint8_t cap = 0;
- uint16_t caps_ptr;
-
- list = (drm_inst_list_t *)handle;
- mstate = &list->disl_state;
- ASSERT(mstate != NULL);
-
- /* has capabilities list ? */
- if ((pci_config_get16(mstate->mis_cfg_hdl, PCI_CONF_STAT) &
- PCI_CONF_CAP_MASK) == 0)
- return (NULL);
-
- caps_ptr = pci_config_get8(mstate->mis_cfg_hdl, PCI_CONF_CAP_PTR);
- while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
- cap = pci_config_get32(mstate->mis_cfg_hdl, caps_ptr);
- if ((cap & PCI_CONF_CAPID_MASK) == capid)
- return (cap);
- caps_ptr = pci_config_get8(mstate->mis_cfg_hdl,
- caps_ptr + PCI_CAP_NEXT_PTR);
+ struct drm_map_list *_entry;
+
+ list_for_each_entry(_entry, struct drm_map_list, &dev->maplist, head) {
+ if (_entry->user_token == token)
+ return (_entry->map);
}
- return (0);
+ return (NULL);
}