2005-04-16 15:20:36 -07:00
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
*/
2006-01-02 20:14:23 +11:00
/*
2005-04-16 15:20:36 -07:00
* Copyright 2003 Tungsten Graphics , Inc . , Cedar Park , Texas .
* All Rights Reserved .
2005-06-23 22:46:46 +10:00
*
* 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 , sub license , 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 NON - INFRINGEMENT .
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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 .
*
2006-01-02 20:14:23 +11:00
*/
2005-04-16 15:20:36 -07:00
# include "drmP.h"
# include "drm.h"
# include "i915_drm.h"
# include "i915_drv.h"
/* Really want an OS-independent resettable timer. Would like to have
* this loop run for ( eg ) 3 sec , but have the timer reset every time
* the head pointer changes , so that EBUSY only happens if the ring
* actually stalls for ( eg ) 3 seconds .
*/
2007-07-11 15:53:27 +10:00
int i915_wait_ring ( struct drm_device * dev , int n , const char * caller )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv = dev - > primary - > master - > driver_priv ;
2005-04-16 15:20:36 -07:00
drm_i915_ring_buffer_t * ring = & ( dev_priv - > ring ) ;
2008-07-30 12:21:20 -07:00
u32 acthd_reg = IS_I965G ( dev ) ? ACTHD_I965 : ACTHD ;
u32 last_acthd = I915_READ ( acthd_reg ) ;
u32 acthd ;
2008-07-29 11:54:06 -07:00
u32 last_head = I915_READ ( PRB0_HEAD ) & HEAD_ADDR ;
2005-04-16 15:20:36 -07:00
int i ;
2008-07-30 12:21:20 -07:00
for ( i = 0 ; i < 100000 ; i + + ) {
2008-07-29 11:54:06 -07:00
ring - > head = I915_READ ( PRB0_HEAD ) & HEAD_ADDR ;
2008-07-30 12:21:20 -07:00
acthd = I915_READ ( acthd_reg ) ;
2005-04-16 15:20:36 -07:00
ring - > space = ring - > head - ( ring - > tail + 8 ) ;
if ( ring - > space < 0 )
ring - > space + = ring - > Size ;
if ( ring - > space > = n )
return 0 ;
2008-11-28 14:22:24 +10:00
if ( master_priv - > sarea_priv )
master_priv - > sarea_priv - > perf_boxes | = I915_BOX_WAIT ;
2005-04-16 15:20:36 -07:00
if ( ring - > head ! = last_head )
i = 0 ;
2008-07-30 12:21:20 -07:00
if ( acthd ! = last_acthd )
i = 0 ;
2005-04-16 15:20:36 -07:00
last_head = ring - > head ;
2008-07-30 12:21:20 -07:00
last_acthd = acthd ;
msleep_interruptible ( 10 ) ;
2005-04-16 15:20:36 -07:00
}
2007-08-25 19:22:43 +10:00
return - EBUSY ;
2005-04-16 15:20:36 -07:00
}
2008-07-30 13:03:43 -07:00
/**
* Sets up the hardware status page for devices that need a physical address
* in the register .
*/
2008-10-02 12:24:47 -07:00
static int i915_init_phys_hws ( struct drm_device * dev )
2008-07-30 13:03:43 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
/* Program Hardware Status Page */
dev_priv - > status_page_dmah =
drm_pci_alloc ( dev , PAGE_SIZE , PAGE_SIZE , 0xffffffff ) ;
if ( ! dev_priv - > status_page_dmah ) {
DRM_ERROR ( " Can not allocate hardware status page \n " ) ;
return - ENOMEM ;
}
dev_priv - > hw_status_page = dev_priv - > status_page_dmah - > vaddr ;
dev_priv - > dma_status_page = dev_priv - > status_page_dmah - > busaddr ;
memset ( dev_priv - > hw_status_page , 0 , PAGE_SIZE ) ;
I915_WRITE ( HWS_PGA , dev_priv - > dma_status_page ) ;
DRM_DEBUG ( " Enabled hardware status page \n " ) ;
return 0 ;
}
/**
* Frees the hardware status page , whether it ' s a physical address or a virtual
* address set up by the X Server .
*/
2008-10-02 12:24:47 -07:00
static void i915_free_hws ( struct drm_device * dev )
2008-07-30 13:03:43 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
if ( dev_priv - > status_page_dmah ) {
drm_pci_free ( dev , dev_priv - > status_page_dmah ) ;
dev_priv - > status_page_dmah = NULL ;
}
if ( dev_priv - > status_gfx_addr ) {
dev_priv - > status_gfx_addr = 0 ;
drm_core_ioremapfree ( & dev_priv - > hws_map , dev ) ;
}
/* Need to rewrite hardware status page */
I915_WRITE ( HWS_PGA , 0x1ffff000 ) ;
}
2007-07-11 15:53:27 +10:00
void i915_kernel_lost_context ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv ;
2005-04-16 15:20:36 -07:00
drm_i915_ring_buffer_t * ring = & ( dev_priv - > ring ) ;
2008-07-29 11:54:06 -07:00
ring - > head = I915_READ ( PRB0_HEAD ) & HEAD_ADDR ;
ring - > tail = I915_READ ( PRB0_TAIL ) & TAIL_ADDR ;
2005-04-16 15:20:36 -07:00
ring - > space = ring - > head - ( ring - > tail + 8 ) ;
if ( ring - > space < 0 )
ring - > space + = ring - > Size ;
2008-11-28 14:22:24 +10:00
if ( ! dev - > primary - > master )
return ;
master_priv = dev - > primary - > master - > driver_priv ;
if ( ring - > head = = ring - > tail & & master_priv - > sarea_priv )
master_priv - > sarea_priv - > perf_boxes | = I915_BOX_RING_EMPTY ;
2005-04-16 15:20:36 -07:00
}
2007-07-11 15:53:27 +10:00
static int i915_dma_cleanup ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
2007-11-22 14:14:14 +10:00
drm_i915_private_t * dev_priv = dev - > dev_private ;
2005-04-16 15:20:36 -07:00
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed , it ' s too late .
*/
2008-07-29 12:10:39 -07:00
if ( dev - > irq_enabled )
2005-09-25 14:28:13 +10:00
drm_irq_uninstall ( dev ) ;
2005-04-16 15:20:36 -07:00
2007-11-22 14:14:14 +10:00
if ( dev_priv - > ring . virtual_start ) {
drm_core_ioremapfree ( & dev_priv - > ring . map , dev ) ;
2008-10-02 12:24:47 -07:00
dev_priv - > ring . virtual_start = NULL ;
dev_priv - > ring . map . handle = NULL ;
2007-11-22 14:14:14 +10:00
dev_priv - > ring . map . size = 0 ;
}
2007-06-10 15:58:19 +10:00
2008-07-30 13:03:43 -07:00
/* Clear the HWS virtual address at teardown */
if ( I915_NEED_GFX_HWS ( dev ) )
i915_free_hws ( dev ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-11-22 14:14:14 +10:00
static int i915_initialize ( struct drm_device * dev , drm_i915_init_t * init )
2005-04-16 15:20:36 -07:00
{
2007-11-22 14:14:14 +10:00
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv = dev - > primary - > master - > driver_priv ;
2005-04-16 15:20:36 -07:00
2008-07-30 12:06:12 -07:00
if ( init - > ring_size ! = 0 ) {
if ( dev_priv - > ring . ring_obj ! = NULL ) {
i915_dma_cleanup ( dev ) ;
DRM_ERROR ( " Client tried to initialize ringbuffer in "
" GEM mode \n " ) ;
return - EINVAL ;
}
2005-04-16 15:20:36 -07:00
2008-07-30 12:06:12 -07:00
dev_priv - > ring . Size = init - > ring_size ;
dev_priv - > ring . tail_mask = dev_priv - > ring . Size - 1 ;
2005-04-16 15:20:36 -07:00
2008-07-30 12:06:12 -07:00
dev_priv - > ring . map . offset = init - > ring_start ;
dev_priv - > ring . map . size = init - > ring_size ;
dev_priv - > ring . map . type = 0 ;
dev_priv - > ring . map . flags = 0 ;
dev_priv - > ring . map . mtrr = 0 ;
2005-04-16 15:20:36 -07:00
2008-07-30 12:06:12 -07:00
drm_core_ioremap ( & dev_priv - > ring . map , dev ) ;
if ( dev_priv - > ring . map . handle = = NULL ) {
i915_dma_cleanup ( dev ) ;
DRM_ERROR ( " can not ioremap virtual address for "
" ring buffer \n " ) ;
return - ENOMEM ;
}
2005-04-16 15:20:36 -07:00
}
dev_priv - > ring . virtual_start = dev_priv - > ring . map . handle ;
2006-10-24 23:37:43 +10:00
dev_priv - > cpp = init - > cpp ;
2005-04-16 15:20:36 -07:00
dev_priv - > back_offset = init - > back_offset ;
dev_priv - > front_offset = init - > front_offset ;
dev_priv - > current_page = 0 ;
2008-11-28 14:22:24 +10:00
if ( master_priv - > sarea_priv )
master_priv - > sarea_priv - > pf_current_page = 0 ;
2005-04-16 15:20:36 -07:00
/* Allow hardware batchbuffers unless told otherwise.
*/
dev_priv - > allow_batchbuffer = 1 ;
return 0 ;
}
2007-07-11 15:53:27 +10:00
static int i915_dma_resume ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = ( drm_i915_private_t * ) dev - > dev_private ;
2008-04-30 00:55:10 -07:00
DRM_DEBUG ( " %s \n " , __func__ ) ;
2005-04-16 15:20:36 -07:00
if ( dev_priv - > ring . map . handle = = NULL ) {
DRM_ERROR ( " can not ioremap virtual address for "
" ring buffer \n " ) ;
2007-08-25 19:22:43 +10:00
return - ENOMEM ;
2005-04-16 15:20:36 -07:00
}
/* Program Hardware Status Page */
if ( ! dev_priv - > hw_status_page ) {
DRM_ERROR ( " Can not find hardware status page \n " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
DRM_DEBUG ( " hw status page @ %p \n " , dev_priv - > hw_status_page ) ;
2007-06-10 15:58:19 +10:00
if ( dev_priv - > status_gfx_addr ! = 0 )
2008-07-29 11:54:06 -07:00
I915_WRITE ( HWS_PGA , dev_priv - > status_gfx_addr ) ;
2007-06-10 15:58:19 +10:00
else
2008-07-29 11:54:06 -07:00
I915_WRITE ( HWS_PGA , dev_priv - > dma_status_page ) ;
2005-04-16 15:20:36 -07:00
DRM_DEBUG ( " Enabled hardware status page \n " ) ;
return 0 ;
}
2007-09-03 12:06:45 +10:00
static int i915_dma_init ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
2007-09-03 12:06:45 +10:00
drm_i915_init_t * init = data ;
2005-04-16 15:20:36 -07:00
int retcode = 0 ;
2007-09-03 12:06:45 +10:00
switch ( init - > func ) {
2005-04-16 15:20:36 -07:00
case I915_INIT_DMA :
2007-11-22 14:14:14 +10:00
retcode = i915_initialize ( dev , init ) ;
2005-04-16 15:20:36 -07:00
break ;
case I915_CLEANUP_DMA :
retcode = i915_dma_cleanup ( dev ) ;
break ;
case I915_RESUME_DMA :
2006-01-02 20:14:23 +11:00
retcode = i915_dma_resume ( dev ) ;
2005-04-16 15:20:36 -07:00
break ;
default :
2007-08-25 19:22:43 +10:00
retcode = - EINVAL ;
2005-04-16 15:20:36 -07:00
break ;
}
return retcode ;
}
/* Implement basically the same security restrictions as hardware does
* for MI_BATCH_NON_SECURE . These can be made stricter at any time .
*
* Most of the calculations below involve calculating the size of a
* particular instruction . It ' s important to get the size right as
* that tells us where the next instruction to check is . Any illegal
* instruction detected will be given a size of zero , which is a
* signal to abort the rest of the buffer .
*/
static int do_validate_cmd ( int cmd )
{
switch ( ( ( cmd > > 29 ) & 0x7 ) ) {
case 0x0 :
switch ( ( cmd > > 23 ) & 0x3f ) {
case 0x0 :
return 1 ; /* MI_NOOP */
case 0x4 :
return 1 ; /* MI_FLUSH */
default :
return 0 ; /* disallow everything else */
}
break ;
case 0x1 :
return 0 ; /* reserved */
case 0x2 :
return ( cmd & 0xff ) + 2 ; /* 2d commands */
case 0x3 :
if ( ( ( cmd > > 24 ) & 0x1f ) < = 0x18 )
return 1 ;
switch ( ( cmd > > 24 ) & 0x1f ) {
case 0x1c :
return 1 ;
case 0x1d :
2005-09-25 14:28:13 +10:00
switch ( ( cmd > > 16 ) & 0xff ) {
2005-04-16 15:20:36 -07:00
case 0x3 :
return ( cmd & 0x1f ) + 2 ;
case 0x4 :
return ( cmd & 0xf ) + 2 ;
default :
return ( cmd & 0xffff ) + 2 ;
}
case 0x1e :
if ( cmd & ( 1 < < 23 ) )
return ( cmd & 0xffff ) + 1 ;
else
return 1 ;
case 0x1f :
if ( ( cmd & ( 1 < < 23 ) ) = = 0 ) /* inline vertices */
return ( cmd & 0x1ffff ) + 2 ;
else if ( cmd & ( 1 < < 17 ) ) /* indirect random */
if ( ( cmd & 0xffff ) = = 0 )
return 0 ; /* unknown length, too hard */
else
return ( ( ( cmd & 0xffff ) + 1 ) / 2 ) + 1 ;
else
return 2 ; /* indirect sequential */
default :
return 0 ;
}
default :
return 0 ;
}
return 0 ;
}
static int validate_cmd ( int cmd )
{
int ret = do_validate_cmd ( cmd ) ;
2007-11-05 12:50:58 +10:00
/* printk("validate_cmd( %x ): %d\n", cmd, ret); */
2005-04-16 15:20:36 -07:00
return ret ;
}
2007-07-11 15:53:27 +10:00
static int i915_emit_cmds ( struct drm_device * dev , int __user * buffer , int dwords )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
int i ;
RING_LOCALS ;
2006-01-25 15:31:43 +11:00
if ( ( dwords + 1 ) * sizeof ( int ) > = dev_priv - > ring . Size - 8 )
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2006-01-25 15:31:43 +11:00
2006-08-12 16:29:24 +10:00
BEGIN_LP_RING ( ( dwords + 1 ) & ~ 1 ) ;
2006-01-25 15:31:43 +11:00
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < dwords ; ) {
int cmd , sz ;
if ( DRM_COPY_FROM_USER_UNCHECKED ( & cmd , & buffer [ i ] , sizeof ( cmd ) ) )
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
if ( ( sz = validate_cmd ( cmd ) ) = = 0 | | i + sz > dwords )
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
OUT_RING ( cmd ) ;
while ( + + i , - - sz ) {
if ( DRM_COPY_FROM_USER_UNCHECKED ( & cmd , & buffer [ i ] ,
sizeof ( cmd ) ) ) {
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
OUT_RING ( cmd ) ;
}
}
2006-01-25 15:31:43 +11:00
if ( dwords & 1 )
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2008-07-30 12:06:12 -07:00
int
i915_emit_box ( struct drm_device * dev ,
struct drm_clip_rect __user * boxes ,
int i , int DR1 , int DR4 )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2007-07-11 15:27:12 +10:00
struct drm_clip_rect box ;
2005-04-16 15:20:36 -07:00
RING_LOCALS ;
if ( DRM_COPY_FROM_USER_UNCHECKED ( & box , & boxes [ i ] , sizeof ( box ) ) ) {
2007-08-25 19:22:43 +10:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
}
if ( box . y2 < = box . y1 | | box . x2 < = box . x1 | | box . y2 < = 0 | | box . x2 < = 0 ) {
DRM_ERROR ( " Bad box %d,%d..%d,%d \n " ,
box . x1 , box . y1 , box . x2 , box . y2 ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2006-08-12 16:29:24 +10:00
if ( IS_I965G ( dev ) ) {
BEGIN_LP_RING ( 4 ) ;
OUT_RING ( GFX_OP_DRAWRECT_INFO_I965 ) ;
OUT_RING ( ( box . x1 & 0xffff ) | ( box . y1 < < 16 ) ) ;
2006-08-16 09:15:51 +10:00
OUT_RING ( ( ( box . x2 - 1 ) & 0xffff ) | ( ( box . y2 - 1 ) < < 16 ) ) ;
2006-08-12 16:29:24 +10:00
OUT_RING ( DR4 ) ;
ADVANCE_LP_RING ( ) ;
} else {
BEGIN_LP_RING ( 6 ) ;
OUT_RING ( GFX_OP_DRAWRECT_INFO ) ;
OUT_RING ( DR1 ) ;
OUT_RING ( ( box . x1 & 0xffff ) | ( box . y1 < < 16 ) ) ;
OUT_RING ( ( ( box . x2 - 1 ) & 0xffff ) | ( ( box . y2 - 1 ) < < 16 ) ) ;
OUT_RING ( DR4 ) ;
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2006-08-12 16:29:24 +10:00
/* XXX: Emitting the counter should really be moved to part of the IRQ
* emit . For now , do it in both places :
*/
2007-07-11 15:53:27 +10:00
static void i915_emit_breadcrumb ( struct drm_device * dev )
2006-01-25 15:31:43 +11:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv = dev - > primary - > master - > driver_priv ;
2006-01-25 15:31:43 +11:00
RING_LOCALS ;
2008-08-20 11:20:13 -04:00
dev_priv - > counter + + ;
2008-05-07 12:15:39 +10:00
if ( dev_priv - > counter > 0x7FFFFFFFUL )
2008-08-20 11:20:13 -04:00
dev_priv - > counter = 0 ;
2008-11-28 14:22:24 +10:00
if ( master_priv - > sarea_priv )
master_priv - > sarea_priv - > last_enqueue = dev_priv - > counter ;
2006-01-25 15:31:43 +11:00
BEGIN_LP_RING ( 4 ) ;
2008-07-29 11:54:06 -07:00
OUT_RING ( MI_STORE_DWORD_INDEX ) ;
2008-11-08 11:44:14 +10:00
OUT_RING ( I915_BREADCRUMB_INDEX < < MI_STORE_DWORD_INDEX_SHIFT ) ;
2006-01-25 15:31:43 +11:00
OUT_RING ( dev_priv - > counter ) ;
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
}
2007-07-11 15:53:27 +10:00
static int i915_dispatch_cmdbuffer ( struct drm_device * dev ,
2005-04-16 15:20:36 -07:00
drm_i915_cmdbuffer_t * cmd )
{
int nbox = cmd - > num_cliprects ;
int i = 0 , count , ret ;
if ( cmd - > sz & 0x3 ) {
DRM_ERROR ( " alignment " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
i915_kernel_lost_context ( dev ) ;
count = nbox ? nbox : 1 ;
for ( i = 0 ; i < count ; i + + ) {
if ( i < nbox ) {
ret = i915_emit_box ( dev , cmd - > cliprects , i ,
cmd - > DR1 , cmd - > DR4 ) ;
if ( ret )
return ret ;
}
ret = i915_emit_cmds ( dev , ( int __user * ) cmd - > buf , cmd - > sz / 4 ) ;
if ( ret )
return ret ;
}
2006-01-25 15:31:43 +11:00
i915_emit_breadcrumb ( dev ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-07-11 15:53:27 +10:00
static int i915_dispatch_batchbuffer ( struct drm_device * dev ,
2005-04-16 15:20:36 -07:00
drm_i915_batchbuffer_t * batch )
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2007-07-11 15:27:12 +10:00
struct drm_clip_rect __user * boxes = batch - > cliprects ;
2005-04-16 15:20:36 -07:00
int nbox = batch - > num_cliprects ;
int i = 0 , count ;
RING_LOCALS ;
if ( ( batch - > start | batch - > used ) & 0x7 ) {
DRM_ERROR ( " alignment " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
i915_kernel_lost_context ( dev ) ;
count = nbox ? nbox : 1 ;
for ( i = 0 ; i < count ; i + + ) {
if ( i < nbox ) {
int ret = i915_emit_box ( dev , boxes , i ,
batch - > DR1 , batch - > DR4 ) ;
if ( ret )
return ret ;
}
2008-07-30 12:28:47 -07:00
if ( ! IS_I830 ( dev ) & & ! IS_845G ( dev ) ) {
2005-04-16 15:20:36 -07:00
BEGIN_LP_RING ( 2 ) ;
2007-08-07 09:09:51 +10:00
if ( IS_I965G ( dev ) ) {
OUT_RING ( MI_BATCH_BUFFER_START | ( 2 < < 6 ) | MI_BATCH_NON_SECURE_I965 ) ;
OUT_RING ( batch - > start ) ;
} else {
OUT_RING ( MI_BATCH_BUFFER_START | ( 2 < < 6 ) ) ;
OUT_RING ( batch - > start | MI_BATCH_NON_SECURE ) ;
}
2005-04-16 15:20:36 -07:00
ADVANCE_LP_RING ( ) ;
} else {
BEGIN_LP_RING ( 4 ) ;
OUT_RING ( MI_BATCH_BUFFER ) ;
OUT_RING ( batch - > start | MI_BATCH_NON_SECURE ) ;
OUT_RING ( batch - > start + batch - > used - 4 ) ;
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
}
}
2006-01-25 15:31:43 +11:00
i915_emit_breadcrumb ( dev ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2008-05-07 12:15:39 +10:00
static int i915_dispatch_flip ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv =
dev - > primary - > master - > driver_priv ;
2005-04-16 15:20:36 -07:00
RING_LOCALS ;
2008-11-28 14:22:24 +10:00
if ( ! master_priv - > sarea_priv )
2008-08-20 11:20:13 -04:00
return - EINVAL ;
2008-05-07 12:15:39 +10:00
DRM_DEBUG ( " %s: page=%d pfCurrentPage=%d \n " ,
2008-10-15 22:01:25 -07:00
__func__ ,
2008-05-07 12:15:39 +10:00
dev_priv - > current_page ,
2008-11-28 14:22:24 +10:00
master_priv - > sarea_priv - > pf_current_page ) ;
2005-04-16 15:20:36 -07:00
2008-05-07 12:15:39 +10:00
i915_kernel_lost_context ( dev ) ;
BEGIN_LP_RING ( 2 ) ;
2008-07-29 11:54:06 -07:00
OUT_RING ( MI_FLUSH | MI_READ_FLUSH ) ;
2008-05-07 12:15:39 +10:00
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
2005-04-16 15:20:36 -07:00
2008-05-07 12:15:39 +10:00
BEGIN_LP_RING ( 6 ) ;
OUT_RING ( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP ) ;
OUT_RING ( 0 ) ;
if ( dev_priv - > current_page = = 0 ) {
OUT_RING ( dev_priv - > back_offset ) ;
dev_priv - > current_page = 1 ;
2005-04-16 15:20:36 -07:00
} else {
2008-05-07 12:15:39 +10:00
OUT_RING ( dev_priv - > front_offset ) ;
dev_priv - > current_page = 0 ;
2005-04-16 15:20:36 -07:00
}
2008-05-07 12:15:39 +10:00
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
2005-04-16 15:20:36 -07:00
2008-05-07 12:15:39 +10:00
BEGIN_LP_RING ( 2 ) ;
OUT_RING ( MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP ) ;
OUT_RING ( 0 ) ;
ADVANCE_LP_RING ( ) ;
2005-04-16 15:20:36 -07:00
2008-11-28 14:22:24 +10:00
master_priv - > sarea_priv - > last_enqueue = dev_priv - > counter + + ;
2005-04-16 15:20:36 -07:00
BEGIN_LP_RING ( 4 ) ;
2008-07-29 11:54:06 -07:00
OUT_RING ( MI_STORE_DWORD_INDEX ) ;
2008-11-08 11:44:14 +10:00
OUT_RING ( I915_BREADCRUMB_INDEX < < MI_STORE_DWORD_INDEX_SHIFT ) ;
2008-05-07 12:15:39 +10:00
OUT_RING ( dev_priv - > counter ) ;
OUT_RING ( 0 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_LP_RING ( ) ;
2008-11-28 14:22:24 +10:00
master_priv - > sarea_priv - > pf_current_page = dev_priv - > current_page ;
2008-05-07 12:15:39 +10:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-07-11 15:53:27 +10:00
static int i915_quiescent ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
i915_kernel_lost_context ( dev ) ;
2008-04-30 00:55:10 -07:00
return i915_wait_ring ( dev , dev_priv - > ring . Size - 8 , __func__ ) ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
static int i915_flush_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
2008-09-01 16:45:29 -07:00
int ret ;
RING_LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
ret = i915_quiescent ( dev ) ;
mutex_unlock ( & dev - > struct_mutex ) ;
return ret ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
static int i915_batchbuffer ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = ( drm_i915_private_t * ) dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv = dev - > primary - > master - > driver_priv ;
2005-04-16 15:20:36 -07:00
drm_i915_sarea_t * sarea_priv = ( drm_i915_sarea_t * )
2008-11-28 14:22:24 +10:00
master_priv - > sarea_priv ;
2007-09-03 12:06:45 +10:00
drm_i915_batchbuffer_t * batch = data ;
2005-04-16 15:20:36 -07:00
int ret ;
if ( ! dev_priv - > allow_batchbuffer ) {
DRM_ERROR ( " Batchbuffer ioctl disabled \n " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
DRM_DEBUG ( " i915 batchbuffer, start %x used %d cliprects %d \n " ,
2007-09-03 12:06:45 +10:00
batch - > start , batch - > used , batch - > num_cliprects ) ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
RING_LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-16 15:20:36 -07:00
2007-09-03 12:06:45 +10:00
if ( batch - > num_cliprects & & DRM_VERIFYAREA_READ ( batch - > cliprects ,
batch - > num_cliprects *
2007-07-11 15:27:12 +10:00
sizeof ( struct drm_clip_rect ) ) )
2007-08-25 19:22:43 +10:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-09-03 12:06:45 +10:00
ret = i915_dispatch_batchbuffer ( dev , batch ) ;
2008-09-01 16:45:29 -07:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-16 15:20:36 -07:00
2008-08-20 11:20:13 -04:00
if ( sarea_priv )
2008-11-08 11:44:14 +10:00
sarea_priv - > last_dispatch = READ_BREADCRUMB ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
return ret ;
}
2007-09-03 12:06:45 +10:00
static int i915_cmdbuffer ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = ( drm_i915_private_t * ) dev - > dev_private ;
2008-11-28 14:22:24 +10:00
struct drm_i915_master_private * master_priv = dev - > primary - > master - > driver_priv ;
2005-04-16 15:20:36 -07:00
drm_i915_sarea_t * sarea_priv = ( drm_i915_sarea_t * )
2008-11-28 14:22:24 +10:00
master_priv - > sarea_priv ;
2007-09-03 12:06:45 +10:00
drm_i915_cmdbuffer_t * cmdbuf = data ;
2005-04-16 15:20:36 -07:00
int ret ;
DRM_DEBUG ( " i915 cmdbuffer, buf %p sz %d cliprects %d \n " ,
2007-09-03 12:06:45 +10:00
cmdbuf - > buf , cmdbuf - > sz , cmdbuf - > num_cliprects ) ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
RING_LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-16 15:20:36 -07:00
2007-09-03 12:06:45 +10:00
if ( cmdbuf - > num_cliprects & &
DRM_VERIFYAREA_READ ( cmdbuf - > cliprects ,
cmdbuf - > num_cliprects *
2007-07-11 15:27:12 +10:00
sizeof ( struct drm_clip_rect ) ) ) {
2005-04-16 15:20:36 -07:00
DRM_ERROR ( " Fault accessing cliprects \n " ) ;
2007-08-25 19:22:43 +10:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
}
2008-09-01 16:45:29 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-09-03 12:06:45 +10:00
ret = i915_dispatch_cmdbuffer ( dev , cmdbuf ) ;
2008-09-01 16:45:29 -07:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-16 15:20:36 -07:00
if ( ret ) {
DRM_ERROR ( " i915_dispatch_cmdbuffer failed \n " ) ;
return ret ;
}
2008-08-20 11:20:13 -04:00
if ( sarea_priv )
2008-11-08 11:44:14 +10:00
sarea_priv - > last_dispatch = READ_BREADCRUMB ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-09-03 12:06:45 +10:00
static int i915_flip_bufs ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
2008-09-01 16:45:29 -07:00
int ret ;
2008-10-15 22:01:25 -07:00
DRM_DEBUG ( " %s \n " , __func__ ) ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
RING_LOCK_TEST_WITH_RETURN ( dev , file_priv ) ;
2005-04-16 15:20:36 -07:00
2008-09-01 16:45:29 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
ret = i915_dispatch_flip ( dev ) ;
mutex_unlock ( & dev - > struct_mutex ) ;
return ret ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
static int i915_getparam ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2007-09-03 12:06:45 +10:00
drm_i915_getparam_t * param = data ;
2005-04-16 15:20:36 -07:00
int value ;
if ( ! dev_priv ) {
2008-01-24 15:58:57 +10:00
DRM_ERROR ( " called with no initialization \n " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
switch ( param - > param ) {
2005-04-16 15:20:36 -07:00
case I915_PARAM_IRQ_ACTIVE :
2008-09-30 12:14:26 -07:00
value = dev - > pdev - > irq ? 1 : 0 ;
2005-04-16 15:20:36 -07:00
break ;
case I915_PARAM_ALLOW_BATCHBUFFER :
value = dev_priv - > allow_batchbuffer ? 1 : 0 ;
break ;
2006-01-02 20:14:23 +11:00
case I915_PARAM_LAST_DISPATCH :
value = READ_BREADCRUMB ( dev_priv ) ;
break ;
2008-08-20 11:08:52 -04:00
case I915_PARAM_CHIPSET_ID :
value = dev - > pci_device ;
break ;
2008-07-30 12:06:12 -07:00
case I915_PARAM_HAS_GEM :
2008-12-19 15:38:34 +10:00
value = dev_priv - > has_gem ;
2008-07-30 12:06:12 -07:00
break ;
2005-04-16 15:20:36 -07:00
default :
2007-09-03 12:06:45 +10:00
DRM_ERROR ( " Unknown parameter %d \n " , param - > param ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
if ( DRM_COPY_TO_USER ( param - > value , & value , sizeof ( int ) ) ) {
2005-04-16 15:20:36 -07:00
DRM_ERROR ( " DRM_COPY_TO_USER failed \n " ) ;
2007-08-25 19:22:43 +10:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
2007-09-03 12:06:45 +10:00
static int i915_setparam ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2007-09-03 12:06:45 +10:00
drm_i915_setparam_t * param = data ;
2005-04-16 15:20:36 -07:00
if ( ! dev_priv ) {
2008-01-24 15:58:57 +10:00
DRM_ERROR ( " called with no initialization \n " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
2007-09-03 12:06:45 +10:00
switch ( param - > param ) {
2005-04-16 15:20:36 -07:00
case I915_SETPARAM_USE_MI_BATCHBUFFER_START :
break ;
case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY :
2007-09-03 12:06:45 +10:00
dev_priv - > tex_lru_log_granularity = param - > value ;
2005-04-16 15:20:36 -07:00
break ;
case I915_SETPARAM_ALLOW_BATCHBUFFER :
2007-09-03 12:06:45 +10:00
dev_priv - > allow_batchbuffer = param - > value ;
2005-04-16 15:20:36 -07:00
break ;
default :
2007-09-03 12:06:45 +10:00
DRM_ERROR ( " unknown parameter %d \n " , param - > param ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
2007-09-03 12:06:45 +10:00
static int i915_set_status_page ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2007-06-10 15:58:19 +10:00
{
drm_i915_private_t * dev_priv = dev - > dev_private ;
2007-09-03 12:06:45 +10:00
drm_i915_hws_addr_t * hws = data ;
2008-02-19 20:59:09 +10:00
if ( ! I915_NEED_GFX_HWS ( dev ) )
return - EINVAL ;
2007-06-10 15:58:19 +10:00
if ( ! dev_priv ) {
2008-01-24 15:58:57 +10:00
DRM_ERROR ( " called with no initialization \n " ) ;
2007-08-25 19:22:43 +10:00
return - EINVAL ;
2007-06-10 15:58:19 +10:00
}
2007-09-03 12:06:45 +10:00
printk ( KERN_DEBUG " set status page addr 0x%08x \n " , ( u32 ) hws - > addr ) ;
dev_priv - > status_gfx_addr = hws - > addr & ( 0x1ffff < < 12 ) ;
2007-06-10 15:58:19 +10:00
2007-11-22 16:40:37 +10:00
dev_priv - > hws_map . offset = dev - > agp - > base + hws - > addr ;
2007-06-10 15:58:19 +10:00
dev_priv - > hws_map . size = 4 * 1024 ;
dev_priv - > hws_map . type = 0 ;
dev_priv - > hws_map . flags = 0 ;
dev_priv - > hws_map . mtrr = 0 ;
drm_core_ioremap ( & dev_priv - > hws_map , dev ) ;
if ( dev_priv - > hws_map . handle = = NULL ) {
i915_dma_cleanup ( dev ) ;
dev_priv - > status_gfx_addr = 0 ;
DRM_ERROR ( " can not ioremap virtual address for "
" G33 hw status page \n " ) ;
2007-08-25 19:22:43 +10:00
return - ENOMEM ;
2007-06-10 15:58:19 +10:00
}
dev_priv - > hw_status_page = dev_priv - > hws_map . handle ;
memset ( dev_priv - > hw_status_page , 0 , PAGE_SIZE ) ;
2008-07-29 11:54:06 -07:00
I915_WRITE ( HWS_PGA , dev_priv - > status_gfx_addr ) ;
DRM_DEBUG ( " load hws HWS_PGA with gfx mem 0x%x \n " ,
2007-06-10 15:58:19 +10:00
dev_priv - > status_gfx_addr ) ;
DRM_DEBUG ( " load hws at %p \n " , dev_priv - > hw_status_page ) ;
return 0 ;
}
2008-11-28 14:22:24 +10:00
int i915_master_create ( struct drm_device * dev , struct drm_master * master )
{
struct drm_i915_master_private * master_priv ;
master_priv = drm_calloc ( 1 , sizeof ( * master_priv ) , DRM_MEM_DRIVER ) ;
if ( ! master_priv )
return - ENOMEM ;
master - > driver_priv = master_priv ;
return 0 ;
}
void i915_master_destroy ( struct drm_device * dev , struct drm_master * master )
{
struct drm_i915_master_private * master_priv = master - > driver_priv ;
if ( ! master_priv )
return ;
drm_free ( master_priv , sizeof ( * master_priv ) , DRM_MEM_DRIVER ) ;
master - > driver_priv = NULL ;
}
2007-07-11 15:53:27 +10:00
int i915_driver_load ( struct drm_device * dev , unsigned long flags )
2005-11-10 22:16:34 +11:00
{
2007-11-22 14:14:14 +10:00
struct drm_i915_private * dev_priv = dev - > dev_private ;
unsigned long base , size ;
int ret = 0 , mmio_bar = IS_I9XX ( dev ) ? 0 : 1 ;
2005-11-10 22:16:34 +11:00
/* i915 has 4 more counters */
dev - > counters + = 4 ;
dev - > types [ 6 ] = _DRM_STAT_IRQ ;
dev - > types [ 7 ] = _DRM_STAT_PRIMARY ;
dev - > types [ 8 ] = _DRM_STAT_SECONDARY ;
dev - > types [ 9 ] = _DRM_STAT_DMA ;
2007-11-22 14:14:14 +10:00
dev_priv = drm_alloc ( sizeof ( drm_i915_private_t ) , DRM_MEM_DRIVER ) ;
if ( dev_priv = = NULL )
return - ENOMEM ;
memset ( dev_priv , 0 , sizeof ( drm_i915_private_t ) ) ;
dev - > dev_private = ( void * ) dev_priv ;
2008-07-30 12:06:12 -07:00
dev_priv - > dev = dev ;
2007-11-22 14:14:14 +10:00
/* Add register map (needed for suspend/resume) */
base = drm_get_resource_start ( dev , mmio_bar ) ;
size = drm_get_resource_len ( dev , mmio_bar ) ;
2008-10-02 12:24:47 -07:00
dev_priv - > regs = ioremap ( base , size ) ;
2008-07-29 12:10:39 -07:00
2008-12-19 15:38:34 +10:00
# ifdef CONFIG_HIGHMEM64G
/* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
dev_priv - > has_gem = 0 ;
# else
/* enable GEM by default */
dev_priv - > has_gem = 1 ;
# endif
2008-07-30 12:06:12 -07:00
i915_gem_load ( dev ) ;
2008-07-30 13:03:43 -07:00
/* Init HWS */
if ( ! I915_NEED_GFX_HWS ( dev ) ) {
ret = i915_init_phys_hws ( dev ) ;
if ( ret ! = 0 )
return ret ;
}
2008-07-29 12:10:39 -07:00
/* On the 945G/GM, the chipset reports the MSI capability on the
* integrated graphics even though the support isn ' t actually there
* according to the published specs . It doesn ' t appear to function
* correctly in testing on 945 G .
* This may be a side effect of MSI having been made available for PEG
* and the registers being closely associated .
2008-10-17 00:44:42 -07:00
*
* According to chipset errata , on the 965 GM , MSI interrupts may
2008-12-08 11:12:28 -08:00
* be lost or delayed , but we use them anyways to avoid
* stuck interrupts on some machines .
2008-07-29 12:10:39 -07:00
*/
2008-12-08 11:12:28 -08:00
if ( ! IS_I945G ( dev ) & & ! IS_I945GM ( dev ) )
2008-11-03 14:46:17 -08:00
pci_enable_msi ( dev - > pdev ) ;
2008-07-29 12:10:39 -07:00
2008-08-05 19:37:25 +01:00
intel_opregion_init ( dev ) ;
2008-07-29 12:10:39 -07:00
spin_lock_init ( & dev_priv - > user_irq_lock ) ;
2008-11-18 09:30:25 -08:00
ret = drm_vblank_init ( dev , I915_NUM_PIPE ) ;
if ( ret ) {
( void ) i915_driver_unload ( dev ) ;
return ret ;
}
2007-11-22 14:14:14 +10:00
return ret ;
}
int i915_driver_unload ( struct drm_device * dev )
{
struct drm_i915_private * dev_priv = dev - > dev_private ;
2008-07-29 12:10:39 -07:00
if ( dev - > pdev - > msi_enabled )
pci_disable_msi ( dev - > pdev ) ;
2008-07-30 13:03:43 -07:00
i915_free_hws ( dev ) ;
2008-10-02 12:24:47 -07:00
if ( dev_priv - > regs ! = NULL )
iounmap ( dev_priv - > regs ) ;
2007-11-22 14:14:14 +10:00
2008-08-05 19:37:25 +01:00
intel_opregion_free ( dev ) ;
2007-11-22 14:14:14 +10:00
drm_free ( dev - > dev_private , sizeof ( drm_i915_private_t ) ,
DRM_MEM_DRIVER ) ;
2005-11-10 22:16:34 +11:00
return 0 ;
}
2008-07-30 12:06:12 -07:00
int i915_driver_open ( struct drm_device * dev , struct drm_file * file_priv )
{
struct drm_i915_file_private * i915_file_priv ;
DRM_DEBUG ( " \n " ) ;
i915_file_priv = ( struct drm_i915_file_private * )
drm_alloc ( sizeof ( * i915_file_priv ) , DRM_MEM_FILES ) ;
if ( ! i915_file_priv )
return - ENOMEM ;
file_priv - > driver_priv = i915_file_priv ;
i915_file_priv - > mm . last_gem_seqno = 0 ;
i915_file_priv - > mm . last_gem_throttle_seqno = 0 ;
return 0 ;
}
2007-07-11 15:53:27 +10:00
void i915_driver_lastclose ( struct drm_device * dev )
2005-04-16 15:20:36 -07:00
{
2007-11-22 14:14:14 +10:00
drm_i915_private_t * dev_priv = dev - > dev_private ;
2008-03-30 07:53:58 +10:00
if ( ! dev_priv )
return ;
2008-07-30 12:06:12 -07:00
i915_gem_lastclose ( dev ) ;
2007-11-22 14:14:14 +10:00
if ( dev_priv - > agp_heap )
2005-09-25 14:28:13 +10:00
i915_mem_takedown ( & ( dev_priv - > agp_heap ) ) ;
2007-11-22 14:14:14 +10:00
2005-09-25 14:28:13 +10:00
i915_dma_cleanup ( dev ) ;
2005-04-16 15:20:36 -07:00
}
2007-08-25 20:23:09 +10:00
void i915_driver_preclose ( struct drm_device * dev , struct drm_file * file_priv )
2005-04-16 15:20:36 -07:00
{
2007-11-22 14:14:14 +10:00
drm_i915_private_t * dev_priv = dev - > dev_private ;
i915_mem_release ( dev , file_priv , dev_priv - > agp_heap ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-30 12:06:12 -07:00
void i915_driver_postclose ( struct drm_device * dev , struct drm_file * file_priv )
{
struct drm_i915_file_private * i915_file_priv = file_priv - > driver_priv ;
drm_free ( i915_file_priv , sizeof ( * i915_file_priv ) , DRM_MEM_FILES ) ;
}
2007-09-03 12:06:45 +10:00
struct drm_ioctl_desc i915_ioctls [ ] = {
DRM_IOCTL_DEF ( DRM_I915_INIT , i915_dma_init , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_FLUSH , i915_flush_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_FLIP , i915_flip_bufs , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_BATCHBUFFER , i915_batchbuffer , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_IRQ_EMIT , i915_irq_emit , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_IRQ_WAIT , i915_irq_wait , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_GETPARAM , i915_getparam , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_SETPARAM , i915_setparam , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_ALLOC , i915_mem_alloc , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_FREE , i915_mem_free , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_INIT_HEAP , i915_mem_init_heap , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_CMDBUFFER , i915_cmdbuffer , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_DESTROY_HEAP , i915_mem_destroy_heap , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_SET_VBLANK_PIPE , i915_vblank_pipe_set , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_GET_VBLANK_PIPE , i915_vblank_pipe_get , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_VBLANK_SWAP , i915_vblank_swap , DRM_AUTH ) ,
2008-10-18 07:18:05 +10:00
DRM_IOCTL_DEF ( DRM_I915_HWS_ADDR , i915_set_status_page , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2008-10-07 13:40:10 +10:00
DRM_IOCTL_DEF ( DRM_I915_GEM_INIT , i915_gem_init_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2008-07-30 12:06:12 -07:00
DRM_IOCTL_DEF ( DRM_I915_GEM_EXECBUFFER , i915_gem_execbuffer , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_PIN , i915_gem_pin_ioctl , DRM_AUTH | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_UNPIN , i915_gem_unpin_ioctl , DRM_AUTH | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_BUSY , i915_gem_busy_ioctl , DRM_AUTH ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_THROTTLE , i915_gem_throttle_ioctl , DRM_AUTH ) ,
2008-10-07 13:40:10 +10:00
DRM_IOCTL_DEF ( DRM_I915_GEM_ENTERVT , i915_gem_entervt_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_LEAVEVT , i915_gem_leavevt_ioctl , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY ) ,
2008-07-30 12:06:12 -07:00
DRM_IOCTL_DEF ( DRM_I915_GEM_CREATE , i915_gem_create_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_PREAD , i915_gem_pread_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_PWRITE , i915_gem_pwrite_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_MMAP , i915_gem_mmap_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_SET_DOMAIN , i915_gem_set_domain_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_SW_FINISH , i915_gem_sw_finish_ioctl , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_SET_TILING , i915_gem_set_tiling , 0 ) ,
DRM_IOCTL_DEF ( DRM_I915_GEM_GET_TILING , i915_gem_get_tiling , 0 ) ,
2008-10-22 21:40:13 -07:00
DRM_IOCTL_DEF ( DRM_I915_GEM_GET_APERTURE , i915_gem_get_aperture_ioctl , 0 ) ,
2005-07-07 21:03:38 +10:00
} ;
int i915_max_ioctl = DRM_ARRAY_SIZE ( i915_ioctls ) ;
2005-07-10 17:31:26 +10:00
/**
* Determine if the device really is AGP or not .
*
* All Intel graphics chipsets are treated as AGP , even if they are really
* PCI - e .
*
* \ param dev The device to be tested .
*
* \ returns
* A value of 1 is always retured to indictate every i9x5 is AGP .
*/
2007-07-11 15:53:27 +10:00
int i915_driver_device_is_agp ( struct drm_device * dev )
2005-07-10 17:31:26 +10:00
{
return 1 ;
}