- Tie the DRM to a specific device: setunique no longer succeeds when given
a busid that doesn't correspond to the device the DRM is attached to. This is a breaking of backwards-compatibility only for the multiple-DRI-head case with X Servers that don't use interface 1.1. - Move irq_busid to drm_irq.h and make it only return the IRQ for the current device. Retains compatibility with previous X Servers, cleans up unnecessary code. This means no irq_busid on !__HAVE_IRQ, but can be changed if necessary. - Bump interface version to 1.2. This version when set signifies that the control ioctl should ignore the irq number passed in and enable the interrupt handler for the attached device. Otherwise it errors out when the passed-in irq is not equal to the device's. - Store the highest version the interface has been set to in the device. - Fix a recursion on DRM_LOCK in irq_uninstall on FreeBSD. This leaves irq_uninstall being done without the lock in some cases, but it was racey anyways.main
parent
19ee64add2
commit
66c9e3053f
|
@ -118,6 +118,8 @@ typedef struct drm_file drm_file_t;
|
|||
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
|
||||
#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
|
||||
(_map) = (_dev)->context_sareas[_ctx]; \
|
||||
} while(0)
|
||||
|
@ -316,6 +318,7 @@ struct drm_device {
|
|||
device_t device; /* Device instance from newbus */
|
||||
#endif
|
||||
dev_t devnode; /* Device number for mknod */
|
||||
int if_version; /* Highest interface version set */
|
||||
|
||||
int flags; /* Flags to open(2) */
|
||||
|
||||
|
@ -355,14 +358,21 @@ struct drm_device {
|
|||
|
||||
/* Context support */
|
||||
int irq; /* Interrupt used by board */
|
||||
int irqrid; /* Interrupt used by board */
|
||||
int irq_enabled; /* True if the irq handler is enabled */
|
||||
#ifdef __FreeBSD__
|
||||
int irqrid; /* Interrupt used by board */
|
||||
struct resource *irqr; /* Resource for interrupt used by board */
|
||||
#elif defined(__NetBSD__)
|
||||
struct pci_attach_args pa;
|
||||
pci_intr_handle_t ih;
|
||||
#endif
|
||||
void *irqh; /* Handle from bus_setup_intr */
|
||||
|
||||
int pci_domain;
|
||||
int pci_bus;
|
||||
int pci_slot;
|
||||
int pci_func;
|
||||
|
||||
atomic_t context_flag; /* Context swapping flag */
|
||||
int last_context; /* Last current context */
|
||||
#if __FreeBSD_version >= 400005
|
||||
|
@ -445,7 +455,7 @@ extern void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp);
|
|||
|
||||
#if __HAVE_IRQ
|
||||
/* IRQ support (drm_irq.h) */
|
||||
extern int DRM(irq_install)( drm_device_t *dev, int irq );
|
||||
extern int DRM(irq_install)(drm_device_t *dev);
|
||||
extern int DRM(irq_uninstall)( drm_device_t *dev );
|
||||
extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS );
|
||||
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
|
||||
|
@ -494,7 +504,7 @@ extern int DRM(version)( DRM_IOCTL_ARGS );
|
|||
extern int DRM(setversion)( DRM_IOCTL_ARGS );
|
||||
|
||||
/* Misc. IOCTL support (drm_ioctl.h) */
|
||||
extern int DRM(irq_busid)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(irq_by_busid)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(getunique)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(setunique)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(getmap)(DRM_IOCTL_ARGS);
|
||||
|
|
|
@ -134,7 +134,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
|
||||
#if __HAVE_IRQ
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
|
||||
|
@ -477,9 +479,10 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
|
||||
dev->lock.hw_lock = NULL;
|
||||
dev->lock.lock_queue = 0;
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->last_context = 0;
|
||||
dev->if_version = 0;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
dev->buf_sigio = NULL;
|
||||
|
@ -507,7 +510,7 @@ static int DRM(takedown)( drm_device_t *dev )
|
|||
|
||||
DRIVER_PRETAKEDOWN();
|
||||
#if __HAVE_IRQ
|
||||
if (dev->irq != 0)
|
||||
if (dev->irq_enabled)
|
||||
DRM(irq_uninstall)( dev );
|
||||
#endif
|
||||
|
||||
|
@ -644,6 +647,13 @@ static int DRM(init)( device_t nbdev )
|
|||
unit = minor(dev->device.dv_unit);
|
||||
#endif
|
||||
|
||||
dev->irq = pci_get_irq(dev->device);
|
||||
/* XXX Fix domain number (alpha hoses) */
|
||||
dev->pci_domain = 0;
|
||||
dev->pci_bus = pci_get_bus(dev->device);
|
||||
dev->pci_slot = pci_get_slot(dev->device);
|
||||
dev->pci_func = pci_get_function(dev->device);
|
||||
|
||||
dev->maplist = DRM(calloc)(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
|
||||
if (dev->maplist == NULL) {
|
||||
retcode = ENOMEM;
|
||||
|
|
|
@ -32,53 +32,6 @@
|
|||
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(irq_busid)( DRM_IOCTL_ARGS )
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_irq_busid_t id;
|
||||
devclass_t pci;
|
||||
device_t bus, dev;
|
||||
device_t *kids;
|
||||
int error, i, num_kids;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( id, (drm_irq_busid_t *)data, sizeof(id) );
|
||||
|
||||
pci = devclass_find("pci");
|
||||
if (!pci)
|
||||
return ENOENT;
|
||||
bus = devclass_get_device(pci, id.busnum);
|
||||
if (!bus)
|
||||
return ENOENT;
|
||||
error = device_get_children(bus, &kids, &num_kids);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev = 0;
|
||||
for (i = 0; i < num_kids; i++) {
|
||||
dev = kids[i];
|
||||
if (pci_get_slot(dev) == id.devnum
|
||||
&& pci_get_function(dev) == id.funcnum)
|
||||
break;
|
||||
}
|
||||
|
||||
free(kids, M_TEMP);
|
||||
|
||||
if (i != num_kids)
|
||||
id.irq = pci_get_irq(dev);
|
||||
else
|
||||
id.irq = 0;
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
id.busnum, id.devnum, id.funcnum, id.irq);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, id, sizeof(id) );
|
||||
|
||||
return 0;
|
||||
#else
|
||||
/* don't support interrupt-driven drivers on Net yet */
|
||||
return ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Beginning in revision 1.1 of the DRM interface, getunique will return
|
||||
* a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
|
||||
|
@ -110,6 +63,7 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
|
|||
{
|
||||
DRM_DEVICE;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique)
|
||||
return DRM_ERR(EBUSY);
|
||||
|
@ -130,6 +84,21 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
|
|||
|
||||
dev->unique[dev->unique_len] = '\0';
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return DRM_ERR(EINVAL);
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -146,10 +115,8 @@ DRM(set_busid)(drm_device_t *dev)
|
|||
if (dev->unique == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* XXX Fix domain number (alpha hoses) */
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
|
||||
0, pci_get_bus(dev->device), pci_get_slot(dev->device),
|
||||
pci_get_function(dev->device));
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,26 +227,31 @@ int DRM(getstats)( DRM_IOCTL_ARGS )
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int DRM(setversion)(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_set_version_t sv;
|
||||
drm_set_version_t retv;
|
||||
int if_version;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
|
||||
|
||||
retv.drm_di_major = 1;
|
||||
retv.drm_di_minor = 1;
|
||||
retv.drm_di_major = DRM_IF_MAJOR;
|
||||
retv.drm_di_minor = DRM_IF_MINOR;
|
||||
retv.drm_dd_major = DRIVER_MAJOR;
|
||||
retv.drm_dd_minor = DRIVER_MINOR;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
|
||||
|
||||
if (sv.drm_di_major != -1) {
|
||||
if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_di_minor > 1)
|
||||
if (sv.drm_di_major != DRM_IF_MAJOR ||
|
||||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
|
||||
return EINVAL;
|
||||
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (sv.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
|
@ -289,12 +261,11 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
|
|||
}
|
||||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_dd_minor > DRIVER_MINOR)
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
|
||||
return EINVAL;
|
||||
#ifdef DRIVER_SETVERSION
|
||||
DRIVER_SETVERSION(dev, sv);
|
||||
DRIVER_SETVERSION(dev, &sv);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -28,6 +28,29 @@
|
|||
*
|
||||
*/
|
||||
|
||||
int DRM(irq_by_busid)( DRM_IOCTL_ARGS )
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_irq_busid_t irq;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
|
||||
|
||||
if ((irq.busnum >> 8) != dev->pci_domain ||
|
||||
(irq.busnum & 0xff) != dev->pci_bus ||
|
||||
irq.devnum != dev->pci_slot ||
|
||||
irq.funcnum != dev->pci_func)
|
||||
return EINVAL;
|
||||
|
||||
irq.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
irq.busnum, irq.devnum, irq.funcnum, irq.irq);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
|
||||
static irqreturn_t
|
||||
DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
|
||||
|
@ -40,22 +63,22 @@ DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
|
|||
}
|
||||
#endif
|
||||
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
int DRM(irq_install)(drm_device_t *dev)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if ( irq == 0 || dev->dev_private == NULL)
|
||||
if (dev->irq == 0 || dev->dev_private == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_LOCK();
|
||||
if ( dev->irq ) {
|
||||
if (dev->irq_enabled) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
dev->irq = irq;
|
||||
dev->irq_enabled = 1;
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
|
||||
|
@ -68,31 +91,18 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
|
||||
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
|
||||
|
||||
#if __HAVE_VBL_IRQ && 0 /* disabled */
|
||||
TAILQ_INIT( &dev->vbl_sig_list );
|
||||
#endif
|
||||
|
||||
/* Before installing handler */
|
||||
DRM(driver_irq_preinstall)( dev );
|
||||
|
||||
/* Install handler */
|
||||
dev->irqrid = 0;
|
||||
#ifdef __FreeBSD__
|
||||
dev->irqrid = 0;
|
||||
dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid,
|
||||
0, ~0, 1, RF_SHAREABLE);
|
||||
if (!dev->irqr) {
|
||||
#elif defined(__NetBSD__)
|
||||
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
|
||||
#endif
|
||||
DRM_LOCK();
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
return ENOENT;
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD_version < 500000
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
|
||||
DRM(irq_handler), dev, &dev->irqh);
|
||||
|
@ -100,45 +110,56 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
|
||||
DRM(irq_handler_wrap), dev, &dev->irqh);
|
||||
#endif
|
||||
if ( retcode ) {
|
||||
if (retcode != 0)
|
||||
goto err;
|
||||
#elif defined(__NetBSD__)
|
||||
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
|
||||
(irqreturn_t (*)(DRM_IRQ_ARGS))DRM(irq_handler), dev);
|
||||
if ( !dev->irqh ) {
|
||||
#endif
|
||||
DRM_LOCK();
|
||||
#ifdef __FreeBSD__
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
if (!dev->irqh) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* After installing handler */
|
||||
DRM(driver_irq_postinstall)( dev );
|
||||
|
||||
return 0;
|
||||
err:
|
||||
DRM_LOCK();
|
||||
dev->irq_enabled = 0;
|
||||
#ifdef ___FreeBSD__
|
||||
if (dev->irqrid != 0) {
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
|
||||
dev->irqr);
|
||||
dev->irqrid = 0;
|
||||
}
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* XXX: This function needs to be called with the device lock held. In some
|
||||
* cases it isn't, so far.
|
||||
*/
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
int irq_enabled;
|
||||
int irqrid;
|
||||
|
||||
DRM_LOCK();
|
||||
irq = dev->irq;
|
||||
irqrid = dev->irqrid;
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
|
||||
if ( !irq )
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
dev->irq_enabled = 0;
|
||||
irqrid = dev->irqrid;
|
||||
dev->irqrid = 0;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
DRM(driver_irq_uninstall)( dev );
|
||||
|
||||
|
@ -157,14 +178,21 @@ int DRM(control)( DRM_IOCTL_ARGS )
|
|||
{
|
||||
DRM_DEVICE;
|
||||
drm_control_t ctl;
|
||||
int err;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
|
||||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return DRM_ERR(EINVAL);
|
||||
return DRM(irq_install)(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
DRM_LOCK();
|
||||
err = DRM(irq_uninstall)( dev );
|
||||
DRM_UNLOCK();
|
||||
return err;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
@ -178,7 +206,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
|
|||
struct timeval now;
|
||||
int ret;
|
||||
|
||||
if (!dev->irq)
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
|
||||
|
|
16
bsd/drmP.h
16
bsd/drmP.h
|
@ -118,6 +118,8 @@ typedef struct drm_file drm_file_t;
|
|||
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
|
||||
#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
|
||||
(_map) = (_dev)->context_sareas[_ctx]; \
|
||||
} while(0)
|
||||
|
@ -316,6 +318,7 @@ struct drm_device {
|
|||
device_t device; /* Device instance from newbus */
|
||||
#endif
|
||||
dev_t devnode; /* Device number for mknod */
|
||||
int if_version; /* Highest interface version set */
|
||||
|
||||
int flags; /* Flags to open(2) */
|
||||
|
||||
|
@ -355,14 +358,21 @@ struct drm_device {
|
|||
|
||||
/* Context support */
|
||||
int irq; /* Interrupt used by board */
|
||||
int irqrid; /* Interrupt used by board */
|
||||
int irq_enabled; /* True if the irq handler is enabled */
|
||||
#ifdef __FreeBSD__
|
||||
int irqrid; /* Interrupt used by board */
|
||||
struct resource *irqr; /* Resource for interrupt used by board */
|
||||
#elif defined(__NetBSD__)
|
||||
struct pci_attach_args pa;
|
||||
pci_intr_handle_t ih;
|
||||
#endif
|
||||
void *irqh; /* Handle from bus_setup_intr */
|
||||
|
||||
int pci_domain;
|
||||
int pci_bus;
|
||||
int pci_slot;
|
||||
int pci_func;
|
||||
|
||||
atomic_t context_flag; /* Context swapping flag */
|
||||
int last_context; /* Last current context */
|
||||
#if __FreeBSD_version >= 400005
|
||||
|
@ -445,7 +455,7 @@ extern void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp);
|
|||
|
||||
#if __HAVE_IRQ
|
||||
/* IRQ support (drm_irq.h) */
|
||||
extern int DRM(irq_install)( drm_device_t *dev, int irq );
|
||||
extern int DRM(irq_install)(drm_device_t *dev);
|
||||
extern int DRM(irq_uninstall)( drm_device_t *dev );
|
||||
extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS );
|
||||
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
|
||||
|
@ -494,7 +504,7 @@ extern int DRM(version)( DRM_IOCTL_ARGS );
|
|||
extern int DRM(setversion)( DRM_IOCTL_ARGS );
|
||||
|
||||
/* Misc. IOCTL support (drm_ioctl.h) */
|
||||
extern int DRM(irq_busid)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(irq_by_busid)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(getunique)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(setunique)(DRM_IOCTL_ARGS);
|
||||
extern int DRM(getmap)(DRM_IOCTL_ARGS);
|
||||
|
|
|
@ -134,7 +134,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
|
||||
#if __HAVE_IRQ
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
|
||||
|
@ -477,9 +479,10 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
|
||||
dev->lock.hw_lock = NULL;
|
||||
dev->lock.lock_queue = 0;
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->last_context = 0;
|
||||
dev->if_version = 0;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
dev->buf_sigio = NULL;
|
||||
|
@ -507,7 +510,7 @@ static int DRM(takedown)( drm_device_t *dev )
|
|||
|
||||
DRIVER_PRETAKEDOWN();
|
||||
#if __HAVE_IRQ
|
||||
if (dev->irq != 0)
|
||||
if (dev->irq_enabled)
|
||||
DRM(irq_uninstall)( dev );
|
||||
#endif
|
||||
|
||||
|
@ -644,6 +647,13 @@ static int DRM(init)( device_t nbdev )
|
|||
unit = minor(dev->device.dv_unit);
|
||||
#endif
|
||||
|
||||
dev->irq = pci_get_irq(dev->device);
|
||||
/* XXX Fix domain number (alpha hoses) */
|
||||
dev->pci_domain = 0;
|
||||
dev->pci_bus = pci_get_bus(dev->device);
|
||||
dev->pci_slot = pci_get_slot(dev->device);
|
||||
dev->pci_func = pci_get_function(dev->device);
|
||||
|
||||
dev->maplist = DRM(calloc)(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
|
||||
if (dev->maplist == NULL) {
|
||||
retcode = ENOMEM;
|
||||
|
|
|
@ -32,53 +32,6 @@
|
|||
|
||||
#include "drmP.h"
|
||||
|
||||
int DRM(irq_busid)( DRM_IOCTL_ARGS )
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_irq_busid_t id;
|
||||
devclass_t pci;
|
||||
device_t bus, dev;
|
||||
device_t *kids;
|
||||
int error, i, num_kids;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( id, (drm_irq_busid_t *)data, sizeof(id) );
|
||||
|
||||
pci = devclass_find("pci");
|
||||
if (!pci)
|
||||
return ENOENT;
|
||||
bus = devclass_get_device(pci, id.busnum);
|
||||
if (!bus)
|
||||
return ENOENT;
|
||||
error = device_get_children(bus, &kids, &num_kids);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev = 0;
|
||||
for (i = 0; i < num_kids; i++) {
|
||||
dev = kids[i];
|
||||
if (pci_get_slot(dev) == id.devnum
|
||||
&& pci_get_function(dev) == id.funcnum)
|
||||
break;
|
||||
}
|
||||
|
||||
free(kids, M_TEMP);
|
||||
|
||||
if (i != num_kids)
|
||||
id.irq = pci_get_irq(dev);
|
||||
else
|
||||
id.irq = 0;
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
id.busnum, id.devnum, id.funcnum, id.irq);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, id, sizeof(id) );
|
||||
|
||||
return 0;
|
||||
#else
|
||||
/* don't support interrupt-driven drivers on Net yet */
|
||||
return ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Beginning in revision 1.1 of the DRM interface, getunique will return
|
||||
* a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
|
||||
|
@ -110,6 +63,7 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
|
|||
{
|
||||
DRM_DEVICE;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique)
|
||||
return DRM_ERR(EBUSY);
|
||||
|
@ -130,6 +84,21 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
|
|||
|
||||
dev->unique[dev->unique_len] = '\0';
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return DRM_ERR(EINVAL);
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -146,10 +115,8 @@ DRM(set_busid)(drm_device_t *dev)
|
|||
if (dev->unique == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* XXX Fix domain number (alpha hoses) */
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
|
||||
0, pci_get_bus(dev->device), pci_get_slot(dev->device),
|
||||
pci_get_function(dev->device));
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,26 +227,31 @@ int DRM(getstats)( DRM_IOCTL_ARGS )
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int DRM(setversion)(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_set_version_t sv;
|
||||
drm_set_version_t retv;
|
||||
int if_version;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
|
||||
|
||||
retv.drm_di_major = 1;
|
||||
retv.drm_di_minor = 1;
|
||||
retv.drm_di_major = DRM_IF_MAJOR;
|
||||
retv.drm_di_minor = DRM_IF_MINOR;
|
||||
retv.drm_dd_major = DRIVER_MAJOR;
|
||||
retv.drm_dd_minor = DRIVER_MINOR;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
|
||||
|
||||
if (sv.drm_di_major != -1) {
|
||||
if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_di_minor > 1)
|
||||
if (sv.drm_di_major != DRM_IF_MAJOR ||
|
||||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
|
||||
return EINVAL;
|
||||
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (sv.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
|
@ -289,12 +261,11 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
|
|||
}
|
||||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_dd_minor > DRIVER_MINOR)
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
|
||||
return EINVAL;
|
||||
#ifdef DRIVER_SETVERSION
|
||||
DRIVER_SETVERSION(dev, sv);
|
||||
DRIVER_SETVERSION(dev, &sv);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
|
|
120
bsd/drm_irq.h
120
bsd/drm_irq.h
|
@ -28,6 +28,29 @@
|
|||
*
|
||||
*/
|
||||
|
||||
int DRM(irq_by_busid)( DRM_IOCTL_ARGS )
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_irq_busid_t irq;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
|
||||
|
||||
if ((irq.busnum >> 8) != dev->pci_domain ||
|
||||
(irq.busnum & 0xff) != dev->pci_bus ||
|
||||
irq.devnum != dev->pci_slot ||
|
||||
irq.funcnum != dev->pci_func)
|
||||
return EINVAL;
|
||||
|
||||
irq.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
irq.busnum, irq.devnum, irq.funcnum, irq.irq);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
|
||||
static irqreturn_t
|
||||
DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
|
||||
|
@ -40,22 +63,22 @@ DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
|
|||
}
|
||||
#endif
|
||||
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
int DRM(irq_install)(drm_device_t *dev)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if ( irq == 0 || dev->dev_private == NULL)
|
||||
if (dev->irq == 0 || dev->dev_private == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_LOCK();
|
||||
if ( dev->irq ) {
|
||||
if (dev->irq_enabled) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
dev->irq = irq;
|
||||
dev->irq_enabled = 1;
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
|
||||
|
@ -68,31 +91,18 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
|
||||
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
|
||||
|
||||
#if __HAVE_VBL_IRQ && 0 /* disabled */
|
||||
TAILQ_INIT( &dev->vbl_sig_list );
|
||||
#endif
|
||||
|
||||
/* Before installing handler */
|
||||
DRM(driver_irq_preinstall)( dev );
|
||||
|
||||
/* Install handler */
|
||||
dev->irqrid = 0;
|
||||
#ifdef __FreeBSD__
|
||||
dev->irqrid = 0;
|
||||
dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid,
|
||||
0, ~0, 1, RF_SHAREABLE);
|
||||
if (!dev->irqr) {
|
||||
#elif defined(__NetBSD__)
|
||||
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
|
||||
#endif
|
||||
DRM_LOCK();
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
return ENOENT;
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD_version < 500000
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
|
||||
DRM(irq_handler), dev, &dev->irqh);
|
||||
|
@ -100,45 +110,56 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
|
||||
DRM(irq_handler_wrap), dev, &dev->irqh);
|
||||
#endif
|
||||
if ( retcode ) {
|
||||
if (retcode != 0)
|
||||
goto err;
|
||||
#elif defined(__NetBSD__)
|
||||
if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
|
||||
(irqreturn_t (*)(DRM_IRQ_ARGS))DRM(irq_handler), dev);
|
||||
if ( !dev->irqh ) {
|
||||
#endif
|
||||
DRM_LOCK();
|
||||
#ifdef __FreeBSD__
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
if (!dev->irqh) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* After installing handler */
|
||||
DRM(driver_irq_postinstall)( dev );
|
||||
|
||||
return 0;
|
||||
err:
|
||||
DRM_LOCK();
|
||||
dev->irq_enabled = 0;
|
||||
#ifdef ___FreeBSD__
|
||||
if (dev->irqrid != 0) {
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
|
||||
dev->irqr);
|
||||
dev->irqrid = 0;
|
||||
}
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* XXX: This function needs to be called with the device lock held. In some
|
||||
* cases it isn't, so far.
|
||||
*/
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
int irq_enabled;
|
||||
int irqrid;
|
||||
|
||||
DRM_LOCK();
|
||||
irq = dev->irq;
|
||||
irqrid = dev->irqrid;
|
||||
dev->irq = 0;
|
||||
dev->irqrid = 0;
|
||||
DRM_UNLOCK();
|
||||
|
||||
if ( !irq )
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
dev->irq_enabled = 0;
|
||||
irqrid = dev->irqrid;
|
||||
dev->irqrid = 0;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
DRM(driver_irq_uninstall)( dev );
|
||||
|
||||
|
@ -157,14 +178,21 @@ int DRM(control)( DRM_IOCTL_ARGS )
|
|||
{
|
||||
DRM_DEVICE;
|
||||
drm_control_t ctl;
|
||||
int err;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
|
||||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return DRM_ERR(EINVAL);
|
||||
return DRM(irq_install)(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
DRM_LOCK();
|
||||
err = DRM(irq_uninstall)( dev );
|
||||
DRM_UNLOCK();
|
||||
return err;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
@ -178,7 +206,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
|
|||
struct timeval now;
|
||||
int ret;
|
||||
|
||||
if (!dev->irq)
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
|
||||
|
|
|
@ -353,6 +353,7 @@ do { \
|
|||
#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
|
||||
#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
|
||||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
/**
|
||||
* Get the private SAREA mapping.
|
||||
*
|
||||
|
@ -658,6 +659,7 @@ typedef struct drm_device {
|
|||
dev_t device; /**< Device number for mknod */
|
||||
char *devname; /**< For /proc/interrupts */
|
||||
int minor; /**< Minor device number */
|
||||
int if_version; /**< Highest interface version set */
|
||||
|
||||
int blocked; /**< Blocked due to VC switch? */
|
||||
struct proc_dir_entry *root; /**< Root for this device's entries */
|
||||
|
@ -715,6 +717,7 @@ typedef struct drm_device {
|
|||
/** \name Context support */
|
||||
/*@{*/
|
||||
int irq; /**< Interrupt used by board */
|
||||
int irq_enabled; /**< True if irq handler is enabled */
|
||||
__volatile__ long context_flag; /**< Context swapping flag */
|
||||
__volatile__ long interrupt_flag; /**< Interruption handler flag */
|
||||
__volatile__ long dma_flag; /**< DMA dispatch flag */
|
||||
|
@ -754,7 +757,12 @@ typedef struct drm_device {
|
|||
#if __REALLY_HAVE_AGP
|
||||
drm_agp_head_t *agp; /**< AGP data */
|
||||
#endif
|
||||
|
||||
struct pci_dev *pdev; /**< PCI device structure */
|
||||
int pci_domain; /**< PCI bus domain number */
|
||||
int pci_bus; /**< PCI bus number */
|
||||
int pci_slot; /**< PCI slot number */
|
||||
int pci_func; /**< PCI function number */
|
||||
#ifdef __alpha__
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
|
||||
struct pci_controler *hose;
|
||||
|
@ -844,7 +852,7 @@ extern int DRM(unbind_agp)(DRM_AGP_MEM *handle);
|
|||
#endif
|
||||
|
||||
/* Misc. IOCTL support (drm_ioctl.h) */
|
||||
extern int DRM(irq_busid)(struct inode *inode, struct file *filp,
|
||||
extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int DRM(getunique)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
@ -950,7 +958,7 @@ extern int DRM(control)( struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg );
|
||||
#endif
|
||||
#if __HAVE_IRQ
|
||||
extern int DRM(irq_install)( drm_device_t *dev, int irq );
|
||||
extern int DRM(irq_install)( drm_device_t *dev );
|
||||
extern int DRM(irq_uninstall)( drm_device_t *dev );
|
||||
extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS );
|
||||
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
|
||||
|
|
|
@ -173,7 +173,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
|
||||
#if __HAVE_IRQ
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
|
||||
|
@ -334,7 +336,7 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
dev->queue_reserved = 0;
|
||||
dev->queue_slots = 0;
|
||||
dev->queuelist = NULL;
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
dev->dma_flag = 0;
|
||||
|
@ -342,6 +344,7 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
dev->last_switch = 0;
|
||||
dev->last_checked = 0;
|
||||
init_waitqueue_head( &dev->context_wait );
|
||||
dev->if_version = 0;
|
||||
|
||||
dev->ctx_start = 0;
|
||||
dev->lck_start = 0;
|
||||
|
@ -389,7 +392,7 @@ static int DRM(takedown)( drm_device_t *dev )
|
|||
|
||||
DRIVER_PRETAKEDOWN();
|
||||
#if __HAVE_IRQ
|
||||
if ( dev->irq ) DRM(irq_uninstall)( dev );
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
|
||||
#endif
|
||||
|
||||
down( &dev->struct_sem );
|
||||
|
@ -569,10 +572,18 @@ static int DRM(probe)(struct pci_dev *pdev)
|
|||
return -EPERM;
|
||||
dev->device = MKDEV(DRM_MAJOR, dev->minor );
|
||||
dev->name = DRIVER_NAME;
|
||||
|
||||
dev->pdev = pdev;
|
||||
#ifdef __alpha__
|
||||
dev->hose = pdev->sysdata;
|
||||
dev->pci_domain = dev->hose->bus->number;
|
||||
#else
|
||||
dev->pci_domain = 0;
|
||||
#endif
|
||||
dev->pci_bus = pdev->bus->number;
|
||||
dev->pci_slot = PCI_SLOT(pdev->devfn);
|
||||
dev->pci_func = PCI_FUNC(pdev->devfn);
|
||||
dev->irq = pdev->irq;
|
||||
|
||||
DRIVER_PREINIT();
|
||||
|
||||
|
|
|
@ -38,69 +38,6 @@
|
|||
|
||||
#include "linux/pci.h"
|
||||
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_irq_busid structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Finds the PCI device with the specified bus id and gets its IRQ number.
|
||||
*/
|
||||
int DRM(irq_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_irq_busid_t p;
|
||||
struct pci_dev *dev;
|
||||
|
||||
if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
#ifdef __alpha__
|
||||
{
|
||||
int domain = p.busnum >> 8;
|
||||
p.busnum &= 0xff;
|
||||
|
||||
/*
|
||||
* Find the hose the device is on (the domain number is the
|
||||
* hose index) and offset the bus by the root bus of that
|
||||
* hose.
|
||||
*/
|
||||
for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
|
||||
dev;
|
||||
dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
|
||||
struct pci_controller *hose = dev->sysdata;
|
||||
|
||||
if (hose->index == domain) {
|
||||
p.busnum += hose->bus->number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
|
||||
if (!dev) {
|
||||
DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
|
||||
p.busnum, p.devnum, p.funcnum);
|
||||
p.irq = 0;
|
||||
goto out;
|
||||
}
|
||||
if (pci_enable_device(dev) != 0) {
|
||||
DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
|
||||
p.busnum, p.devnum, p.funcnum);
|
||||
p.irq = 0;
|
||||
goto out;
|
||||
}
|
||||
p.irq = dev->irq;
|
||||
out:
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bus id.
|
||||
*
|
||||
|
@ -140,9 +77,9 @@ int DRM(getunique)(struct inode *inode, struct file *filp,
|
|||
* \param arg user argument, pointing to a drm_unique structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Copies the bus id from userspace into drm_device::unique, and searches for
|
||||
* the respective PCI device, updating drm_device::pdev. Deprecated in
|
||||
* interface version 1.1 and will return EBUSY when setversion has requested
|
||||
* Copies the bus id from userspace into drm_device::unique, and verifies that
|
||||
* it matches the device this DRM is attached to (EINVAL otherwise). Deprecated
|
||||
* in interface version 1.1 and will return EBUSY when setversion has requested
|
||||
* version 1.1 or greater.
|
||||
*/
|
||||
int DRM(setunique)(struct inode *inode, struct file *filp,
|
||||
|
@ -151,6 +88,7 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
|||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique) return -EBUSY;
|
||||
|
||||
|
@ -168,55 +106,25 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
|||
|
||||
dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
|
||||
DRM_MEM_DRIVER);
|
||||
if(!dev->devname) {
|
||||
DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
|
||||
if (!dev->devname)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
||||
|
||||
do {
|
||||
struct pci_dev *pci_dev;
|
||||
int domain, b, d, f;
|
||||
char *p;
|
||||
|
||||
for(p = dev->unique; p && *p && *p != ':'; p++);
|
||||
if (!p || !*p) break;
|
||||
b = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p != ':') break;
|
||||
d = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p != ':') break;
|
||||
f = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p) break;
|
||||
|
||||
domain = b >> 8;
|
||||
b &= 0xff;
|
||||
|
||||
#ifdef __alpha__
|
||||
/*
|
||||
* Find the hose the device is on (the domain number is the
|
||||
* hose index) and offset the bus by the root bus of that
|
||||
* hose.
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
|
||||
pci_dev;
|
||||
pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
|
||||
struct pci_controller *hose = pci_dev->sysdata;
|
||||
ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return DRM_ERR(EINVAL);
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if (hose->index == domain) {
|
||||
b += hose->bus->number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
|
||||
if (pci_dev) {
|
||||
dev->pdev = pci_dev;
|
||||
#ifdef __alpha__
|
||||
dev->hose = pci_dev->sysdata;
|
||||
#endif
|
||||
}
|
||||
} while(0);
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -232,21 +140,8 @@ DRM(set_busid)(drm_device_t *dev)
|
|||
if (dev->unique == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%s", pci_name(dev->pdev));
|
||||
#else
|
||||
{
|
||||
int domain = 0;
|
||||
#ifdef __alpha__
|
||||
struct pci_controller *hose = pci_dev->sysdata;
|
||||
|
||||
domain = hose->bus->number;
|
||||
#endif
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
domain, dev->pdev->bus->number,
|
||||
PCI_SLOT(dev->pdev->devfn), PCI_FUNC(dev->pdev->devfn));
|
||||
}
|
||||
#endif
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -398,26 +293,31 @@ int DRM(getstats)( struct inode *inode, struct file *filp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int DRM(setversion)(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_set_version_t sv;
|
||||
drm_set_version_t retv;
|
||||
int if_version;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
|
||||
|
||||
retv.drm_di_major = 1;
|
||||
retv.drm_di_minor = 1;
|
||||
retv.drm_di_major = DRM_IF_MAJOR;
|
||||
retv.drm_di_minor = DRM_IF_MINOR;
|
||||
retv.drm_dd_major = DRIVER_MAJOR;
|
||||
retv.drm_dd_minor = DRIVER_MINOR;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
|
||||
|
||||
if (sv.drm_di_major != -1) {
|
||||
if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_di_minor > 1)
|
||||
if (sv.drm_di_major != DRM_IF_MAJOR ||
|
||||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
|
||||
return EINVAL;
|
||||
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (sv.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
|
@ -427,13 +327,13 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
|
|||
}
|
||||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_dd_minor > DRIVER_MINOR)
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
|
||||
return EINVAL;
|
||||
#ifdef DRIVER_SETVERSION
|
||||
DRIVER_SETVERSION(dev, sv);
|
||||
DRIVER_SETVERSION(dev, &sv);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,44 @@
|
|||
#define DRM_IRQ_TYPE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_irq_busid structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Finds the PCI device with the specified bus id and gets its IRQ number.
|
||||
* This IOCTL is deprecated, and will now return EINVAL for any busid not equal
|
||||
* to that of the device that this DRM instance attached to.
|
||||
*/
|
||||
int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_irq_busid_t p;
|
||||
|
||||
if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
|
||||
if ((p.busnum >> 8) != dev->pci_domain ||
|
||||
(p.busnum & 0xff) != dev->pci_bus ||
|
||||
p.devnum != dev->pci_slot ||
|
||||
p.funcnum != dev->pci_func)
|
||||
return -EINVAL;
|
||||
|
||||
p.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if __HAVE_IRQ
|
||||
|
||||
/**
|
||||
|
@ -60,11 +98,11 @@
|
|||
* \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
|
||||
* before and after the installation.
|
||||
*/
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
int DRM(irq_install)( drm_device_t *dev )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( !irq )
|
||||
if ( dev->irq == 0 )
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
|
@ -75,14 +113,14 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( dev->irq ) {
|
||||
if ( dev->irq_enabled ) {
|
||||
up( &dev->struct_sem );
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->irq = irq;
|
||||
dev->irq_enabled = 1;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
|
@ -121,7 +159,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
DRM_IRQ_TYPE, dev->devname, dev );
|
||||
if ( ret < 0 ) {
|
||||
down( &dev->struct_sem );
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
return ret;
|
||||
}
|
||||
|
@ -141,21 +179,21 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
*/
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
int irq_enabled;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
irq = dev->irq;
|
||||
dev->irq = 0;
|
||||
irq_enabled = dev->irq_enabled;
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
if ( !irq )
|
||||
if ( !irq_enabled )
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
DRM(driver_irq_uninstall)( dev );
|
||||
|
||||
free_irq( irq, dev );
|
||||
free_irq( dev->irq, dev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,7 +221,10 @@ int DRM(control)( struct inode *inode, struct file *filp,
|
|||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return -EINVAL;
|
||||
return DRM(irq_install)( dev );
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
default:
|
||||
|
|
|
@ -244,7 +244,7 @@ int i810_dma_cleanup(drm_device_t *dev)
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq) DRM(irq_uninstall)(dev);
|
||||
if (dev->irq_enabled) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if (dev->dev_private) {
|
||||
|
|
|
@ -243,7 +243,7 @@ int i830_dma_cleanup(drm_device_t *dev)
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq) DRM(irq_uninstall)(dev);
|
||||
if (dev->irq_enabled) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if (dev->dev_private) {
|
||||
|
@ -1546,7 +1546,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
|
||||
switch( param.param ) {
|
||||
case I830_PARAM_IRQ_ACTIVE:
|
||||
value = dev->irq ? 1 : 0;
|
||||
value = dev->irq_enabled;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
12
linux/drmP.h
12
linux/drmP.h
|
@ -353,6 +353,7 @@ do { \
|
|||
#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
|
||||
#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
|
||||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
/**
|
||||
* Get the private SAREA mapping.
|
||||
*
|
||||
|
@ -658,6 +659,7 @@ typedef struct drm_device {
|
|||
dev_t device; /**< Device number for mknod */
|
||||
char *devname; /**< For /proc/interrupts */
|
||||
int minor; /**< Minor device number */
|
||||
int if_version; /**< Highest interface version set */
|
||||
|
||||
int blocked; /**< Blocked due to VC switch? */
|
||||
struct proc_dir_entry *root; /**< Root for this device's entries */
|
||||
|
@ -715,6 +717,7 @@ typedef struct drm_device {
|
|||
/** \name Context support */
|
||||
/*@{*/
|
||||
int irq; /**< Interrupt used by board */
|
||||
int irq_enabled; /**< True if irq handler is enabled */
|
||||
__volatile__ long context_flag; /**< Context swapping flag */
|
||||
__volatile__ long interrupt_flag; /**< Interruption handler flag */
|
||||
__volatile__ long dma_flag; /**< DMA dispatch flag */
|
||||
|
@ -754,7 +757,12 @@ typedef struct drm_device {
|
|||
#if __REALLY_HAVE_AGP
|
||||
drm_agp_head_t *agp; /**< AGP data */
|
||||
#endif
|
||||
|
||||
struct pci_dev *pdev; /**< PCI device structure */
|
||||
int pci_domain; /**< PCI bus domain number */
|
||||
int pci_bus; /**< PCI bus number */
|
||||
int pci_slot; /**< PCI slot number */
|
||||
int pci_func; /**< PCI function number */
|
||||
#ifdef __alpha__
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
|
||||
struct pci_controler *hose;
|
||||
|
@ -844,7 +852,7 @@ extern int DRM(unbind_agp)(DRM_AGP_MEM *handle);
|
|||
#endif
|
||||
|
||||
/* Misc. IOCTL support (drm_ioctl.h) */
|
||||
extern int DRM(irq_busid)(struct inode *inode, struct file *filp,
|
||||
extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int DRM(getunique)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
@ -950,7 +958,7 @@ extern int DRM(control)( struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg );
|
||||
#endif
|
||||
#if __HAVE_IRQ
|
||||
extern int DRM(irq_install)( drm_device_t *dev, int irq );
|
||||
extern int DRM(irq_install)( drm_device_t *dev );
|
||||
extern int DRM(irq_uninstall)( drm_device_t *dev );
|
||||
extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS );
|
||||
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
|
||||
|
|
|
@ -173,7 +173,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
|
||||
#if __HAVE_IRQ
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
|
||||
#endif
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
|
||||
|
@ -334,7 +336,7 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
dev->queue_reserved = 0;
|
||||
dev->queue_slots = 0;
|
||||
dev->queuelist = NULL;
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
dev->dma_flag = 0;
|
||||
|
@ -342,6 +344,7 @@ static int DRM(setup)( drm_device_t *dev )
|
|||
dev->last_switch = 0;
|
||||
dev->last_checked = 0;
|
||||
init_waitqueue_head( &dev->context_wait );
|
||||
dev->if_version = 0;
|
||||
|
||||
dev->ctx_start = 0;
|
||||
dev->lck_start = 0;
|
||||
|
@ -389,7 +392,7 @@ static int DRM(takedown)( drm_device_t *dev )
|
|||
|
||||
DRIVER_PRETAKEDOWN();
|
||||
#if __HAVE_IRQ
|
||||
if ( dev->irq ) DRM(irq_uninstall)( dev );
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
|
||||
#endif
|
||||
|
||||
down( &dev->struct_sem );
|
||||
|
@ -569,10 +572,18 @@ static int DRM(probe)(struct pci_dev *pdev)
|
|||
return -EPERM;
|
||||
dev->device = MKDEV(DRM_MAJOR, dev->minor );
|
||||
dev->name = DRIVER_NAME;
|
||||
|
||||
dev->pdev = pdev;
|
||||
#ifdef __alpha__
|
||||
dev->hose = pdev->sysdata;
|
||||
dev->pci_domain = dev->hose->bus->number;
|
||||
#else
|
||||
dev->pci_domain = 0;
|
||||
#endif
|
||||
dev->pci_bus = pdev->bus->number;
|
||||
dev->pci_slot = PCI_SLOT(pdev->devfn);
|
||||
dev->pci_func = PCI_FUNC(pdev->devfn);
|
||||
dev->irq = pdev->irq;
|
||||
|
||||
DRIVER_PREINIT();
|
||||
|
||||
|
|
|
@ -38,69 +38,6 @@
|
|||
|
||||
#include "linux/pci.h"
|
||||
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_irq_busid structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Finds the PCI device with the specified bus id and gets its IRQ number.
|
||||
*/
|
||||
int DRM(irq_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_irq_busid_t p;
|
||||
struct pci_dev *dev;
|
||||
|
||||
if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
#ifdef __alpha__
|
||||
{
|
||||
int domain = p.busnum >> 8;
|
||||
p.busnum &= 0xff;
|
||||
|
||||
/*
|
||||
* Find the hose the device is on (the domain number is the
|
||||
* hose index) and offset the bus by the root bus of that
|
||||
* hose.
|
||||
*/
|
||||
for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
|
||||
dev;
|
||||
dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
|
||||
struct pci_controller *hose = dev->sysdata;
|
||||
|
||||
if (hose->index == domain) {
|
||||
p.busnum += hose->bus->number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
|
||||
if (!dev) {
|
||||
DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
|
||||
p.busnum, p.devnum, p.funcnum);
|
||||
p.irq = 0;
|
||||
goto out;
|
||||
}
|
||||
if (pci_enable_device(dev) != 0) {
|
||||
DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
|
||||
p.busnum, p.devnum, p.funcnum);
|
||||
p.irq = 0;
|
||||
goto out;
|
||||
}
|
||||
p.irq = dev->irq;
|
||||
out:
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bus id.
|
||||
*
|
||||
|
@ -140,9 +77,9 @@ int DRM(getunique)(struct inode *inode, struct file *filp,
|
|||
* \param arg user argument, pointing to a drm_unique structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Copies the bus id from userspace into drm_device::unique, and searches for
|
||||
* the respective PCI device, updating drm_device::pdev. Deprecated in
|
||||
* interface version 1.1 and will return EBUSY when setversion has requested
|
||||
* Copies the bus id from userspace into drm_device::unique, and verifies that
|
||||
* it matches the device this DRM is attached to (EINVAL otherwise). Deprecated
|
||||
* in interface version 1.1 and will return EBUSY when setversion has requested
|
||||
* version 1.1 or greater.
|
||||
*/
|
||||
int DRM(setunique)(struct inode *inode, struct file *filp,
|
||||
|
@ -151,6 +88,7 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
|||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique) return -EBUSY;
|
||||
|
||||
|
@ -168,55 +106,25 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
|
|||
|
||||
dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
|
||||
DRM_MEM_DRIVER);
|
||||
if(!dev->devname) {
|
||||
DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
|
||||
if (!dev->devname)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
|
||||
|
||||
do {
|
||||
struct pci_dev *pci_dev;
|
||||
int domain, b, d, f;
|
||||
char *p;
|
||||
|
||||
for(p = dev->unique; p && *p && *p != ':'; p++);
|
||||
if (!p || !*p) break;
|
||||
b = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p != ':') break;
|
||||
d = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p != ':') break;
|
||||
f = (int)simple_strtoul(p+1, &p, 10);
|
||||
if (*p) break;
|
||||
|
||||
domain = b >> 8;
|
||||
b &= 0xff;
|
||||
|
||||
#ifdef __alpha__
|
||||
/*
|
||||
* Find the hose the device is on (the domain number is the
|
||||
* hose index) and offset the bus by the root bus of that
|
||||
* hose.
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
|
||||
pci_dev;
|
||||
pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
|
||||
struct pci_controller *hose = pci_dev->sysdata;
|
||||
ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return DRM_ERR(EINVAL);
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if (hose->index == domain) {
|
||||
b += hose->bus->number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
|
||||
if (pci_dev) {
|
||||
dev->pdev = pci_dev;
|
||||
#ifdef __alpha__
|
||||
dev->hose = pci_dev->sysdata;
|
||||
#endif
|
||||
}
|
||||
} while(0);
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -232,21 +140,8 @@ DRM(set_busid)(drm_device_t *dev)
|
|||
if (dev->unique == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%s", pci_name(dev->pdev));
|
||||
#else
|
||||
{
|
||||
int domain = 0;
|
||||
#ifdef __alpha__
|
||||
struct pci_controller *hose = pci_dev->sysdata;
|
||||
|
||||
domain = hose->bus->number;
|
||||
#endif
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
domain, dev->pdev->bus->number,
|
||||
PCI_SLOT(dev->pdev->devfn), PCI_FUNC(dev->pdev->devfn));
|
||||
}
|
||||
#endif
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -398,26 +293,31 @@ int DRM(getstats)( struct inode *inode, struct file *filp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int DRM(setversion)(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_set_version_t sv;
|
||||
drm_set_version_t retv;
|
||||
int if_version;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
|
||||
|
||||
retv.drm_di_major = 1;
|
||||
retv.drm_di_minor = 1;
|
||||
retv.drm_di_major = DRM_IF_MAJOR;
|
||||
retv.drm_di_minor = DRM_IF_MINOR;
|
||||
retv.drm_dd_major = DRIVER_MAJOR;
|
||||
retv.drm_dd_minor = DRIVER_MINOR;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
|
||||
|
||||
if (sv.drm_di_major != -1) {
|
||||
if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_di_minor > 1)
|
||||
if (sv.drm_di_major != DRM_IF_MAJOR ||
|
||||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
|
||||
return EINVAL;
|
||||
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (sv.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
|
@ -427,13 +327,13 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
|
|||
}
|
||||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
|
||||
return EINVAL;
|
||||
if (sv.drm_dd_minor > DRIVER_MINOR)
|
||||
if (sv.drm_dd_major != DRIVER_MAJOR ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
|
||||
return EINVAL;
|
||||
#ifdef DRIVER_SETVERSION
|
||||
DRIVER_SETVERSION(dev, sv);
|
||||
DRIVER_SETVERSION(dev, &sv);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,44 @@
|
|||
#define DRM_IRQ_TYPE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_irq_busid structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Finds the PCI device with the specified bus id and gets its IRQ number.
|
||||
* This IOCTL is deprecated, and will now return EINVAL for any busid not equal
|
||||
* to that of the device that this DRM instance attached to.
|
||||
*/
|
||||
int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_irq_busid_t p;
|
||||
|
||||
if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
|
||||
return -EFAULT;
|
||||
|
||||
if ((p.busnum >> 8) != dev->pci_domain ||
|
||||
(p.busnum & 0xff) != dev->pci_bus ||
|
||||
p.devnum != dev->pci_slot ||
|
||||
p.funcnum != dev->pci_func)
|
||||
return -EINVAL;
|
||||
|
||||
p.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if __HAVE_IRQ
|
||||
|
||||
/**
|
||||
|
@ -60,11 +98,11 @@
|
|||
* \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
|
||||
* before and after the installation.
|
||||
*/
|
||||
int DRM(irq_install)( drm_device_t *dev, int irq )
|
||||
int DRM(irq_install)( drm_device_t *dev )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ( !irq )
|
||||
if ( dev->irq == 0 )
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
|
@ -75,14 +113,14 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( dev->irq ) {
|
||||
if ( dev->irq_enabled ) {
|
||||
up( &dev->struct_sem );
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->irq = irq;
|
||||
dev->irq_enabled = 1;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
|
@ -121,7 +159,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
DRM_IRQ_TYPE, dev->devname, dev );
|
||||
if ( ret < 0 ) {
|
||||
down( &dev->struct_sem );
|
||||
dev->irq = 0;
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
return ret;
|
||||
}
|
||||
|
@ -141,21 +179,21 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
|
|||
*/
|
||||
int DRM(irq_uninstall)( drm_device_t *dev )
|
||||
{
|
||||
int irq;
|
||||
int irq_enabled;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
irq = dev->irq;
|
||||
dev->irq = 0;
|
||||
irq_enabled = dev->irq_enabled;
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
|
||||
if ( !irq )
|
||||
if ( !irq_enabled )
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
DRM(driver_irq_uninstall)( dev );
|
||||
|
||||
free_irq( irq, dev );
|
||||
free_irq( dev->irq, dev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,7 +221,10 @@ int DRM(control)( struct inode *inode, struct file *filp,
|
|||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
return DRM(irq_install)( dev, ctl.irq );
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return -EINVAL;
|
||||
return DRM(irq_install)( dev );
|
||||
case DRM_UNINST_HANDLER:
|
||||
return DRM(irq_uninstall)( dev );
|
||||
default:
|
||||
|
|
|
@ -652,7 +652,7 @@ int gamma_do_cleanup_dma( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -244,7 +244,7 @@ int i810_dma_cleanup(drm_device_t *dev)
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq) DRM(irq_uninstall)(dev);
|
||||
if (dev->irq_enabled) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if (dev->dev_private) {
|
||||
|
|
|
@ -243,7 +243,7 @@ int i830_dma_cleanup(drm_device_t *dev)
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq) DRM(irq_uninstall)(dev);
|
||||
if (dev->irq_enabled) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if (dev->dev_private) {
|
||||
|
@ -1546,7 +1546,7 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
|
||||
switch( param.param ) {
|
||||
case I830_PARAM_IRQ_ACTIVE:
|
||||
value = dev->irq ? 1 : 0;
|
||||
value = dev->irq_enabled;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -644,7 +644,7 @@ int mga_do_cleanup_dma( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -599,7 +599,7 @@ int r128_do_cleanup_cce( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -1287,7 +1287,7 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -644,7 +644,7 @@ int mga_do_cleanup_dma( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -599,7 +599,7 @@ int r128_do_cleanup_cce( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
|
@ -1287,7 +1287,7 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
|
|||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if ( dev->irq ) DRM(irq_uninstall)(dev);
|
||||
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_private ) {
|
||||
|
|
Loading…
Reference in New Issue