diff options
author | Gareth Hughes <gareth@users.sourceforge.net> | 2001-02-13 03:43:04 +0000 |
---|---|---|
committer | Gareth Hughes <gareth@users.sourceforge.net> | 2001-02-13 03:43:04 +0000 |
commit | b093470fc600a1465be9621ed58a68f53f1660f4 (patch) | |
tree | 59e74e2871987eb3d71aeb9161770461d724f19e | |
parent | 650f48096df93033607952410985ed52878a9469 (diff) |
Merge (most of) the latest trunk code into the branch.
-rw-r--r-- | linux-core/mga_drv.c | 3 | ||||
-rw-r--r-- | linux/mga_dma.c | 50 | ||||
-rw-r--r-- | linux/mga_drm.h | 27 | ||||
-rw-r--r-- | linux/mga_drv.c | 3 | ||||
-rw-r--r-- | linux/mga_drv.h | 10 | ||||
-rw-r--r-- | linux/mga_state.c | 278 |
6 files changed, 226 insertions, 145 deletions
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index 2a727c52..2ab48272 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -53,7 +53,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, #define __HAVE_COUNTERS 3 #define __HAVE_COUNTER6 _DRM_STAT_IRQ diff --git a/linux/mga_dma.c b/linux/mga_dma.c index f4f2b05b..97f33ae0 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -209,6 +209,10 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) tail = primary->tail + dev_priv->primary->offset; + /* We need to pad the stream between flushes, as the card + * actually (partially?) reads the first of these commands. + * See page 4-16 in the G400 manual, middle of the page or so. + */ BEGIN_DMA( 1 ); DMA_BLOCK( MGA_DMAPAD, 0x00000000, @@ -233,7 +237,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) DRM_DEBUG( " space = 0x%06x\n", primary->space ); mga_flush_write_combine(); - MGA_WRITE( MGA_PRIMEND, tail | MGA_PRIMNOSTART | MGA_PAGPXFER ); + MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); DRM_DEBUG( "%s: done.\n", __FUNCTION__ ); } @@ -275,7 +279,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) DRM_DEBUG( " space = 0x%06x\n", primary->space ); mga_flush_write_combine(); - MGA_WRITE( MGA_PRIMEND, tail | MGA_PRIMNOSTART | MGA_PAGPXFER ); + MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); DRM_DEBUG( "%s: done.\n", __FUNCTION__ ); } @@ -288,6 +292,7 @@ void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ) DRM_DEBUG( "%s:\n", __FUNCTION__ ); sarea_priv->last_wrap++; + DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap ); *primary->head = head; @@ -444,9 +449,8 @@ static int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; - drm_mga_freelist_t *head; - drm_mga_freelist_t *next; - drm_mga_freelist_t *prev; + drm_mga_freelist_t *head, *next, *prev; + DRM_DEBUG( "%s: age=0x%06lx wrap=%d\n", __FUNCTION__, buf_priv->list_entry->age.head - @@ -454,29 +458,19 @@ static int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) buf_priv->list_entry->age.wrap ); if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) { - /* Discarded buffer, put it on the tail. - */ - next = buf_priv->list_entry; - next->age.head = MGA_BUFFER_FREE; - next->age.wrap = 0; - prev = dev_priv->tail; - prev->next = next; - next->prev = prev; - next->next = NULL; - dev_priv->tail = next; - } else { - /* Normally aged buffer, put it on the head + 1, - * as the real head is a sentinal element - */ - next = buf_priv->list_entry; - head = dev_priv->head; - prev = head->next; - head->next = next; - prev->prev = next; - next->prev = head; - next->next = prev; + SET_AGE( &next->age, MGA_BUFFER_FREE, 0 ); } + /* Put buffer on the head + 1, as the head is a sentinal. + */ + next = buf_priv->list_entry; + head = dev_priv->head; + prev = head->next; + head->next = next; + prev->prev = next; + next->prev = head; + next->next = prev; + return 0; } @@ -580,7 +574,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) dev_priv->prim.last_flush = 0; dev_priv->prim.last_wrap = 0; - dev_priv->prim.high_mark = 128 * DMA_BLOCK_SIZE; + dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE; spin_lock_init( &dev_priv->prim.flush_lock ); spin_lock_init( &dev_priv->prim.list_lock ); @@ -668,6 +662,8 @@ int mga_dma_flush( struct inode *inode, struct file *filp, (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" ); + WRAP_TEST_WITH_RETURN( dev_priv ); + if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) { mga_do_dma_flush( dev_priv ); } diff --git a/linux/mga_drm.h b/linux/mga_drm.h index 76367840..c2fe4a18 100644 --- a/linux/mga_drm.h +++ b/linux/mga_drm.h @@ -96,9 +96,8 @@ /* 32 buffers of 64k each, total 2 meg. */ -#define MGA_DMA_BUF_ORDER 16 -#define MGA_DMA_BUF_SZ (1 << MGA_DMA_BUF_ORDER) -#define MGA_DMA_BUF_NR 31 +#define MGA_BUFFER_SIZE (1 << 16) +#define MGA_NUM_BUFFERS 32 /* Keep these small for testing. */ @@ -159,7 +158,7 @@ typedef struct { unsigned int texorg4; } drm_mga_texture_regs_t; -/* General ageing mechanism +/* General aging mechanism */ typedef struct { unsigned int head; /* Position of head pointer */ @@ -279,16 +278,16 @@ typedef struct drm_mga_clear { } drm_mga_clear_t; typedef struct drm_mga_vertex { - int idx; /* buffer to queue */ - int used; /* bytes in use */ - int discard; /* client finished with buffer? */ + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ } drm_mga_vertex_t; typedef struct drm_mga_indices { - int idx; /* buffer to queue */ + int idx; /* buffer to queue */ unsigned int start; unsigned int end; - int discard; /* client finished with buffer? */ + int discard; /* client finished with buffer? */ } drm_mga_indices_t; typedef struct drm_mga_iload { @@ -297,4 +296,14 @@ typedef struct drm_mga_iload { unsigned int length; } drm_mga_iload_t; +typedef struct drm_mga_blit { + unsigned int planemask; + unsigned int srcorg; + unsigned int dstorg; + int src_pitch, dst_pitch; + int delta_sx, delta_sy; + int delta_dx, delta_dy; + int height, ydir; /* flip image vertically */ +} drm_mga_blit_t; + #endif diff --git a/linux/mga_drv.c b/linux/mga_drv.c index 2a727c52..2ab48272 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -53,7 +53,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, #define __HAVE_COUNTERS 3 #define __HAVE_COUNTER6 _DRM_STAT_IRQ diff --git a/linux/mga_drv.h b/linux/mga_drv.h index de32a90f..93cd288b 100644 --- a/linux/mga_drv.h +++ b/linux/mga_drv.h @@ -178,6 +178,8 @@ extern int mga_dma_indices( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int mga_dma_iload( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int mga_dma_blit( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* mga_warp.c */ extern int mga_warp_install_microcode( drm_device_t *dev ); @@ -246,7 +248,7 @@ do { \ * Primary DMA command stream */ -#define MGA_VERBOSE ( 0 /*dev_priv->prim.space < 0x100*/ ) +#define MGA_VERBOSE 0 #define DMA_LOCALS unsigned int write; volatile u8 *prim; @@ -260,9 +262,6 @@ do { \ DRM_INFO( " space=0x%x req=0x%x\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ - if ( dev_priv->prim.space < (int)((n) * DMA_BLOCK_SIZE + \ - MGA_DMA_SOFTRAP_SIZE) ) { \ - } \ prim = dev_priv->prim.start; \ write = dev_priv->prim.tail; \ } while (0) @@ -270,7 +269,7 @@ do { \ #define BEGIN_DMA_WRAP() \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( "BEGIN_DMA_WRAP() in %s\n", __FUNCTION__ ); \ + DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \ } \ prim = dev_priv->prim.start; \ @@ -454,6 +453,7 @@ do { \ #define MGA_SECEND 0x2c44 #define MGA_SETUPADDRESS 0x2cd0 #define MGA_SETUPEND 0x2cd4 +#define MGA_SGN 0x1c58 #define MGA_SOFTRAP 0x2c48 #define MGA_SRCORG 0x2cb4 # define MGA_SRMMAP_MASK (1 << 0) diff --git a/linux/mga_state.c b/linux/mga_state.c index 07e8be92..003556f1 100644 --- a/linux/mga_state.c +++ b/linux/mga_state.c @@ -38,25 +38,6 @@ #include "mga_drv.h" #include "drm.h" -#include <linux/interrupt.h> /* For task queue support */ - - -/* If you change the functions to set state, PLEASE - * change these values - */ - -#define MGAEMITCLIP_SIZE 10 -#define MGAEMITCTX_SIZE 20 -#define MGAG200EMITTEX_SIZE 20 -#define MGAG400EMITTEX0_SIZE 30 -#define MGAG400EMITTEX1_SIZE 25 -#define MGAG400EMITPIPE_SIZE 50 -#define MGAG200EMITPIPE_SIZE 15 - -#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \ - MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \ - MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE) - /* ================================================================ * DMA hardware state programming functions @@ -67,7 +48,7 @@ static void mga_emit_clip_rect( drm_mga_private_t *dev_priv, { drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - unsigned int pitch = dev_priv->front_pitch / dev_priv->fb_cpp; + unsigned int pitch = dev_priv->front_pitch; DMA_LOCALS; BEGIN_DMA( 2 ); @@ -94,7 +75,7 @@ static inline void mga_g200_emit_context( drm_mga_private_t *dev_priv ) drm_mga_context_regs_t *ctx = &sarea_priv->context_state; DMA_LOCALS; - BEGIN_DMA( 2 ); + BEGIN_DMA( 3 ); DMA_BLOCK( MGA_DSTORG, ctx->dstorg, MGA_MACCESS, ctx->maccess, @@ -223,7 +204,7 @@ static inline void mga_g400_emit_tex1( drm_mga_private_t *dev_priv ) drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; DMA_LOCALS; - BEGIN_DMA( 6 ); + BEGIN_DMA( 5 ); DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 | MGA_MAP1_ENABLE | @@ -310,16 +291,14 @@ static inline void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) MGA_WACCEPTSEQ, 0x1e000000 ); } else { if ( dev_priv->warp_pipe & MGA_T2 ) { - /* Flush the WARP pipe. - */ + /* Flush the WARP pipe */ DMA_BLOCK( MGA_YDST, 0x00000000, MGA_FXLEFT, 0x00000000, MGA_FXRIGHT, 0x00000001, MGA_DWGCTL, MGA_DWGCTL_FLUSH ); DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001, - /*MGA_DWGSYNC, 0x00007000,*/ - MGA_DMAPAD, 0x00000000, + MGA_DWGSYNC, 0x00007000, MGA_TEXCTL2, MGA_G400_TC2_MAGIC, MGA_LEN + MGA_EXEC, 0x00000000 ); @@ -356,8 +335,7 @@ static inline void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ - /* Padding required to to hardware bug. - */ + /* Padding required to to hardware bug */ DMA_BLOCK( MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, MGA_DMAPAD, 0xffffffff, @@ -505,6 +483,16 @@ static int mga_verify_iload( drm_mga_private_t *dev_priv, return 0; } +static int mga_verify_blit( drm_mga_private_t *dev_priv, + unsigned int srcorg, unsigned int dstorg ) +{ + if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || + (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) { + return -EINVAL; + } + return 0; +} + /* ================================================================ * @@ -520,83 +508,75 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - if ( clear->flags & MGA_FRONT ) { - BEGIN_DMA( 1 + nbox ); + DRM_DEBUG( __FUNCTION__ ":\n" ); - DMA_BLOCK( MGA_FCOL, clear->clear_color, - MGA_PLNWT, clear->color_mask, - MGA_DSTORG, dev_priv->front_offset, - MGA_DWGCTL, dev_priv->clear_cmd ); + for ( i = 0 ; i < nbox ; i++ ) { + drm_clip_rect_t *box = &pbox[i]; + u32 height = box->y2 - box->y1; - for ( i = 0 ; i < nbox ; i++ ) { - drm_clip_rect_t *box = &pbox[i]; - u32 height = box->y2 - box->y1; + if ( clear->flags & MGA_FRONT ) { + BEGIN_DMA( 2 ); DMA_BLOCK( MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, + MGA_PLNWT, clear->color_mask, MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY + MGA_EXEC, - (box->x2 << 16) | box->x1 ); - } + MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); - ADVANCE_DMA(); - } + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_FCOL, clear->clear_color, + MGA_DSTORG, dev_priv->front_offset, + MGA_DWGCTL + MGA_EXEC, + dev_priv->clear_cmd ); - if ( clear->flags & MGA_BACK ) { - BEGIN_DMA( 1 + nbox ); + ADVANCE_DMA(); + } - DMA_BLOCK( MGA_FCOL, clear->clear_color, - MGA_PLNWT, clear->color_mask, - MGA_DSTORG, dev_priv->back_offset, - MGA_DWGCTL, dev_priv->clear_cmd ); - for ( i = 0 ; i < nbox ; i++ ) { - drm_clip_rect_t *box = &pbox[i]; - u32 height = box->y2 - box->y1; + if ( clear->flags & MGA_BACK ) { + BEGIN_DMA( 2 ); DMA_BLOCK( MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, + MGA_PLNWT, clear->color_mask, MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY + MGA_EXEC, - (box->x2 << 16) | box->x1 ); - } - - ADVANCE_DMA(); - } + MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); - if ( clear->flags & MGA_DEPTH ) { - BEGIN_DMA( 1 + nbox ); + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_FCOL, clear->clear_color, + MGA_DSTORG, dev_priv->back_offset, + MGA_DWGCTL + MGA_EXEC, + dev_priv->clear_cmd ); - DMA_BLOCK( MGA_FCOL, clear->clear_depth, - MGA_PLNWT, clear->depth_mask, - MGA_DSTORG, dev_priv->depth_offset, - MGA_DWGCTL, dev_priv->clear_cmd ); + ADVANCE_DMA(); + } - for ( i = 0 ; i < nbox ; i++ ) { - drm_clip_rect_t *box = &pbox[i]; - u32 height = box->y2 - box->y1; + if ( clear->flags & MGA_DEPTH ) { + BEGIN_DMA( 2 ); DMA_BLOCK( MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, + MGA_PLNWT, clear->depth_mask, MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY + MGA_EXEC, - (box->x2 << 16) | box->x1 ); + MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_FCOL, clear->clear_depth, + MGA_DSTORG, dev_priv->depth_offset, + MGA_DWGCTL + MGA_EXEC, + dev_priv->clear_cmd ); + + ADVANCE_DMA(); } - ADVANCE_DMA(); } -#if 0 + BEGIN_DMA( 1 ); + /* Force reset of DWGCTL */ DMA_BLOCK( MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl ); ADVANCE_DMA(); -#endif FLUSH_DMA(); } @@ -608,28 +588,38 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) drm_mga_context_regs_t *ctx = &sarea_priv->context_state; drm_clip_rect_t *pbox = sarea_priv->boxes; int nbox = sarea_priv->nbox; - u32 pitch = dev_priv->front_pitch / dev_priv->fb_cpp; int i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __FUNCTION__ ); + DRM_DEBUG( __FUNCTION__ ":\n" ); DRM_DEBUG( " head = 0x%06x\n", *dev_priv->prim.head ); - BEGIN_DMA( 2 + nbox ); + sarea_priv->last_frame.head = dev_priv->prim.tail; + sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; + + DRM_DEBUG( " tail = 0x%06x\n", dev_priv->prim.tail ); + DRM_DEBUG( " wrap = 0x%06x\n", dev_priv->prim.last_wrap ); - DMA_BLOCK( MGA_MACCESS, dev_priv->maccess, - MGA_SRCORG, dev_priv->back_offset, - MGA_DSTORG, dev_priv->front_offset, - MGA_AR5, pitch ); + BEGIN_DMA( 4 + nbox ); DMA_BLOCK( MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, + MGA_DWGSYNC, 0x00007100, + MGA_DWGSYNC, 0x00007000 ); + + DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset, + MGA_MACCESS, dev_priv->maccess, + MGA_SRCORG, dev_priv->back_offset, + MGA_AR5, dev_priv->front_pitch ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, + MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY ); for ( i = 0 ; i < nbox ; i++ ) { drm_clip_rect_t *box = &pbox[i]; u32 height = box->y2 - box->y1; - u32 start = box->y1 * pitch; + u32 start = box->y1 * dev_priv->front_pitch; DMA_BLOCK( MGA_AR0, start + box->x2 - 1, MGA_AR3, start + box->x1, @@ -637,22 +627,17 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height ); } -#if 0 + DMA_BLOCK( MGA_DMAPAD, 0x00000000, MGA_PLNWT, ctx->plnwt, MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl ); -#endif ADVANCE_DMA(); - sarea_priv->last_frame.head = dev_priv->prim.tail; - sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; - - DRM_DEBUG( " tail = 0x%06x\n", dev_priv->prim.tail ); - DRM_DEBUG( " wrap = 0x%06x\n", dev_priv->prim.last_wrap ); - FLUSH_DMA(); + + DRM_DEBUG( "%s... done.\n", __FUNCTION__ ); } static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) @@ -664,9 +649,7 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) u32 length = (u32) buf->used; int i = 0; DMA_LOCALS; - - DRM_DEBUG( "%s: buf=%d used=%d\n", - __FUNCTION__, buf->idx, buf->used ); + DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used ); if ( buf->used ) { buf_priv->dispatched = 1; @@ -714,8 +697,7 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf, u32 address = (u32) buf->bus_address; int i = 0; DMA_LOCALS; - DRM_INFO( __FUNCTION__ ": buf=%d start=%d end=%d\n", - buf->idx, start, end ); + DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end ); if ( start != end ) { buf_priv->dispatched = 1; @@ -761,6 +743,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_buf_priv_t *buf_priv = buf->dev_private; + drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; u32 y2; DMA_LOCALS; @@ -778,7 +761,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, MGA_AR5, 64 ); DMA_BLOCK( MGA_PITCH, 64, - MGA_DMAPAD, 0x00000000, + MGA_PLNWT, 0xffffffff, MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY ); @@ -787,9 +770,9 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2 ); - DMA_BLOCK( MGA_DMAPAD, 0x00000000, + DMA_BLOCK( MGA_PLNWT, ctx->plnwt, MGA_SRCORG, dev_priv->front_offset, - MGA_PITCH, dev_priv->front_pitch / dev_priv->fb_cpp, + MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000 ); ADVANCE_DMA(); @@ -802,6 +785,66 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, FLUSH_DMA(); } +static void mga_dma_dispatch_blit( drm_device_t *dev, + drm_mga_blit_t *blit ) +{ + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_context_regs_t *ctx = &sarea_priv->context_state; + drm_clip_rect_t *pbox = sarea_priv->boxes; + int nbox = sarea_priv->nbox; + u32 scandir = 0, i; + DMA_LOCALS; + + BEGIN_DMA( 4 + nbox ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DWGSYNC, 0x00007100, + MGA_DWGSYNC, 0x00007000 ); + + DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY, + MGA_PLNWT, blit->planemask, + MGA_SRCORG, blit->srcorg, + MGA_DSTORG, blit->dstorg ); + + DMA_BLOCK( MGA_SGN, scandir, + MGA_MACCESS, dev_priv->maccess, + MGA_AR5, blit->ydir * blit->src_pitch, + MGA_PITCH, blit->dst_pitch ); + + for ( i = 0 ; i < nbox ; i++ ) { + int srcx = pbox[i].x1 + blit->delta_sx; + int srcy = pbox[i].y1 + blit->delta_sy; + int dstx = pbox[i].x1 + blit->delta_dx; + int dsty = pbox[i].y1 + blit->delta_dy; + int h = pbox[i].y2 - pbox[i].y1; + int w = pbox[i].x2 - pbox[i].x1 - 1; + int start; + + if ( blit->ydir == -1 ) { + srcy = blit->height - srcy - 1; + } + + start = srcy * blit->src_pitch + srcx; + + DMA_BLOCK( MGA_AR0, start + w, + MGA_AR3, start, + MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), + MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h ); + } + + /* Do something to flush AGP? + */ + + /* Force reset of DWGCTL */ + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_PLNWT, ctx->plnwt, + MGA_PITCH, dev_priv->front_pitch, + MGA_DWGCTL, ctx->dwgctl ); + + ADVANCE_DMA(); +} /* ================================================================ @@ -911,7 +954,6 @@ int mga_dma_indices( struct inode *inode, struct file *filp, drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_indices_t indices; - DRM_INFO( __FUNCTION__ "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -952,7 +994,7 @@ int mga_dma_iload( struct inode *inode, struct file *filp, drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; drm_mga_iload_t iload; - DRM_INFO( __FUNCTION__ ":\n" ); + DRM_DEBUG( __FUNCTION__ ":\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -984,3 +1026,35 @@ int mga_dma_iload( struct inode *inode, struct file *filp, return 0; } + +int mga_dma_blit( 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_mga_private_t *dev_priv = dev->dev_private; + drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_mga_blit_t blit; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + LOCK_TEST_WITH_RETURN( dev ); + + if ( copy_from_user( &blit, (drm_mga_blit_t *)arg, sizeof(blit) ) ) + return -EFAULT; + + if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; + + if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) ) + return -EINVAL; + + WRAP_TEST_WITH_RETURN( dev_priv ); + + mga_dma_dispatch_blit( dev, &blit ); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; + + return 0; +} |