2005-04-17 02:20:36 +04:00
/**
2005-09-25 08:28:13 +04:00
* \ file drm_drv . c
2005-04-17 02:20:36 +04:00
* Generic driver template
*
* \ author Rickard E . ( Rik ) Faith < faith @ valinux . com >
* \ author Gareth Hughes < gareth @ valinux . com >
*
* To use this template , you must at least define the following ( samples
* given for the MGA driver ) :
*
* \ code
* # define DRIVER_AUTHOR " VA Linux Systems, Inc. "
*
* # define DRIVER_NAME " mga "
* # define DRIVER_DESC " Matrox G200/G400 "
* # define DRIVER_DATE " 20001127 "
*
* # define drm_x mga_ # # x
* \ endcode
*/
/*
* Created : Thu Nov 23 03 : 10 : 50 2000 by gareth @ valinux . com
*
* Copyright 1999 , 2000 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
* All Rights Reserved .
*
* 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 :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* 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
* VA LINUX SYSTEMS AND / OR ITS SUPPLIERS 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 .
*/
# include "drmP.h"
# include "drm_core.h"
2007-09-03 06:06:45 +04:00
static int drm_version ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
2005-07-07 15:03:38 +04:00
2005-04-17 02:20:36 +04:00
/** Ioctl table */
2007-09-03 06:06:45 +04:00
static struct drm_ioctl_desc drm_ioctls [ ] = {
DRM_IOCTL_DEF ( DRM_IOCTL_VERSION , drm_version , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_UNIQUE , drm_getunique , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_MAGIC , drm_getmagic , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_IRQ_BUSID , drm_irq_by_busid , DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_MAP , drm_getmap , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_CLIENT , drm_getclient , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_STATS , drm_getstats , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SET_VERSION , drm_setversion , DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SET_UNIQUE , drm_setunique , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_BLOCK , drm_noop , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_UNBLOCK , drm_noop , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AUTH_MAGIC , drm_authmagic , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_ADD_MAP , drm_addmap_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_RM_MAP , drm_rmmap_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SET_SAREA_CTX , drm_setsareactx , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_SAREA_CTX , drm_getsareactx , DRM_AUTH ) ,
2008-11-28 07:22:24 +03:00
DRM_IOCTL_DEF ( DRM_IOCTL_SET_MASTER , drm_setmaster_ioctl , DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_DROP_MASTER , drm_dropmaster_ioctl , DRM_ROOT_ONLY ) ,
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_ADD_CTX , drm_addctx , DRM_AUTH | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_RM_CTX , drm_rmctx , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MOD_CTX , drm_modctx , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GET_CTX , drm_getctx , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SWITCH_CTX , drm_switchctx , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_NEW_CTX , drm_newctx , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_RES_CTX , drm_resctx , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_ADD_DRAW , drm_adddraw , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_RM_DRAW , drm_rmdraw , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_LOCK , drm_lock , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_UNLOCK , drm_unlock , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_FINISH , drm_noop , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_ADD_BUFS , drm_addbufs , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MARK_BUFS , drm_markbufs , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_INFO_BUFS , drm_infobufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MAP_BUFS , drm_mapbufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_FREE_BUFS , drm_freebufs , DRM_AUTH ) ,
2005-04-17 02:20:36 +04:00
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_DMA , NULL , DRM_AUTH ) ,
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_CONTROL , drm_control , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2005-04-17 02:20:36 +04:00
# if __OS_HAS_AGP
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_ACQUIRE , drm_agp_acquire_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_RELEASE , drm_agp_release_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_ENABLE , drm_agp_enable_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_INFO , drm_agp_info_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_ALLOC , drm_agp_alloc_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_FREE , drm_agp_free_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_BIND , drm_agp_bind_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_AGP_UNBIND , drm_agp_unbind_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2005-04-17 02:20:36 +04:00
# endif
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_SG_ALLOC , drm_sg_alloc_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_SG_FREE , drm_sg_free , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_WAIT_VBLANK , drm_wait_vblank , 0 ) ,
2006-10-24 17:04:19 +04:00
2008-09-30 23:14:26 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_MODESET_CTL , drm_modeset_ctl , 0 ) ,
2007-09-03 06:06:45 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_UPDATE_DRAW , drm_update_drawable_info , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2008-07-30 23:06:12 +04:00
DRM_IOCTL_DEF ( DRM_IOCTL_GEM_CLOSE , drm_gem_close_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GEM_FLINK , drm_gem_flink_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_GEM_OPEN , drm_gem_open_ioctl , DRM_AUTH ) ,
2008-11-08 01:05:41 +03:00
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETRESOURCES , drm_mode_getresources , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETCRTC , drm_mode_getcrtc , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETCONNECTOR , drm_mode_getconnector , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_SETCRTC , drm_mode_setcrtc , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_CURSOR , drm_mode_cursor_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_ADDFB , drm_mode_addfb , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_RMFB , drm_mode_rmfb , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETFB , drm_mode_getfb , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_SETPROPERTY , drm_mode_connector_property_set_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETPROPBLOB , drm_mode_getblob_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_ATTACHMODE , drm_mode_attachmode_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_DETACHMODE , drm_mode_detachmode_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETPROPERTY , drm_mode_getproperty_ioctl , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_REPLACEFB , drm_mode_replacefb , DRM_MASTER | DRM_ROOT_ONLY | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETENCODER , drm_mode_getencoder , DRM_MASTER | DRM_CONTROL_ALLOW ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_GETGAMMA , drm_mode_gamma_get_ioctl , DRM_MASTER ) ,
DRM_IOCTL_DEF ( DRM_IOCTL_MODE_SETGAMMA , drm_mode_gamma_set_ioctl , DRM_MASTER ) ,
2005-04-17 02:20:36 +04:00
} ;
2007-05-08 09:28:15 +04:00
# define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
2005-04-17 02:20:36 +04:00
/**
* Take down the DRM device .
*
* \ param dev DRM device structure .
*
* Frees every resource in \ p dev .
*
2005-07-10 10:58:40 +04:00
* \ sa drm_device
2005-04-17 02:20:36 +04:00
*/
2007-07-11 09:53:27 +04:00
int drm_lastclose ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:21:47 +04:00
struct drm_vma_entry * vma , * vma_temp ;
2005-04-17 02:20:36 +04:00
int i ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2005-11-10 14:16:34 +03:00
if ( dev - > driver - > lastclose )
dev - > driver - > lastclose ( dev ) ;
DRM_DEBUG ( " driver lastclose completed \n " ) ;
2005-04-17 02:20:36 +04:00
2008-11-08 01:05:41 +03:00
if ( dev - > irq_enabled & & ! drm_core_check_feature ( dev , DRIVER_MODESET ) )
2005-09-25 08:28:13 +04:00
drm_irq_uninstall ( dev ) ;
2005-04-17 02:20:36 +04:00
2006-02-02 11:37:46 +03:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-07-17 04:55:47 +04:00
/* Free drawable information memory */
drm_drawable_free_all ( dev ) ;
2005-09-25 08:28:13 +04:00
del_timer ( & dev - > timer ) ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
/* Clear AGP information */
2008-11-08 01:05:41 +03:00
if ( drm_core_has_AGP ( dev ) & & dev - > agp & &
! drm_core_check_feature ( dev , DRIVER_MODESET ) ) {
2007-07-11 10:53:40 +04:00
struct drm_agp_mem * entry , * tempe ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called . */
2007-05-25 23:01:51 +04:00
list_for_each_entry_safe ( entry , tempe , & dev - > agp - > memory , head ) {
2005-09-25 08:28:13 +04:00
if ( entry - > bound )
drm_unbind_agp ( entry - > memory ) ;
drm_free_agp ( entry - > memory , entry - > pages ) ;
drm_free ( entry , sizeof ( * entry ) , DRM_MEM_AGPLISTS ) ;
2005-04-17 02:20:36 +04:00
}
2007-05-25 23:01:51 +04:00
INIT_LIST_HEAD ( & dev - > agp - > memory ) ;
2005-04-17 02:20:36 +04:00
2005-07-10 10:56:52 +04:00
if ( dev - > agp - > acquired )
2005-09-25 08:28:13 +04:00
drm_agp_release ( dev ) ;
2005-04-17 02:20:36 +04:00
dev - > agp - > acquired = 0 ;
2005-09-25 08:28:13 +04:00
dev - > agp - > enabled = 0 ;
2005-04-17 02:20:36 +04:00
}
2008-11-08 01:05:41 +03:00
if ( drm_core_check_feature ( dev , DRIVER_SG ) & & dev - > sg & &
! drm_core_check_feature ( dev , DRIVER_MODESET ) ) {
2005-07-10 13:27:04 +04:00
drm_sg_cleanup ( dev - > sg ) ;
dev - > sg = NULL ;
}
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
/* Clear vma list (only built for debugging) */
2007-05-25 23:01:51 +04:00
list_for_each_entry_safe ( vma , vma_temp , & dev - > vmalist , head ) {
list_del ( & vma - > head ) ;
drm_free ( vma , sizeof ( * vma ) , DRM_MEM_VMAS ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
if ( drm_core_check_feature ( dev , DRIVER_DMA_QUEUE ) & & dev - > queuelist ) {
for ( i = 0 ; i < dev - > queue_count ; i + + ) {
if ( dev - > queuelist [ i ] ) {
drm_free ( dev - > queuelist [ i ] ,
sizeof ( * dev - > queuelist [ 0 ] ) ,
DRM_MEM_QUEUES ) ;
2005-04-17 02:20:36 +04:00
dev - > queuelist [ i ] = NULL ;
}
}
2005-09-25 08:28:13 +04:00
drm_free ( dev - > queuelist ,
dev - > queue_slots * sizeof ( * dev - > queuelist ) ,
DRM_MEM_QUEUES ) ;
2005-04-17 02:20:36 +04:00
dev - > queuelist = NULL ;
}
dev - > queue_count = 0 ;
2008-11-08 01:05:41 +03:00
if ( drm_core_check_feature ( dev , DRIVER_HAVE_DMA ) & &
! drm_core_check_feature ( dev , DRIVER_MODESET ) )
2005-09-25 08:28:13 +04:00
drm_dma_takedown ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-11-05 21:31:53 +03:00
dev - > dev_mapping = NULL ;
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
2005-11-10 14:16:34 +03:00
DRM_DEBUG ( " lastclose completed \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* Module initialization . Called via init_module at module load time , or via
* linux / init / main . c ( this is not currently supported ) .
*
* \ return zero on success or a negative number on failure .
*
* Initializes an array of drm_device structures , and attempts to
* initialize all available devices , using consecutive minors , registering the
* stubs and initializing the AGP device .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* Expands the \ c DRIVER_PREINIT and \ c DRIVER_POST_INIT macros before and
* after the initialization for driver customization .
*/
2005-09-25 08:28:13 +04:00
int drm_init ( struct drm_driver * driver )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * pdev = NULL ;
struct pci_device_id * pid ;
int i ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2008-11-28 06:43:47 +03:00
INIT_LIST_HEAD ( & driver - > device_list ) ;
2005-09-25 08:28:13 +04:00
for ( i = 0 ; driver - > pci_driver . id_table [ i ] . vendor ! = 0 ; i + + ) {
2005-04-17 02:20:36 +04:00
pid = ( struct pci_device_id * ) & driver - > pci_driver . id_table [ i ] ;
2005-09-25 08:28:13 +04:00
2008-11-11 11:02:12 +03:00
/* Loop around setting up a DRM device for each PCI device
* matching our ID and device class . If we had the internal
* function that pci_get_subsys and pci_get_class used , we ' d
* be able to just pass pid in instead of doing a two - stage
* thing .
*/
2005-09-25 08:28:13 +04:00
pdev = NULL ;
while ( ( pdev =
pci_get_subsys ( pid - > vendor , pid - > device , pid - > subvendor ,
pid - > subdevice , pdev ) ) ! = NULL ) {
2008-11-11 11:02:12 +03:00
if ( ( pdev - > class & pid - > class_mask ) ! = pid - > class )
continue ;
2005-04-17 02:20:36 +04:00
/* stealth mode requires a manual probe */
pci_dev_get ( pdev ) ;
drm_get_dev ( pdev , pid , driver ) ;
}
}
return 0 ;
}
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( drm_init ) ;
/**
* Called via cleanup_module ( ) at module unload time .
*
2005-11-10 14:16:34 +03:00
* Cleans up all DRM device , calling drm_lastclose ( ) .
2005-09-25 08:28:13 +04:00
*
2005-07-10 10:58:40 +04:00
* \ sa drm_init
2005-04-17 02:20:36 +04:00
*/
2007-07-11 09:53:27 +04:00
static void drm_cleanup ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2008-11-05 21:31:53 +03:00
struct drm_driver * driver = dev - > driver ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
if ( ! dev ) {
DRM_ERROR ( " cleanup called no dev \n " ) ;
return ;
}
2008-11-18 20:30:25 +03:00
drm_vblank_cleanup ( dev ) ;
2005-11-10 14:16:34 +03:00
drm_lastclose ( dev ) ;
2005-04-17 02:20:36 +04:00
if ( drm_core_has_MTRR ( dev ) & & drm_core_has_AGP ( dev ) & &
dev - > agp & & dev - > agp - > agp_mtrr > = 0 ) {
int retval ;
2005-09-25 08:28:13 +04:00
retval = mtrr_del ( dev - > agp - > agp_mtrr ,
dev - > agp - > agp_info . aper_base ,
dev - > agp - > agp_info . aper_size * 1024 * 1024 ) ;
DRM_DEBUG ( " mtrr_del=%d \n " , retval ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
if ( drm_core_has_AGP ( dev ) & & dev - > agp ) {
drm_free ( dev - > agp , sizeof ( * dev - > agp ) , DRM_MEM_AGPLISTS ) ;
2005-04-17 02:20:36 +04:00
dev - > agp = NULL ;
}
2005-11-10 14:16:34 +03:00
if ( dev - > driver - > unload )
dev - > driver - > unload ( dev ) ;
2005-09-25 08:28:13 +04:00
2007-12-17 02:41:56 +03:00
drm_ht_remove ( & dev - > map_hash ) ;
drm_ctxbitmap_cleanup ( dev ) ;
2008-11-05 21:31:53 +03:00
2008-11-08 01:05:41 +03:00
if ( drm_core_check_feature ( dev , DRIVER_MODESET ) )
drm_put_minor ( & dev - > control ) ;
2008-11-05 21:31:53 +03:00
if ( driver - > driver_features & DRIVER_GEM )
drm_gem_destroy ( dev ) ;
2007-12-17 02:41:56 +03:00
2008-04-21 10:47:32 +04:00
drm_put_minor ( & dev - > primary ) ;
2005-09-25 08:28:13 +04:00
if ( drm_put_dev ( dev ) )
DRM_ERROR ( " Cannot unload module \n " ) ;
2005-04-17 02:20:36 +04:00
}
2008-04-21 10:47:32 +04:00
void drm_exit ( struct drm_driver * driver )
{
2008-11-28 06:43:47 +03:00
struct drm_device * dev , * tmp ;
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " \n " ) ;
2005-04-17 02:20:36 +04:00
2008-11-28 06:43:47 +03:00
list_for_each_entry_safe ( dev , tmp , & driver - > device_list , driver_item )
drm_cleanup ( dev ) ;
2008-04-21 10:47:32 +04:00
2005-09-25 08:28:13 +04:00
DRM_INFO ( " Module unloaded \n " ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( drm_exit ) ;
/** File operations structure */
2007-02-12 11:55:32 +03:00
static const struct file_operations drm_stub_fops = {
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
2005-09-25 08:28:13 +04:00
. open = drm_stub_open
2005-04-17 02:20:36 +04:00
} ;
static int __init drm_core_init ( void )
{
int ret = - ENOMEM ;
2005-09-25 08:28:13 +04:00
2008-04-21 10:47:32 +04:00
idr_init ( & drm_minors_idr ) ;
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
if ( register_chrdev ( DRM_MAJOR , " drm " , & drm_stub_fops ) )
goto err_p1 ;
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
drm_class = drm_sysfs_create ( THIS_MODULE , " drm " ) ;
if ( IS_ERR ( drm_class ) ) {
2005-09-25 08:28:13 +04:00
printk ( KERN_ERR " DRM: Error creating drm class. \n " ) ;
2005-04-17 02:20:36 +04:00
ret = PTR_ERR ( drm_class ) ;
goto err_p2 ;
}
2005-09-29 01:32:57 +04:00
drm_proc_root = proc_mkdir ( " dri " , NULL ) ;
2005-04-17 02:20:36 +04:00
if ( ! drm_proc_root ) {
DRM_ERROR ( " Cannot create /proc/dri \n " ) ;
ret = - 1 ;
goto err_p3 ;
}
2005-09-25 08:28:13 +04:00
2007-11-22 11:43:46 +03:00
drm_mem_init ( ) ;
2005-09-25 08:28:13 +04:00
DRM_INFO ( " Initialized %s %d.%d.%d %s \n " ,
CORE_NAME , CORE_MAJOR , CORE_MINOR , CORE_PATCHLEVEL , CORE_DATE ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-11-22 07:02:38 +03:00
err_p3 :
drm_sysfs_destroy ( ) ;
err_p2 :
2005-04-17 02:20:36 +04:00
unregister_chrdev ( DRM_MAJOR , " drm " ) ;
2008-04-21 10:47:32 +04:00
idr_destroy ( & drm_minors_idr ) ;
2007-11-22 07:02:38 +03:00
err_p1 :
2005-04-17 02:20:36 +04:00
return ret ;
}
2005-09-25 08:28:13 +04:00
static void __exit drm_core_exit ( void )
2005-04-17 02:20:36 +04:00
{
remove_proc_entry ( " dri " , NULL ) ;
2007-11-22 07:02:38 +03:00
drm_sysfs_destroy ( ) ;
2005-04-17 02:20:36 +04:00
unregister_chrdev ( DRM_MAJOR , " drm " ) ;
2008-04-21 10:47:32 +04:00
idr_destroy ( & drm_minors_idr ) ;
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
module_init ( drm_core_init ) ;
module_exit ( drm_core_exit ) ;
2005-04-17 02:20:36 +04:00
/**
* Get version information
*
* \ param inode device inode .
* \ param filp file pointer .
* \ param cmd command .
* \ param arg user argument , pointing to a drm_version structure .
* \ return zero on success or negative number on failure .
*
* Fills in the version information in \ p arg .
*/
2007-09-03 06:06:45 +04:00
static int drm_version ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_version * version = data ;
2005-11-10 14:16:34 +03:00
int len ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
version - > version_major = dev - > driver - > major ;
version - > version_minor = dev - > driver - > minor ;
version - > version_patchlevel = dev - > driver - > patchlevel ;
DRM_COPY ( version - > name , dev - > driver - > name ) ;
DRM_COPY ( version - > date , dev - > driver - > date ) ;
DRM_COPY ( version - > desc , dev - > driver - > desc ) ;
2005-09-25 08:28:13 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-09-25 08:28:13 +04:00
/**
2005-04-17 02:20:36 +04:00
* Called whenever a process performs an ioctl on / dev / drm .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg user argument .
* \ return zero on success or negative number on failure .
*
* Looks up the ioctl function in the : : ioctls table , checking for root
* previleges if so required , and dispatches to the respective function .
*/
2005-09-25 08:28:13 +04:00
int drm_ioctl ( struct inode * inode , struct file * filp ,
unsigned int cmd , unsigned long arg )
2005-04-17 02:20:36 +04:00
{
2007-08-25 14:23:09 +04:00
struct drm_file * file_priv = filp - > private_data ;
2008-04-21 10:47:32 +04:00
struct drm_device * dev = file_priv - > minor - > dev ;
2007-09-03 06:06:45 +04:00
struct drm_ioctl_desc * ioctl ;
2005-04-17 02:20:36 +04:00
drm_ioctl_t * func ;
unsigned int nr = DRM_IOCTL_NR ( cmd ) ;
int retcode = - EINVAL ;
2007-09-03 06:06:45 +04:00
char * kdata = NULL ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
atomic_inc ( & dev - > ioctl_count ) ;
atomic_inc ( & dev - > counts [ _DRM_STAT_IOCTLS ] ) ;
2007-08-25 14:23:09 +04:00
+ + file_priv - > ioctl_count ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d \n " ,
2007-10-19 10:40:40 +04:00
task_pid_nr ( current ) , cmd , nr ,
2008-04-21 10:47:32 +04:00
( long ) old_encode_dev ( file_priv - > minor - > device ) ,
2007-08-25 14:23:09 +04:00
file_priv - > authenticated ) ;
2005-09-25 08:28:13 +04:00
2007-05-08 09:28:15 +04:00
if ( ( nr > = DRM_CORE_IOCTL_COUNT ) & &
2007-03-19 00:52:17 +03:00
( ( nr < DRM_COMMAND_BASE ) | | ( nr > = DRM_COMMAND_END ) ) )
goto err_i1 ;
2007-05-08 09:28:15 +04:00
if ( ( nr > = DRM_COMMAND_BASE ) & & ( nr < DRM_COMMAND_END ) & &
( nr < DRM_COMMAND_BASE + dev - > driver - > num_ioctls ) )
2005-04-17 02:20:36 +04:00
ioctl = & dev - > driver - > ioctls [ nr - DRM_COMMAND_BASE ] ;
2008-06-20 09:42:38 +04:00
else if ( ( nr > = DRM_COMMAND_END ) | | ( nr < DRM_COMMAND_BASE ) ) {
2007-03-19 00:52:17 +03:00
ioctl = & drm_ioctls [ nr ] ;
2008-06-20 09:42:38 +04:00
cmd = ioctl - > cmd ;
} else
2005-04-17 02:20:36 +04:00
goto err_i1 ;
2005-09-25 08:28:13 +04:00
2008-06-13 09:04:40 +04:00
/* Do not trust userspace, use our own definition */
2005-04-17 02:20:36 +04:00
func = ioctl - > func ;
/* is there a local override? */
if ( ( nr = = DRM_IOCTL_NR ( DRM_IOCTL_DMA ) ) & & dev - > driver - > dma_ioctl )
func = dev - > driver - > dma_ioctl ;
2005-09-25 08:28:13 +04:00
if ( ! func ) {
DRM_DEBUG ( " no function \n " ) ;
2005-04-17 02:20:36 +04:00
retcode = - EINVAL ;
2006-01-02 05:54:04 +03:00
} else if ( ( ( ioctl - > flags & DRM_ROOT_ONLY ) & & ! capable ( CAP_SYS_ADMIN ) ) | |
2007-08-25 14:23:09 +04:00
( ( ioctl - > flags & DRM_AUTH ) & & ! file_priv - > authenticated ) | |
2008-12-19 04:00:46 +03:00
( ( ioctl - > flags & DRM_MASTER ) & & ! file_priv - > is_master ) ) {
2005-04-17 02:20:36 +04:00
retcode = - EACCES ;
} else {
2007-09-03 06:06:45 +04:00
if ( cmd & ( IOC_IN | IOC_OUT ) ) {
kdata = kmalloc ( _IOC_SIZE ( cmd ) , GFP_KERNEL ) ;
2008-02-07 07:51:32 +03:00
if ( ! kdata ) {
retcode = - ENOMEM ;
goto err_i1 ;
}
2007-09-03 06:06:45 +04:00
}
if ( cmd & IOC_IN ) {
if ( copy_from_user ( kdata , ( void __user * ) arg ,
_IOC_SIZE ( cmd ) ) ! = 0 ) {
2008-02-07 07:51:32 +03:00
retcode = - EFAULT ;
2007-09-03 06:06:45 +04:00
goto err_i1 ;
}
}
retcode = func ( dev , kdata , file_priv ) ;
2008-02-07 07:51:32 +03:00
if ( ( retcode = = 0 ) & & ( cmd & IOC_OUT ) ) {
2007-09-03 06:06:45 +04:00
if ( copy_to_user ( ( void __user * ) arg , kdata ,
_IOC_SIZE ( cmd ) ) ! = 0 )
2008-02-07 07:51:32 +03:00
retcode = - EFAULT ;
2007-09-03 06:06:45 +04:00
}
2005-04-17 02:20:36 +04:00
}
2005-09-25 08:28:13 +04:00
err_i1 :
2007-09-03 06:06:45 +04:00
if ( kdata )
kfree ( kdata ) ;
2005-09-25 08:28:13 +04:00
atomic_dec ( & dev - > ioctl_count ) ;
if ( retcode )
DRM_DEBUG ( " ret = %x \n " , retcode ) ;
2005-04-17 02:20:36 +04:00
return retcode ;
}
2005-09-25 08:28:13 +04:00
EXPORT_SYMBOL ( drm_ioctl ) ;
2007-05-25 23:04:51 +04:00
drm_local_map_t * drm_getsarea ( struct drm_device * dev )
{
2007-07-11 10:53:40 +04:00
struct drm_map_list * entry ;
2007-05-25 23:04:51 +04:00
2007-05-28 13:41:35 +04:00
list_for_each_entry ( entry , & dev - > maplist , head ) {
2007-05-25 23:04:51 +04:00
if ( entry - > map & & entry - > map - > type = = _DRM_SHM & &
( entry - > map - > flags & _DRM_CONTAINS_LOCK ) ) {
return entry - > map ;
}
}
return NULL ;
}
EXPORT_SYMBOL ( drm_getsarea ) ;