summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Hughes <gareth@users.sourceforge.net>2001-02-13 03:43:04 +0000
committerGareth Hughes <gareth@users.sourceforge.net>2001-02-13 03:43:04 +0000
commitb093470fc600a1465be9621ed58a68f53f1660f4 (patch)
tree59e74e2871987eb3d71aeb9161770461d724f19e
parent650f48096df93033607952410985ed52878a9469 (diff)
downloaddrm-b093470fc600a1465be9621ed58a68f53f1660f4.tar.gz
Merge (most of) the latest trunk code into the branch.
-rw-r--r--linux-core/mga_drv.c3
-rw-r--r--linux/mga_dma.c50
-rw-r--r--linux/mga_drm.h27
-rw-r--r--linux/mga_drv.c3
-rw-r--r--linux/mga_drv.h10
-rw-r--r--linux/mga_state.c278
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;
+}