2012-05-08 04:24:27 +04:00
/*
* Copyright 2012 Red Hat Inc .
*
* 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 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
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) 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 "nouveau_drv.h"
# include "nouveau_dma.h"
# include "nouveau_abi16.h"
2012-07-04 17:44:54 +04:00
# include <core/ramht.h>
2012-05-08 04:24:27 +04:00
# include "nouveau_software.h"
int
nouveau_abi16_ioctl_getparam ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct drm_nouveau_getparam * getparam = data ;
switch ( getparam - > param ) {
case NOUVEAU_GETPARAM_CHIPSET_ID :
getparam - > value = dev_priv - > chipset ;
break ;
case NOUVEAU_GETPARAM_PCI_VENDOR :
getparam - > value = dev - > pci_vendor ;
break ;
case NOUVEAU_GETPARAM_PCI_DEVICE :
getparam - > value = dev - > pci_device ;
break ;
case NOUVEAU_GETPARAM_BUS_TYPE :
if ( drm_pci_device_is_agp ( dev ) )
getparam - > value = 0 ;
else
if ( ! pci_is_pcie ( dev - > pdev ) )
getparam - > value = 1 ;
else
getparam - > value = 2 ;
break ;
case NOUVEAU_GETPARAM_FB_SIZE :
getparam - > value = dev_priv - > fb_available_size ;
break ;
case NOUVEAU_GETPARAM_AGP_SIZE :
getparam - > value = dev_priv - > gart_info . aper_size ;
break ;
case NOUVEAU_GETPARAM_VM_VRAM_BASE :
getparam - > value = 0 ; /* deprecated */
break ;
case NOUVEAU_GETPARAM_PTIMER_TIME :
2012-07-11 10:08:25 +04:00
getparam - > value = nv_timer_read ( dev ) ;
2012-05-08 04:24:27 +04:00
break ;
case NOUVEAU_GETPARAM_HAS_BO_USAGE :
getparam - > value = 1 ;
break ;
case NOUVEAU_GETPARAM_HAS_PAGEFLIP :
getparam - > value = 1 ;
break ;
case NOUVEAU_GETPARAM_GRAPH_UNITS :
/* NV40 and NV50 versions are quite different, but register
* address is the same . User is supposed to know the card
* family anyway . . . */
if ( dev_priv - > chipset > = 0x40 ) {
getparam - > value = nv_rd32 ( dev , NV40_PMC_GRAPH_UNITS ) ;
break ;
}
/* FALLTHRU */
default :
NV_DEBUG ( dev , " unknown parameter %lld \n " , getparam - > param ) ;
return - EINVAL ;
}
return 0 ;
}
int
nouveau_abi16_ioctl_setparam ( ABI16_IOCTL_ARGS )
{
return - EINVAL ;
}
int
nouveau_abi16_ioctl_channel_alloc ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct drm_nouveau_channel_alloc * init = data ;
struct nouveau_channel * chan ;
int ret ;
if ( ! dev_priv - > eng [ NVOBJ_ENGINE_GR ] )
return - ENODEV ;
if ( init - > fb_ctxdma_handle = = ~ 0 | | init - > tt_ctxdma_handle = = ~ 0 )
return - EINVAL ;
ret = nouveau_channel_alloc ( dev , & chan , file_priv ,
init - > fb_ctxdma_handle ,
init - > tt_ctxdma_handle ) ;
if ( ret )
return ret ;
init - > channel = chan - > id ;
if ( nouveau_vram_pushbuf = = 0 ) {
if ( chan - > dma . ib_max )
init - > pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
NOUVEAU_GEM_DOMAIN_GART ;
else if ( chan - > pushbuf_bo - > bo . mem . mem_type = = TTM_PL_VRAM )
init - > pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM ;
else
init - > pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART ;
} else {
init - > pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM ;
}
if ( dev_priv - > card_type < NV_C0 ) {
init - > subchan [ 0 ] . handle = 0x00000000 ;
init - > subchan [ 0 ] . grclass = 0x0000 ;
init - > subchan [ 1 ] . handle = NvSw ;
init - > subchan [ 1 ] . grclass = NV_SW ;
init - > nr_subchan = 2 ;
}
/* Named memory object area */
ret = drm_gem_handle_create ( file_priv , chan - > notifier_bo - > gem ,
& init - > notifier_handle ) ;
if ( ret = = 0 )
atomic_inc ( & chan - > users ) ; /* userspace reference */
nouveau_channel_put ( & chan ) ;
return ret ;
}
int
nouveau_abi16_ioctl_channel_free ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_channel_free * req = data ;
struct nouveau_channel * chan ;
chan = nouveau_channel_get ( file_priv , req - > channel ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
list_del ( & chan - > list ) ;
atomic_dec ( & chan - > users ) ;
nouveau_channel_put ( & chan ) ;
return 0 ;
}
int
nouveau_abi16_ioctl_grobj_alloc ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_grobj_alloc * init = data ;
struct nouveau_channel * chan ;
int ret ;
if ( init - > handle = = ~ 0 )
return - EINVAL ;
/* compatibility with userspace that assumes 506e for all chipsets */
if ( init - > class = = 0x506e ) {
init - > class = nouveau_software_class ( dev ) ;
if ( init - > class = = 0x906e )
return 0 ;
} else
if ( init - > class = = 0x906e ) {
2012-09-26 06:41:19 +04:00
NV_DEBUG ( dev , " 906e not supported yet \n " ) ;
2012-05-08 04:24:27 +04:00
return - EINVAL ;
}
chan = nouveau_channel_get ( file_priv , init - > channel ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
if ( nouveau_ramht_find ( chan , init - > handle ) ) {
ret = - EEXIST ;
goto out ;
}
ret = nouveau_gpuobj_gr_new ( chan , init - > handle , init - > class ) ;
if ( ret ) {
NV_ERROR ( dev , " Error creating object: %d (%d/0x%08x) \n " ,
ret , init - > channel , init - > handle ) ;
}
out :
nouveau_channel_put ( & chan ) ;
return ret ;
}
int
nouveau_abi16_ioctl_notifierobj_alloc ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct drm_nouveau_notifierobj_alloc * na = data ;
struct nouveau_channel * chan ;
int ret ;
/* completely unnecessary for these chipsets... */
if ( unlikely ( dev_priv - > card_type > = NV_C0 ) )
return - EINVAL ;
chan = nouveau_channel_get ( file_priv , na - > channel ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
ret = nouveau_notifier_alloc ( chan , na - > handle , na - > size , 0 , 0x1000 ,
& na - > offset ) ;
nouveau_channel_put ( & chan ) ;
return ret ;
}
int
nouveau_abi16_ioctl_gpuobj_free ( ABI16_IOCTL_ARGS )
{
struct drm_nouveau_gpuobj_free * objfree = data ;
struct nouveau_channel * chan ;
int ret ;
chan = nouveau_channel_get ( file_priv , objfree - > channel ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
/* Synchronize with the user channel */
nouveau_channel_idle ( chan ) ;
ret = nouveau_ramht_remove ( chan , objfree - > handle ) ;
nouveau_channel_put ( & chan ) ;
return ret ;
}