/*
*/
/*
* Common misc module interfaces of DRM under Solaris
*/
/*
* the efb driver for sparc currently builds this into the efb module
* instead of as a separately loadable misc module like x86 does.
*/
#include "drm_sunmod.h"
#include <vm/seg_kmem.h>
/* Identifier of this driver */
#ifdef __x86
/*
* devmap callbacks for AGP and PCI GART
*/
static int drm_devmap_dup(devmap_cookie_t, void *,
devmap_cookie_t, void **);
static void drm_devmap_unmap(devmap_cookie_t, void *,
DEVMAP_OPS_REV, /* devmap_rev */
drm_devmap_map, /* devmap_map */
NULL, /* devmap_access */
drm_devmap_dup, /* devmap_dup */
drm_devmap_unmap /* devmap_unmap */
};
#endif
static void drm_supp_free_drv_entry(dev_info_t *);
/*
* Common device operations structure for all DRM drivers
*/
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 */
};
void *
{
int error;
return (NULL);
}
/* create a minor node for common graphics ops */
if (error != DDI_SUCCESS) {
DRM_ERROR("drm_supp_register: "
"failed to create minor node for gfx");
goto exit2;
}
/* setup mapping for later PCI config space access */
if (error != DDI_SUCCESS) {
DRM_ERROR("drm_supp_register: "
"PCI configuration space setup failed");
goto exit2;
}
return ((void *)mstate);
return (NULL);
}
int
{
/* free PCI config access handle */
if (mstate->mis_cfg_hdl)
/* remove all minor nodes */
return (DDI_SUCCESS);
}
static int
{
int newminor;
int instance;
int err;
/*
* return ENXIO for deferred attach so that system can
* attach us again.
*/
return (ENXIO);
/*
* The least 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.
*/
#ifdef __x86
/*
* No operations for VGA & AGP master devices, always return OK.
*/
return (0);
#endif
/*
* From here, we start to process drm
*/
if (!dp)
return (ENXIO);
/*
* Drm driver implements a software lock to serialize access
* to graphics hardware based on per-process granulation. Before
* operating graphics hardware, all clients, including kernel
* and applications, must acquire this lock via DRM_IOCTL_LOCK
* ioctl, and release it via DRM_IOCTL_UNLOCK after finishing
* operations. Drm driver will grant r/w permission to the
* process which acquires this lock (Kernel is assumed to have
* process ID 0).
*
* A process might be terminated without releasing drm lock, in
* this case, drm driver is responsible for clearing the holding.
* To be informed of process exiting, drm driver uses clone open
* to guarantee that each call to open(9e) have one corresponding
* call to close(9e). In most cases, a process will close drm
* during process termination, so that drm driver could have a
* chance to release drm lock.
*
* In fact, a driver cannot know exactly when a process exits.
* Clone open doesn't address this issue completely: Because of
* inheritance, child processes inherit file descriptors from
* their parent. As a result, if the parent exits before its
* children, drm close(9e) entrypoint won't be called until all
* of its children terminate.
*
* Another issue brought up by inheritance is the process PID
* that calls the drm close() entry point may not be the same
* as the one who called open(). Per-process struct is allocated
* when a process first open() drm, and released when the process
* last close() drm. Since open()/close() may be not the same
* process, PID cannot be used for key to lookup per-process
* struct. So, we associate minor number with per-process struct
* during open()'ing, and find corresponding process struct
* via minor number when close() is called.
*/
newminor ++) {
break;
}
goto gotminor;
}
return (EMFILE);
if (err) {
return (err);
}
/* return a clone minor */
return (err);
}
static int
{
int ret;
return (EBADF);
return (0);
DRM_ERROR("drm_sun_close: NULL soft state");
return (ENXIO);
}
return (ret);
}
static int
{
extern drm_ioctl_desc_t drm_ioctls[];
#ifdef __x86
#endif
int retval;
int nr;
if (cmd == VIS_GETIDENTIFIER) {
sizeof (struct vis_identifier), mode))
return (EFAULT);
}
return (EIO);
}
#ifdef __x86
switch (minor) {
case GFX_MINOR:
return (retval);
case AGPMASTER_MINOR:
return (retval);
case DRM_MINOR:
default: /* DRM cloning minor nodes */
break;
}
#endif /* x86 */
/* It's not a core DRM ioctl, try driver-specific. */
/* The array entries begin at DRM_COMMAND_BASE ioctl nr */
nr -= DRM_COMMAND_BASE;
DRM_ERROR("Bad driver ioctl number, 0x%x (of 0x%x)",
return (EINVAL);
}
}
return (ENOTSUP);
}
DRM_ERROR("drm_sun_ioctl : can't find authenticator");
return (EACCES);
}
return (EACCES);
return (retval);
}
static int
{
#ifndef __x86
#endif
#ifdef __x86
unsigned long aperbase;
#endif
int ret;
};
};
return (ENXIO);
switch (minor) {
#ifdef __x86
case GFX_MINOR:
return (ret);
case AGPMASTER_MINOR:
return (ENOTSUP);
#endif /* x86 */
case DRM_MINOR:
break;
default:
/* DRM cloning nodes */
if (minor > MAX_CLONE_MINOR)
return (EBADF);
break;
}
DRM_ERROR("drm_sun_devmap: NULL soft state");
return (EINVAL);
}
/*
* We will solve 32-bit application on 64-bit kernel
* issue later, now, we just use low 32-bit
*/
handle &= 0xffffffff;
if (handle ==
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.
*/
break;
}
}
}
return (-1);
}
return (-1);
}
case _DRM_REGISTERS:
#ifdef _BIG_ENDIAN
dev_attr = &dev_attr_le;
#else
#endif /* _BIG_ENDIAN */
}
/*FALLTHROUGH*/
case _DRM_FRAME_BUFFER:
{
int regno;
if (regno < 0) {
DRM_ERROR("devmap: failed to get register"
return (EINVAL);
}
}
0, dev_attr);
if (ret != 0) {
*maplen = 0;
DRM_ERROR("devmap: failed, regno=%d,type=%d,"
" handle=0x%lx, offset=0x%llx, len=0x%lx",
return (ret);
}
return (ret);
}
case _DRM_SHM:
return (EINVAL);
if (ret != 0) {
*maplen = 0;
return (ret);
}
return (DDI_SUCCESS);
#ifdef __x86
case _DRM_AGP:
"memory before AGP support is enabled");
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
break;
case _DRM_SCATTER_GATHER:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
if (ret != 0) {
return (DDI_FAILURE);
}
break;
#endif /* x86 */
default:
return (DDI_FAILURE);
}
#ifdef __x86
return (DDI_SUCCESS);
#endif
}
#ifdef __x86
/*ARGSUSED*/
static int
{
/*
* This driver only supports MAP_SHARED,
* and doesn't support MAP_PRIVATE
*/
if (flags & MAP_PRIVATE) {
return (EINVAL);
}
return (0);
}
/*ARGSUSED*/
static void
void **new_pvtp2)
{
ncp->cook_refcnt ++;
}
ncp->cook_refcnt ++;
}
cp->cook_refcnt --;
if (cp->cook_refcnt == 0) {
}
}
/*ARGSUSED*/
static int
void **new_pvtp)
{
cp->cook_refcnt ++;
return (0);
}
#endif /* x86 */
int
{
}
/*
* 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
*/
static drm_inst_list_t *
{
/* protect the driver list */
plist = &drm_inst_head;
while (list) {
return (NULL);
}
}
/* "dip" is not registered, create new one and add to list */
return (entry);
} /* drm_supp_alloc_drv_entry */
/*
* drm_supp_free_drv_entry()
*/
static void
{
/* protect the driver list */
plist = &drm_inst_head;
while (list) {
return;
}
}
} /* drm_supp_free_drv_entry() */
/*
* drm_sup_devt_to_state()
*
* description:
* Get the soft state of DRM instance by device number
*/
{
while (list) {
return (mstate);
}
}
return (NULL);
} /* drm_sup_devt_to_state() */
int
{
int irq;
return (irq);
}
int
{
/* has capabilities list ? */
PCI_CONF_CAP_MASK) == 0)
return (NULL);
while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
return (cap);
}
return (0);
}
{
else
return (NULL);
break;
}
return (mp);
}