diff options
Diffstat (limited to 'bsd')
| -rw-r--r-- | bsd/drmP.h | 16 | ||||
| -rw-r--r-- | bsd/drm_drv.h | 16 | ||||
| -rw-r--r-- | bsd/drm_ioctl.h | 91 | ||||
| -rw-r--r-- | bsd/drm_irq.h | 120 | 
4 files changed, 131 insertions, 112 deletions
@@ -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); diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h index 0cbc1083..1083f9f9 100644 --- a/bsd/drm_drv.h +++ b/bsd/drm_drv.h @@ -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; diff --git a/bsd/drm_ioctl.h b/bsd/drm_ioctl.h index 50cf937d..0952211e 100644 --- a/bsd/drm_ioctl.h +++ b/bsd/drm_ioctl.h @@ -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) @@ -109,7 +62,8 @@ int DRM(getunique)( DRM_IOCTL_ARGS )  int DRM(setunique)( DRM_IOCTL_ARGS )  {  	DRM_DEVICE; -	drm_unique_t	 u; +	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; diff --git a/bsd/drm_irq.h b/bsd/drm_irq.h index f984118e..1de817c3 100644 --- a/bsd/drm_irq.h +++ b/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,  | 
