summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2000-02-04 07:32:24 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2000-02-04 07:32:24 +0000
commit4db40c2a8b53b1e02e6607fb301a5ca886d461ce (patch)
tree8dd6a9b392ddf609a9e3b76e21e6eb49d833844f
parent484f610fb1abe449968e796a652b5834b6b95bee (diff)
Added code for swapbuffers and clearbuffers.
Added code to emit all driver state, including context, texture and warp states. Added a hack for carrying state along with a dma buffer. Hopefully Jeff will have a better solution for this problem.
-rw-r--r--linux-core/drmP.h14
-rw-r--r--linux-core/mga_drv.c2
-rw-r--r--linux/Makefile.linux4
-rw-r--r--linux/drm.h4
-rw-r--r--linux/drmP.h14
-rw-r--r--linux/mga_clear.c203
-rw-r--r--linux/mga_dma.c202
-rw-r--r--linux/mga_dma.h57
-rw-r--r--linux/mga_drm_public.h217
-rw-r--r--linux/mga_drv.c2
-rw-r--r--linux/mga_drv.h17
-rw-r--r--linux/mga_state.c442
-rw-r--r--shared-core/drm.h4
-rw-r--r--shared/drm.h4
14 files changed, 882 insertions, 304 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 97d2539a..5bbf1bfe 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -260,14 +260,12 @@ typedef struct drm_buf {
DRM_LIST_PRIO = 4,
DRM_LIST_RECLAIM = 5
} list; /* Which list we're on */
-#if 0
- enum {
- TT_GENERAL,
- TT_BLIT,
- TT_VECTOR,
- TT_VERTEX
- } transfer_type;
-#endif
+
+
+ int type; /* push into dev_priv? */
+ void *dev_priv;
+
+
#if DRM_DMA_HISTOGRAM
cycles_t time_queued; /* Queued to kernel DMA queue */
cycles_t time_dispatched; /* Dispatched to hardware */
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index 81c08e81..60cf9b1d 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -259,7 +259,7 @@ static int mga_takedown(drm_device_t *dev)
drm_agp_mem_t *nexte;
/* Remove AGP resources, but leave dev->agp
- intact until r128_cleanup is called. */
+ intact until cleanup is called. */
for (entry = dev->agp->memory; entry; entry = nexte) {
nexte = entry->next;
if (entry->bound) drm_unbind_agp(entry->memory);
diff --git a/linux/Makefile.linux b/linux/Makefile.linux
index c95ec17d..c0ab34ab 100644
--- a/linux/Makefile.linux
+++ b/linux/Makefile.linux
@@ -71,8 +71,8 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
TDFXOBJS= tdfx_drv.o tdfx_context.o
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
-MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o
-MGAHEADERS= mga_drv.h $(DRMHEADERS)
+MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o mga_state.o mga_clear.o
+MGAHEADERS= mga_drv.h mga_drm_public.h $(DRMHEADERS)
R128OBJS= r128_drv.o r128_context.o
R128HEADERS= r128_drv.h $(DRMHEADERS)
diff --git a/linux/drm.h b/linux/drm.h
index 01b2024c..01c5bdc8 100644
--- a/linux/drm.h
+++ b/linux/drm.h
@@ -162,9 +162,11 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
+ _DRM_DMA_TYPE_MASK = 0x0F000000,
+ _DRM_DMA_GENERAL = 0x00000000, /* the default type */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
- _DRM_DMA_BLIT = 0x04000000
+ _DRM_DMA_BLIT = 0x03000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {
diff --git a/linux/drmP.h b/linux/drmP.h
index 97d2539a..5bbf1bfe 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -260,14 +260,12 @@ typedef struct drm_buf {
DRM_LIST_PRIO = 4,
DRM_LIST_RECLAIM = 5
} list; /* Which list we're on */
-#if 0
- enum {
- TT_GENERAL,
- TT_BLIT,
- TT_VECTOR,
- TT_VERTEX
- } transfer_type;
-#endif
+
+
+ int type; /* push into dev_priv? */
+ void *dev_priv;
+
+
#if DRM_DMA_HISTOGRAM
cycles_t time_queued; /* Queued to kernel DMA queue */
cycles_t time_dispatched; /* Dispatched to hardware */
diff --git a/linux/mga_clear.c b/linux/mga_clear.c
new file mode 100644
index 00000000..8dfcac42
--- /dev/null
+++ b/linux/mga_clear.c
@@ -0,0 +1,203 @@
+/* mga_state.c -- State support for mga g200/g400 -*- linux-c -*-
+ *
+ * Created: February 2000 by keithw@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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
+ * PRECISION INSIGHT 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.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@precisioninsight.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "mga_drv.h"
+#include "mgareg_flags.h"
+#include "mga_dma.h"
+
+#define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | \
+ DC_sgnzero_enable | DC_shftzero_enable | \
+ (0xC << DC_bop_SHIFT) | DC_clipdis_enable | \
+ DC_solid_enable | DC_transc_enable)
+
+
+#define MGA_COPY_CMD (DC_opcod_bitblt | DC_atype_rpl | DC_linear_xy | \
+ DC_solid_disable | DC_arzero_disable | \
+ DC_sgnzero_enable | DC_shftzero_enable | \
+ (0xC << DC_bop_SHIFT) | DC_bltmod_bfcol | \
+ DC_pattern_disable | DC_transc_disable | \
+ DC_clipdis_enable) \
+
+
+void mgaClearBuffers( drm_device_t *dev,
+ int clear_color,
+ int clear_depth,
+ int flags )
+{
+ int cmd, i;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ xf86drmClipRectRec *pbox = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ drm_buf_t *buf;
+ drm_dma_t d;
+ int order = 10; /* ??? */
+ DMALOCALS;
+
+
+ if (!nbox)
+ return;
+
+ if ( dev_priv->sgram )
+ cmd = MGA_CLEAR_CMD | DC_atype_blk;
+ else
+ cmd = MGA_CLEAR_CMD | DC_atype_rstr;
+
+ buf = drm_freelist_get(&dma->bufs[order].freelist, _DRM_DMA_WAIT);
+
+
+ DMAGETPTR( buf );
+
+ for (i = 0 ; i < nbox ; i++) {
+ unsigned int height = pbox[i].y2 - pbox[i].y1;
+
+ /* Is it necessary to be this paranoid? I don't think so.
+ if (pbox[i].x1 > dev_priv->width) continue;
+ if (pbox[i].y1 > dev_priv->height) continue;
+ if (pbox[i].x2 > dev_priv->width) continue;
+ if (pbox[i].y2 > dev_priv->height) continue;
+ if (pbox[i].x2 <= pbox[i].x1) continue;
+ if (pbox[i].y2 <= pbox[i].x1) continue;
+ */
+
+ DMAOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
+ DMAOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
+
+ if ( flags & MGA_CLEAR_FRONTBUFFER ) {
+ DMAOUTREG(MGAREG_FCOL, clear_color);
+ DMAOUTREG(MGAREG_DSTORG, dev_priv->frontOrg);
+ DMAOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_CLEAR_BACKBUFFER ) {
+ DMAOUTREG(MGAREG_FCOL, clear_color);
+ DMAOUTREG(MGAREG_DSTORG, dev_priv->backOrg);
+ DMAOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_CLEAR_DEPTHBUFFER )
+ {
+ DMAOUTREG(MGAREG_FCOL, clear_depth);
+ DMAOUTREG(MGAREG_DSTORG, dev_priv->depthOrg);
+ DMAOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+ }
+
+ DMAADVANCE( buf );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
+
+ d.context = DRM_KERNEL_CONTEXT;
+ d.send_count = 1;
+ d.send_indices = &buf->idx;
+ d.send_sizes = &buf->used;
+ d.flags = _DRM_DMA_GENERAL;
+ d.request_count = 0;
+ d.request_size = 0;
+ d.request_indices = NULL;
+ d.request_sizes = NULL;
+ d.granted_count = 0;
+
+ drm_dma_enqueue(dev, &d);
+}
+
+
+void mgaSwapBuffers( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ xf86drmClipRectRec *pbox = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ drm_buf_t *buf;
+ drm_dma_t d;
+ int order = 10; /* ??? */
+ int i;
+ DMALOCALS;
+
+ if (!nbox)
+ return;
+
+ buf = drm_freelist_get(&dma->bufs[order].freelist, _DRM_DMA_WAIT);
+
+ DMAGETPTR( buf );
+
+ DMAOUTREG(MGAREG_DSTORG, dev_priv->frontOrg);
+ DMAOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
+ DMAOUTREG(MGAREG_SRCORG, dev_priv->backOrg);
+ DMAOUTREG(MGAREG_AR5, dev_priv->stride); /* unnecessary? */
+ DMAOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
+
+ for (i = 0 ; i < nbox; i++) {
+ unsigned int h = pbox[i].y2 - pbox[i].y1;
+ unsigned int start = pbox[i].y1 * dev_priv->stride;
+
+ /*
+ if (pbox[i].x1 > dev_priv->width) continue;
+ if (pbox[i].y1 > dev_priv->height) continue;
+ if (pbox[i].x2 > dev_priv->width) continue;
+ if (pbox[i].y2 > dev_priv->height) continue;
+ if (pbox[i].x2 <= pbox[i].x1) continue;
+ if (pbox[i].y2 <= pbox[i].x1) continue;
+ */
+
+ DMAOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
+ DMAOUTREG(MGAREG_AR3, start + pbox[i].x1);
+ DMAOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16));
+ DMAOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h);
+ }
+
+ DMAOUTREG(MGAREG_SRCORG, 0);
+ DMAADVANCE( buf );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
+
+ d.context = DRM_KERNEL_CONTEXT;
+ d.send_count = 1;
+ d.send_indices = &buf->idx;
+ d.send_sizes = &buf->used;
+ d.flags = _DRM_DMA_GENERAL;
+ d.request_count = 0;
+ d.request_size = 0;
+ d.request_indices = NULL;
+ d.request_sizes = NULL;
+ d.granted_count = 0;
+
+ drm_dma_enqueue(dev, &d);
+}
+
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index 2c4856ed..e7ac0406 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -34,6 +34,7 @@
#include "drmP.h"
#include "mga_drv.h"
#include "mgareg_flags.h"
+#include "mga_dma.h"
#include <linux/interrupt.h> /* For task queue support */
@@ -45,31 +46,23 @@
#define MGA_READ(reg) MGA_DEREF(reg)
#define MGA_WRITE(reg,val) do { MGA_DEREF(reg) = val; } while (0)
-#define DWGREG0 0x1c00
-#define DWGREG0_END 0x1dff
-#define DWGREG1 0x2c00
-#define DWGREG1_END 0x2dff
-#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END)
-#define ADRINDEX0(r) (u8)((r - DWGREG0) >> 2)
-#define ADRINDEX1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
-#define ADRINDEX(r) (ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
-#define DMALOCALS() u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
+#define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
int outcount, num_dwords; unsigned long flags
-#define DMAGETPTR() do { \
+#define PRIMGETPTR() do { \
dma_ptr = dev_priv->current_dma_ptr; \
phys_head = dev_priv->prim_phys_head; \
outcount = 0; \
num_dwords = dev_priv->prim_num_dwords; \
} while(0)
-#define DMAADVANCE() do { \
+#define PRIMADVANCE() do { \
dev_priv->prim_num_dwords = num_dwords; \
dev_priv->current_dma_ptr = dma_ptr; \
} while(0);
-#define DMAOUTREG(reg, val) do { \
+#define PRIMOUTREG(reg, val) do { \
tempIndex[outcount]=ADRINDEX(reg); \
dma_ptr[1+outcount] = val; \
if( ++outcount == 4) { \
@@ -80,7 +73,7 @@ num_dwords += 5; \
} \
}while (0)
-#define CHECK_OVERFLOW(length) do { \
+#define PRIM_CHECK_OVERFLOW(length) do { \
if((dev_priv->prim_max_dwords - dev_priv->prim_num_dwords) < \
length) { \
mga_prim_overflow(dev); \
@@ -89,9 +82,6 @@ if((dev_priv->prim_max_dwords - dev_priv->prim_num_dwords) < \
#define PDEA_pagpxfer_enable 0x2
#define MGA_SYNC_TAG 0x423f4200
-#define MGA_YDSTLEN(y,LEN) DMAOUTREG(MGAREG_YDSTLEN,((y) << 16) | (LEN))
-#define MGA_FXBNDRY(x1,x2) DMAOUTREG(MGAREG_FXBNDRY,((x2) << 16) | (x1))
-#define MGA_DWGCTL_EXEC(x) DMAOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC,x)
typedef enum {
TT_GENERAL,
@@ -122,7 +112,7 @@ int mga_dma_cleanup(drm_device_t *dev)
int temp;
if(dev_priv->ioremap) {
- temp = dev_priv->warp_mc_size + dev_priv->primary_size;
+ temp = dev_priv->warp_ucode_size + dev_priv->primary_size;
temp = ((temp + PAGE_SIZE - 1) /
PAGE_SIZE) * PAGE_SIZE;
drm_ioremapfree((void *) dev_priv->ioremap, temp);
@@ -160,8 +150,8 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_private_t *dev_priv,
/* Scale primary size to the next page */
dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
PAGE_SIZE) * PAGE_SIZE;
- dev_priv->warp_mc_size = init->warp_mc_size;
- dev_priv->type = init->type;
+ dev_priv->warp_ucode_size = init->warp_ucode_size;
+ dev_priv->chipset = init->chipset;
dev_priv->fbOffset = init->fbOffset;
dev_priv->backOffset = init->backOffset;
dev_priv->depthOffset = init->depthOffset;
@@ -177,7 +167,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_private_t *dev_priv,
printk("memcpy done\n");
prim_map = dev->maplist[init->reserved_map_idx];
dev_priv->prim_phys_head = dev->agp->base + init->reserved_map_agpstart;
- temp = init->warp_mc_size + dev_priv->primary_size;
+ temp = init->warp_ucode_size + dev_priv->primary_size;
temp = ((temp + PAGE_SIZE - 1) /
PAGE_SIZE) * PAGE_SIZE;
printk("temp : %x\n", temp);
@@ -199,14 +189,14 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_private_t *dev_priv,
printk("dma initialization\n");
/* Private is now filled in, initialize the hardware */
{
- DMALOCALS();
+ PRIMLOCALS;
mga_prim_overflow(dev);
- DMAGETPTR();
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DWGSYNC, 0);
- DMAOUTREG(MGAREG_SOFTRAP, 0);
- DMAADVANCE();
+ PRIMGETPTR();
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0);
+ PRIMOUTREG(MGAREG_SOFTRAP, 0);
+ PRIMADVANCE();
/* Poll for the first buffer to insure that
* the status register will be correct
@@ -258,52 +248,55 @@ int mga_dma_init(struct inode *inode, struct file *filp,
return retcode;
}
-static void mga_dma_dispatch(drm_device_t *dev, unsigned long address,
- unsigned long length)
+
+#define MGA_ILOAD_CMD (DC_opcod_iload | DC_atype_rpl | \
+ DC_linear_linear | DC_bltmod_bfcol | \
+ (0xC << DC_bop_SHIFT) | DC_sgnzero_enable | \
+ DC_shftzero_enable | DC_clipdis_enable)
+
+
+static void mga_dma_dispatch_iload(drm_device_t *dev, unsigned long address,
+ unsigned long length)
{
drm_mga_private_t *dev_priv = dev->dev_private;
int use_agp = PDEA_pagpxfer_enable;
static int j = 0;
static int k = 0;
int cmd;
- DMALOCALS();
-
- CHECK_OVERFLOW(20);
- DMAGETPTR();
- cmd = DC_opcod_iload | /* image load */
- DC_atype_rpl | /* raster replace mode */
- DC_linear_linear | /* linear source */
- DC_bltmod_bfcol | /* source data is pre-formatted color */
- (0xC << DC_bop_SHIFT) | /* use source bit op */
- DC_sgnzero_enable | /* normal scanning direction */
- DC_shftzero_enable | /* required for iload */
- DC_clipdis_enable; /* don't use the clip rect */
-
- MGA_YDSTLEN( k, 512 ); /* top to bottom */
- MGA_FXBNDRY( j, 511+j ); /* full width */
- DMAOUTREG( MGAREG_AR0, 512 * /* source pixel count */
- 512 - 1);
- DMAOUTREG( MGAREG_AR3, 0 ); /* required */
- DMAOUTREG( MGAREG_DMAPAD, 0);
- DMAOUTREG( MGAREG_DMAPAD, 0);
- DMAOUTREG( MGAREG_DMAPAD, 0);
- MGA_DWGCTL_EXEC(cmd);
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_SECADDRESS, address | TT_BLIT);
- DMAOUTREG(MGAREG_SECEND, (address + length) | use_agp);
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DWGSYNC, 0);
- DMAOUTREG(MGAREG_SOFTRAP, 0);
- DMAADVANCE();
+ int y,h,x1,x2;
+ PRIMLOCALS;
+
+ PRIM_CHECK_OVERFLOW(20);
+ PRIMGETPTR();
+
+ y = k;
+ h = 512;
+ PRIMOUTREG( MGAREG_YDSTLEN,((y) << 16) | (h));
+
+ x2 = j + 511;
+ x1 = j;
+ PRIMOUTREG( MGAREG_FXBNDRY,((x2) << 16) | (x1));
+
+ PRIMOUTREG( MGAREG_AR0, 512 * 512 - 1);
+ PRIMOUTREG( MGAREG_AR3, 0 );
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SECADDRESS, address | TT_BLIT);
+ PRIMOUTREG( MGAREG_SECEND, (address + length) | use_agp);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, 0);
+ PRIMOUTREG( MGAREG_SOFTRAP, 0);
+ PRIMADVANCE();
MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
- MGA_WRITE(MGAREG_PRIMEND, (phys_head +
- (num_dwords*sizeof(unsigned long))) |
- use_agp);
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
k += 20;
j += 5;
@@ -311,6 +304,66 @@ static void mga_dma_dispatch(drm_device_t *dev, unsigned long address,
if( k < 512) k = 0;
}
+
+static void mga_dma_dispatch_vertex(drm_device_t *dev, unsigned long address,
+ unsigned long length)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ int use_agp = PDEA_pagpxfer_enable;
+ PRIMLOCALS;
+
+ PRIM_CHECK_OVERFLOW(20);
+ PRIMGETPTR();
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SECADDRESS, address | TT_VERTEX);
+ PRIMOUTREG( MGAREG_SECEND, (address + length) | use_agp);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, 0);
+ PRIMOUTREG( MGAREG_SOFTRAP, 0);
+ PRIMADVANCE();
+
+ MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
+ while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
+
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+}
+
+
+/* Used internally for the small buffers generated from client state
+ * information.
+ */
+static void mga_dma_dispatch_general(drm_device_t *dev, unsigned long address,
+ unsigned long length)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ int use_agp = PDEA_pagpxfer_enable;
+ PRIMLOCALS;
+
+ PRIM_CHECK_OVERFLOW(20);
+ PRIMGETPTR();
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SECADDRESS, address | TT_VERTEX);
+ PRIMOUTREG( MGAREG_SECEND, (address + length) | use_agp);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, 0);
+ PRIMOUTREG( MGAREG_SOFTRAP, 0);
+ PRIMADVANCE();
+
+ MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
+ while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
+
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+}
+
+
/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
@@ -406,7 +459,6 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
/* Only called by mga_dma_schedule. */
static int mga_do_dma(drm_device_t *dev, int locked)
{
-
unsigned long address;
unsigned long length;
drm_buf_t *buf;
@@ -503,7 +555,27 @@ static int mga_do_dma(drm_device_t *dev, int locked)
buf->time_dispatched = get_cycles();
#endif
- mga_dma_dispatch(dev, address, length);
+
+ switch (buf->type & _DRM_DMA_TYPE_MASK) {
+ case _DRM_DMA_GENERAL:
+ mga_dma_dispatch_general(dev, address, length);
+ break;
+ case _DRM_DMA_VERTEX:
+ mga_dma_dispatch_vertex(dev, address, length);
+ break;
+/* case _DRM_DMA_SETUP: */
+/* mga_dma_dispatch_setup(dev, address, length); */
+/* break; */
+ case _DRM_DMA_BLIT:
+ mga_dma_dispatch_iload(dev, address, length);
+ break;
+ default:
+ printk("bad buffer type %x in dispatch\n",
+ buf->type & _DRM_DMA_TYPE_MASK);
+ /* panic? */
+ break;
+ }
+
drm_free_buffer(dev, dma->this_buffer);
dma->this_buffer = buf;
diff --git a/linux/mga_dma.h b/linux/mga_dma.h
new file mode 100644
index 00000000..6d6d988c
--- /dev/null
+++ b/linux/mga_dma.h
@@ -0,0 +1,57 @@
+#ifndef MGA_DMA_H
+#define MGA_DMA_H
+
+
+#define DWGREG0 0x1c00
+#define DWGREG0_END 0x1dff
+#define DWGREG1 0x2c00
+#define DWGREG1_END 0x2dff
+
+#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END)
+#define ADRINDEX0(r) (u8)((r - DWGREG0) >> 2)
+#define ADRINDEX1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
+#define ADRINDEX(r) (ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
+
+
+/* Macros for inserting commands into a secondary dma buffer.
+ */
+
+#define DMALOCALS u8 tempIndex[4]; u32 *dma_ptr; \
+ int outcount, num_dwords;
+
+#define DMAGETPTR(buf) do { \
+ dma_ptr = (u32 *)((u8 *)buf->address + buf->used); \
+ outcount = 0; \
+ num_dwords = buf->used / 4; \
+} while(0)
+
+#define DMAADVANCE(buf) do { \
+ buf->used = num_dwords * 4; \
+} while(0)
+
+#define DMAOUTREG(reg, val) do { \
+ tempIndex[outcount]=ADRINDEX(reg); \
+ dma_ptr[++outcount] = val; \
+ if (outcount == 4) { \
+ outcount = 0; \
+ dma_ptr[0] = *(u32 *)tempIndex; \
+ dma_ptr+=5; \
+ num_dwords += 5; \
+ } \
+}while (0)
+
+/* Not used for emitting state, as we assume the state will always fit
+ * in a single buffer.
+ *
+ * For clip/swap -- choose a maximum number of cliprects so that a single
+ * buffer is always sufficient?
+ *
+ * For vertex cliprects -- ???
+ */
+#define CHECK_OVERFLOW(length) do { \
+ if (buf->total - buf->used < length * 4) \
+ mga_prim_overflow(dev); \
+}while(0)
+
+
+#endif
diff --git a/linux/mga_drm_public.h b/linux/mga_drm_public.h
index 8c066dd6..20c033c3 100644
--- a/linux/mga_drm_public.h
+++ b/linux/mga_drm_public.h
@@ -23,7 +23,8 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
- * Author: Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Keith Whitwell <keithw@precisioninsight.com>
*
* $XFree86$
*/
@@ -31,34 +32,38 @@
#ifndef _MGA_DRM_PUBLIC_H_
#define _MGA_DRM_PUBLIC_H_
-/* These defines must match the Xserver code */
+#define MGA_A 0x1 /* alpha */
+#define MGA_F 0x2 /* fog */
+#define MGA_S 0x4 /* specular */
+#define MGA_T2 0x8 /* multitexture */
+
#define MGA_WARP_TGZ 0
-#define MGA_WARP_TGZA 1
-#define MGA_WARP_TGZAF 2
-#define MGA_WARP_TGZF 3
-#define MGA_WARP_TGZS 4
-#define MGA_WARP_TGZSA 5
-#define MGA_WARP_TGZSAF 6
-#define MGA_WARP_TGZSF 7
-#define MGA_WARP_T2GZ 8
-#define MGA_WARP_T2GZA 9
-#define MGA_WARP_T2GZAF 10
-#define MGA_WARP_T2GZF 11
-#define MGA_WARP_T2GZS 12
-#define MGA_WARP_T2GZSA 13
-#define MGA_WARP_T2GZSAF 14
-#define MGA_WARP_T2GZSF 15
-
-#define MGA_MAX_WARP_PIPES 16
+#define MGA_WARP_TGZA (MGA_A)
+#define MGA_WARP_TGZF (MGA_F)
+#define MGA_WARP_TGZFA (MGA_F|MGA_A)
+#define MGA_WARP_TGZS (MGA_S)
+#define MGA_WARP_TGZSA (MGA_S|MGA_A)
+#define MGA_WARP_TGZSF (MGA_S|MGA_F)
+#define MGA_WARP_TGZSFA (MGA_S|MGA_F|MGA_A)
+#define MGA_WARP_T2GZ (MGA_T2)
+#define MGA_WARP_T2GZA (MGA_T2|MGA_A)
+#define MGA_WARP_T2GZF (MGA_T2|MGA_F)
+#define MGA_WARP_T2GZFA (MGA_T2|MGA_A|MGA_F)
+#define MGA_WARP_T2GZS (MGA_T2|MGA_S)
+#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
+#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F)
+#define MGA_WARP_T2GZSFA (MGA_T2|MGA_S|MGA_F|MGA_A)
+
+
+#define MGA_MAX_G400_PIPES 16
+#define MGA_MAX_G200_PIPES 8 /* no multitex */
+
+
+#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
#define MGA_CARD_TYPE_G200 1
#define MGA_CARD_TYPE_G400 2
-/* Bogus values */
-
-#define MGA_X_SETUP_SIZE 16
-#define MGA_SETUP_SIZE 16
-#define MGA_TEX_SETUP_SIZE 16
typedef struct _drm_mga_warp_index {
int installed;
@@ -76,8 +81,7 @@ typedef struct drm_mga_init {
int buffer_map_idx;
int sarea_priv_offset;
int primary_size;
- int warp_mc_size;
- int type;
+ int warp_ucode_size;
int fbOffset;
int backOffset;
int depthOffset;
@@ -86,9 +90,13 @@ typedef struct drm_mga_init {
int cpp;
int stride;
int sgram;
+ int chipset;
mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
} drm_mga_init_t;
+
+
+
typedef struct _xf86drmClipRectRec {
unsigned short x1;
unsigned short y1;
@@ -96,65 +104,118 @@ typedef struct _xf86drmClipRectRec {
unsigned short y2;
} xf86drmClipRectRec;
-#define _MGA_2D_DIRTY 0
-/* These aren't finals, its just what the Xserver uses */
-#define _MGA_SETUP_PITCH 0
-#define _MGA_SETUP_CXBNDRY 1
-#define _MGA_SETUP_YTOP 2
-#define _MGA_SETUP_YBOT 3
-#define _MGA_SETUP_DSTORG 4
-#define _MGA_SETUP_MACCESS 5
-#define _MGA_SETUP_PLNWT 6
-#define _MGA_SETUP_ZORG 7
-#define _MGA_SETUP_YDSTLEN 8
-#define _MGA_SETUP_YDSTORG 9
-#define _MGA_SETUP_FXBNDRY 10
-#define _MGA_SETUP_SRCORG 11
-#define _MGA_SETUP_DSTORG 12
-#define _MGA_SETUP_SGN 13
-#define _MGA_SETUP_AR0 14
-#define _MGA_SETUP_AR1 15
-#define _MGA_SETUP_AR2 16
-#define _MGA_SETUP_AR3 17
-#define _MGA_SETUP_AR4 18
-#define _MGA_SETUP_AR5 19
-#define _MGA_SETUP_AR6 20
-#define _MGA_SETUP_CXRIGHT 21
-#define _MGA_SETUP_DWGCTL 22
-#define _MGA_SETUP_XYEND 23
-#define _MGA_SETUP_XYSTRT 24
-#define _MGA_SETUP_FCOL 25
-#define _MGA_SETUP_BCOL 26
-#define _MGA_SETUP_PAT0 27
-#define _MGA_SETUP_PAT1 28
-#define _MGA_SETUP_SHIFT 29
-#define _MGA_SETUP_SRC0 30
-#define _MGA_SETUP_SRC1 31
-#define _MGA_SETUP_SRC2 32
-#define _MGA_SETUP_SRC3 33
-#define _MGA_SETUP_OPMODE 34
-#define _MGA_SETUP_WIADDR2 35
-#define _MGA_SETUP_WGETMSB 36
-#define _MGA_SETUP_WVRTXSZ 37
-#define _MGA_SETUP_WACCEPTSEQ 38
-#define _MGA_SETUP_WIADDR 39
-#define _MGA_SETUP_WMISC 40
+#define MGA_CLEAR_FRONTBUFFER 0x1
+#define MGA_CLEAR_BACKBUFFER 0x2
+#define MGA_CLEAR_DEPTHBUFFER 0x4
+
+typedef struct drm_mga_clear {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drm_mga_clear_t;
+
+typedef struct drm_mga_swap {
+ int flags; /* not actually used? */
+} drm_mga_swap_t;
+
+
+
+/* These were context regs, but are constant under the DRI:
+ */
+#define MGA_CONST_PITCH 0 /* constant */
+#define MGA_CONST_ZORG 7 /* constant */
+
+/* Each context has a state:
+ */
+#define MGA_CTXREG_DSTORG 0 /* top of either front or backbuffer */
+#define MGA_CTXREG_MACCESS 1 /* constant -- except for fog enable */
+#define MGA_CTXREG_PLNWT 2 /* */
+#define MGA_CTXREG_DWGCTL 3
+#define MGA_CTXREG_ALPHACTRL 4
+#define MGA_CTXREG_FOGCOLOR 5
+#define MGA_CTXREG_WFLAG 6
+#define MGA_CTXREG_TDUAL0 7
+#define MGA_CTXREG_TDUAL1 8
+#define MGA_CTX_SETUP_SIZE 9
+
+/* Clipper registers - these #defines aren't used.
+ */
+#define MGA_CLIPREG_CXBNDRY 0
+#define MGA_CLIPREG_YTOP 1
+#define MGA_CLIPREG_YBOT 2
+
+/* Do we restore the server state ourselves, or let the X server do
+ * it after contention? The contended case seems hard to find
+ * in WakeupHandler.
+ *
+ * We need to at least *know* the X server state in order to emit
+ * swapbuffers and clear-front-buffer requests.
+ *
+ * This state is *constant*:
+ */
+#define MGA_2DREG_YDSTORG 0
+#define MGA_2DREG_MACCESS 1
+#define MGA_2DREG_PITCH 2
+#define MGA_2DREG_DSTORG 3
+#define MGA_2DREG_DWGCTL 4
+#define MGA_2DREG_CXBNDRY 5
+#define MGA_2DREG_YTOP 6
+#define MGA_2DREG_YBOT 7
+#define MGA_2DREG_PLNWT 8 /* write mask -- must be restored */
+#define MGA_2D_SETUP_SIZE 9
+
+
+/* Each texture unit has a state:
+ */
+#define MGA_TEXREG_CTL 0
+#define MGA_TEXREG_CTL2 1
+#define MGA_TEXREG_FILTER 2
+#define MGA_TEXREG_BORDERCOL 3
+#define MGA_TEXREG_ORG 4 /* insecure -- validate? */
+#define MGA_TEXREG_ORG1 5
+#define MGA_TEXREG_ORG2 6
+#define MGA_TEXREG_ORG3 7
+#define MGA_TEXREG_ORG4 8
+#define MGA_TEXREG_WIDTH 9
+#define MGA_TEXREG_HEIGHT 10
+#define MGA_TEX_SETUP_SIZE 11
+
+
+/* Keep this small for testing
+ */
+#define MGA_NR_SAREA_CLIPRECTS 2
+
+
+/* Not useful?
+ */
+#define MGASAREA_NEW_CONTEXT 0x1
+#define MGASAREA_NEW_TEX0 0x2
+#define MGASAREA_NEW_TEX1 0x4
+#define MGASAREA_NEW_PIPE 0x8
+#define MGASAREA_NEW_2D_CONTEXT 0x10 /* does it ever happen? */
typedef struct _drm_mga_sarea {
- int CtxOwner;
+ unsigned int ServerState[MGA_2D_SETUP_SIZE];
+ unsigned int ContextState[MGA_CTX_SETUP_SIZE];
+ unsigned int Tex0State[MGA_TEX_SETUP_SIZE];
+ unsigned int Tex1State[MGA_TEX_SETUP_SIZE];
+ unsigned int WarpPipe;
+ unsigned int dirty;
+
+ unsigned int nbox;
+ xf86drmClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS];
+
+ int CtxOwner; /* kernel doesn't touch from here down */
int TexOwner;
- unsigned long ServerState[MGA_X_SETUP_SIZE];
- unsigned long ContextState[MGA_SETUP_SIZE];
- unsigned long Tex0State[MGA_TEX_SETUP_SIZE];
- unsigned long Tex1State[MGA_TEX_SETUP_SIZE];
- int WarpPipe;
- unsigned long NewState;
- int nbox;
- xf86drmClipRectRec boxes[256];
} drm_mga_sarea_t;
+
+
+
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
+#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x40, drm_mga_swap_t)
+#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x40, drm_mga_clear_t)
#endif
diff --git a/linux/mga_drv.c b/linux/mga_drv.c
index 81c08e81..60cf9b1d 100644
--- a/linux/mga_drv.c
+++ b/linux/mga_drv.c
@@ -259,7 +259,7 @@ static int mga_takedown(drm_device_t *dev)
drm_agp_mem_t *nexte;
/* Remove AGP resources, but leave dev->agp
- intact until r128_cleanup is called. */
+ intact until cleanup is called. */
for (entry = dev->agp->memory; entry; entry = nexte) {
nexte = entry->next;
if (entry->bound) drm_unbind_agp(entry->memory);
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index 5cf61883..0491ed92 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -38,8 +38,8 @@ typedef struct _drm_mga_private {
int buffer_map_idx;
drm_mga_sarea_t *sarea_priv;
int primary_size;
- int warp_mc_size;
- int type;
+ int warp_ucode_size;
+ int chipset;
int fbOffset;
int backOffset;
int depthOffset;
@@ -48,7 +48,8 @@ typedef struct _drm_mga_private {
int cpp;
int stride;
int sgram;
- mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
+ int use_agp;
+ mgaWarpIndex WarpIndex[MGA_MAX_G400_PIPES];
__volatile__ unsigned long softrap_age;
atomic_t dispatch_lock;
void *ioremap;
@@ -57,6 +58,15 @@ typedef struct _drm_mga_private {
u32 prim_phys_head;
int prim_num_dwords;
int prim_max_dwords;
+
+
+ /* Some validated register values:
+ */
+ u32 frontOrg;
+ u32 backOrg;
+ u32 depthOrg;
+ u32 mAccess;
+
} drm_mga_private_t;
/* mga_drv.c */
@@ -197,6 +207,7 @@ extern int mga_addmap(struct inode *inode, struct file *filp,
#define MGAREG_STATUS 0x1e14
#define MGAREG_STENCIL 0x2cc8
#define MGAREG_STENCILCTL 0x2ccc
+#define MGAREG_TDUALSTAGE0 0x2cf8
#define MGAREG_TDUALSTAGE1 0x2cfc
#define MGAREG_TEST0 0x1e48
#define MGAREG_TEXBORDERCOL 0x2c5c
diff --git a/linux/mga_state.c b/linux/mga_state.c
index 1a1ed4fc..f52f054c 100644
--- a/linux/mga_state.c
+++ b/linux/mga_state.c
@@ -34,176 +34,348 @@
#include "drmP.h"
#include "mga_drv.h"
#include "mgareg_flags.h"
+#include "mga_dma.h"
+#include "drm.h"
-void mga2drefresh(drm_device_t *dev)
+#if 0
+/* How does this work???
+ */
+int mgaEmitClipRect(drm_device_t *dev, xf86drmClipRectRec *box)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
+
+ /* The G400 seems to have an issue with the second WARP not
+ * stalling clipper register writes. This bothers me, but the only
+ * way I could get it to never clip the last triangle under any
+ * circumstances is by inserting TWO dwgsync commands.
+ */
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+ DMAOUTREG( MGAREG_DWGSYNC, 0 );
+ DMAOUTREG( MGAREG_DWGSYNC, 0 );
+ }
+
+ DMAOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) );
+ DMAOUTREG( MGAREG_YTOP, box->y1 * dev_priv->pitch );
+ DMAOUTREG( MGAREG_YBOT, box->y2 * dev_priv->pitch );
+ DMAADVANCE();
+ return 0;
+}
+#endif
+
+
+static int mgaEmitContext(drm_device_t *dev, drm_buf_t *buf)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
+ DMALOCALS;
+
+ /* Disallow all write destinations except the front and backbuffer.
+ */
+ if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOrg &&
+ regs[MGA_CTXREG_DSTORG] != dev_priv->backOrg)
+ return -1;
+
+ DMAGETPTR( buf );
+ DMAOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] );
+ DMAOUTREG( MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS] );
+ DMAOUTREG( MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT] );
+ DMAOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
+ DMAOUTREG( MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL] );
+ DMAOUTREG( MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR] );
+ DMAOUTREG( MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG] );
+
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+ DMAOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] );
+ DMAOUTREG( MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0] );
+ DMAOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] );
+ }
+ DMAADVANCE( buf );
+ return 0;
}
-void mgaContextRefresh(drm_device_t *dev)
+/* The texture state routines are quite similar, but are a real mess
+ * when integrated into a single function.
+ */
+static int mgaG200EmitTex(drm_device_t *dev, drm_buf_t *buf)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->Tex0State;
+
+ DMALOCALS;
+
+ /* Disallow texture reads from PCI space.
+ */
+ if ((regs[MGA_TEXREG_ORG] & 0x3) == 0x1)
+ return -1;
+
+ DMAGETPTR( buf );
+ DMAOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+ DMAOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ DMAOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ DMAOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
+ DMAOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ DMAOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ DMAOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ DMAOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+ DMAOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ DMAOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ DMAOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ DMAOUTREG(0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] );
+ DMAOUTREG(0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] );
+
+ DMAADVANCE( buf );
+
+ return 0;
}
-void mgaTex0Refresh(drm_device_t *dev)
+static int mgaG400EmitTex0( drm_device_t *dev, drm_buf_t *buf )
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->Tex0State;
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
+
+ DMALOCALS;
+ DMAGETPTR( buf );
+
+ /* Disallow texture reads from PCI space.
+ */
+ if ((regs[MGA_TEXREG_ORG] & 0x3) == 0x1)
+ return -1;
+
+ DMAOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+ DMAOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ DMAOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ DMAOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
+ DMAOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ DMAOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ DMAOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ DMAOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+ DMAOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ DMAOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ DMAOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ DMAOUTREG(0x2d00 + 49*4, 0);
+ DMAOUTREG(0x2d00 + 57*4, 0);
+ DMAOUTREG(0x2d00 + 53*4, 0);
+ DMAOUTREG(0x2d00 + 61*4, 0);
+
+ if (!multitex) {
+ DMAOUTREG(0x2d00 + 52*4, 0x40 );
+ DMAOUTREG(0x2d00 + 60*4, 0x40 );
+ }
+
+ DMAOUTREG(0x2d00 + 54*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
+ DMAOUTREG(0x2d00 + 62*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+
+ DMAADVANCE( buf );
+ return 0;
}
-void mgaTex1Refresh(drm_device_t *dev)
+#define TMC_map1_enable 0x80000000
+
+
+static int mgaG400EmitTex1( drm_device_t *dev, drm_buf_t *buf )
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->Tex1State;
+
+ DMALOCALS;
+ DMAGETPTR(buf);
+
+ /* Disallow texture reads from PCI space.
+ */
+ if ((regs[MGA_TEXREG_ORG] & 0x3) == 0x1)
+ return -1;
+
+ DMAOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable);
+ DMAOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
+ DMAOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
+ DMAOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
+ DMAOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
+ DMAOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
+ DMAOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
+ DMAOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
+ DMAOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );
+ DMAOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
+ DMAOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );
+ DMAOUTREG(0x2d00 + 49*4, 0);
+ DMAOUTREG(0x2d00 + 57*4, 0);
+ DMAOUTREG(0x2d00 + 53*4, 0);
+ DMAOUTREG(0x2d00 + 61*4, 0);
+
+ DMAOUTREG(0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
+ DMAOUTREG(0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
+
+ DMAOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
+
+ DMAADVANCE( buf );
+ return 0;
}
+
+
/* WIADDR might not work in sec bufs, might need to use
* the primary buffer
*/
-int mgaG400SwitchPipe(drm_device_t *dev, void *code)
+static int mgaG400EmitPipe(drm_device_t *dev, drm_buf_t *buf)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- drm_device_dma_t *dma = dev->dma;
- drm_dma_t d;
- drm_buf_t *buf;
- float fParam = 12800.0f;
- DMALOCALS();
-
- buf = drm_freelist_get(&dma->bufs[order].freelist,_DRM_DMA_WAIT);
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->WarpPipe;
+ float fParam = 12800.0f;
+ DMALOCALS;
- /* This needs to get a buffer to fill */
-
- DMAGETPTR(buf);
- DMAOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
+
+ if (pipe > MGA_MAX_G400_PIPES)
+ return -1;
+
+ DMAGETPTR(buf);
+ DMAOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
- if (sarea_priv->WarpPipe >= 8) {
- DMAOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
- DMAOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
- } else {
- DMAOUTREG(MGAREG_WVRTXSZ, 0x00001807);
- DMAOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
- }
+ /* Establish vertex size.
+ */
+ if (pipe & MGA_T2) {
+ DMAOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
+ DMAOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
+ } else {
+ DMAOUTREG(MGAREG_WVRTXSZ, 0x00001807);
+ DMAOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
+ }
- DMAOUTREG(MGAREG_WFLAG, 0);
- DMAOUTREG(MGAREG_WFLAG1, 0);
+ DMAOUTREG(MGAREG_WFLAG, 0);
+ DMAOUTREG(MGAREG_WFLAG1, 0);
- DMAOUTREG(0x2d00 + 56*4, *((mgaUI32 *)(&fParam)));
- DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DMAPAD, 0);
+ DMAOUTREG(0x2d00 + 56*4, *((u32 *)(&fParam)));
+ DMAOUTREG(MGAREG_DMAPAD, 0);
+ DMAOUTREG(MGAREG_DMAPAD, 0);
- /* Perhaps only the registers for the Tex Stage 1 should
- * be set on the microcode that does multitex, however it
- * makes no difference :(
- */
- DMAOUTREG(0x2d00 + 49*4, 0); /* Tex stage 0 */
- DMAOUTREG(0x2d00 + 57*4, 0); /* Tex stage 0 */
- DMAOUTREG(0x2d00 + 53*4, 0); /* Tex stage 1 */
- DMAOUTREG(0x2d00 + 61*4, 0); /* Tex stage 1 */
+ DMAOUTREG(0x2d00 + 49*4, 0); /* Tex stage 0 */
+ DMAOUTREG(0x2d00 + 57*4, 0); /* Tex stage 0 */
+ DMAOUTREG(0x2d00 + 53*4, 0); /* Tex stage 1 */
+ DMAOUTREG(0x2d00 + 61*4, 0); /* Tex stage 1 */
- DMAOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */
- DMAOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */
- DMAOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */
- DMAOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */
+ DMAOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */
+ DMAOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */
+ DMAOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */
+ DMAOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */
- /* Attention! dma pading required due to hw bug (see specs) */
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_WIADDR2,(unsigned long)(code) | WIA_wmode_start |
- WIA_wagp_agp);
- DMAADVANCE(buf);
- d.context = DRM_KERNEL_CONTEXT;
- d.send_count = 1;
- d.send_indices = &buf->idx;
- d.send_sizes = &buf->used;
- d.flags = _DRM_DMA_GENERAL;
- d.request_count = 0;
- d.request_size = 0;
- d.request_indices = NULL;
- d.request_sizes = NULL;
- d.granted_count = 0;
- drm_dma_enqueue(dev, &d);
- return 0;
+ /* Dma pading required due to hw bug */
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_WIADDR2, (dev_priv->WarpIndex[pipe].phys_addr |
+ WIA_wmode_start | WIA_wagp_agp));
+ DMAADVANCE(buf);
+ return 0;
}
-int mgaG200SwitchPipe(drm_device_t *dev, void *code)
+static int mgaG200EmitPipe( drm_device_t *dev, drm_buf_t *buf )
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- drm_dma_t d;
- drm_buf_t *buf;
- DMALOCALS;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->WarpPipe;
+ DMALOCALS;
- /* This needs to get a buffer to fill */
- buf = drm_freelist_get(&dma->bufs[order].freelist,_DRM_DMA_WAIT);
-
- DMAGETPTR(buf);
- DMAOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
- DMAOUTREG(MGAREG_WVRTXSZ, 7);
- DMAOUTREG(MGAREG_WFLAG, 0);
- DMAOUTREG(0x2d00 + 24*4, 0); // tex w/h
+ if (pipe > MGA_MAX_G200_PIPES)
+ return -1;
+
+ DMAGETPTR(buf);
+ DMAOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
+ DMAOUTREG(MGAREG_WVRTXSZ, 7);
+ DMAOUTREG(MGAREG_WFLAG, 0);
+ DMAOUTREG(0x2d00 + 24*4, 0); /* tex w/h */
- DMAOUTREG(0x2d00 + 25*4, 0x100);
- DMAOUTREG(0x2d00 + 34*4, 0); // tex w/h
- DMAOUTREG(0x2d00 + 42*4, 0xFFFF);
- DMAOUTREG(0x2d00 + 60*4, 0xFFFF);
+ DMAOUTREG(0x2d00 + 25*4, 0x100);
+ DMAOUTREG(0x2d00 + 34*4, 0); /* tex w/h */
+ DMAOUTREG(0x2d00 + 42*4, 0xFFFF);
+ DMAOUTREG(0x2d00 + 60*4, 0xFFFF);
- /* Attention! dma pading required due to hw bug (see specs) */
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
- DMAOUTREG(MGAREG_WIADDR,(unsigned long)(code) | WIA_wmode_start |
- WIA_wagp_agp);
- DMAADVANCE(buf);
- d.context = DRM_KERNEL_CONTEXT;
- d.send_count = 1;
- d.send_indices = &buf->idx;
- d.send_sizes = &buf->used;
- d.flags = _DRM_DMA_GENERAL;
- d.request_count = 0;
- d.request_size = 0;
- d.request_indices = NULL;
- d.request_sizes = NULL;
- d.granted_count = 0;
- drm_dma_enqueue(dev, &d);
- return 0;
+ /* Dma pading required due to hw bug */
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ DMAOUTREG(MGAREG_WIADDR, (dev_priv->WarpIndex[pipe].phys_addr |
+ WIA_wmode_start | WIA_wagp_agp));
+
+ DMAADVANCE(buf);
+ return 0;
}
-void mgaWarpPipeRefresh(drm_device_t *dev)
+
+
+void mgaEmitState( drm_device_t *dev )
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- void *code;
- int failure;
-
- code = (void *)dev_priv->WarpIndex[sarea_priv->WarpPipe].phys_addr;
-
- if(!code) {
- printk("Invalid warp code selected : %d\n", sarea_priv->WarpPipe);
- code = (void *)dev_priv->WarpIndex[0].phys_addr;
-
- if(!code) {
- DRM_ERROR("No Warp Pipes Loaded\n");
- return;
- }
- }
- switch(dev_priv->type) {
- case MGA_CARD_TYPE_G400:
- failure = mgaG400SwitchPipe(dev, code);
- break;
- case MGA_CARD_TYPE_G200:
- failure = mgaG200SwitchPipe(dev, code);
- break;
- }
- if(failure) {
- DRM_ERROR("Failed to switch warp pipes to : %d\n",
- sarea_priv->WarpPipe);
- }
+ drm_buf_t *buf;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty ;
+ int rv = 0;
+
+ int order = 1; /* ???? */
+
+ /* Put all state onto a single buffer.
+ */
+ buf = drm_freelist_get(&dma->bufs[order].freelist,_DRM_DMA_WAIT);
+
+
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+
+ if (dirty & MGASAREA_NEW_CONTEXT)
+ rv |= mgaEmitContext( dev, buf );
+
+ if (dirty & MGASAREA_NEW_TEX1)
+ rv |= mgaG400EmitTex1( dev, buf );
+
+ if (dirty & MGASAREA_NEW_TEX0)
+ rv |= mgaG400EmitTex0( dev, buf );
+
+ if (dirty & MGASAREA_NEW_PIPE)
+ rv |= mgaG400EmitPipe( dev, buf );
+
+ } else {
+
+ if (dirty & MGASAREA_NEW_CONTEXT)
+ rv |= mgaEmitContext( dev, buf );
+
+ if (dirty & MGASAREA_NEW_TEX0)
+ rv |= mgaG200EmitTex( dev, buf );
+
+ if (dirty & MGASAREA_NEW_PIPE)
+ rv |= mgaG200EmitPipe( dev, buf );
+ }
+
+
+ if (rv == 0) {
+ drm_dma_t d;
+
+ sarea_priv->dirty = 0;
+
+ d.context = DRM_KERNEL_CONTEXT;
+ d.send_count = 1;
+ d.send_indices = &buf->idx;
+ d.send_sizes = &buf->used;
+ d.flags = _DRM_DMA_GENERAL;
+ d.request_count = 0;
+ d.request_size = 0;
+ d.request_indices = NULL;
+ d.request_sizes = NULL;
+ d.granted_count = 0;
+ drm_dma_enqueue(dev, &d);
+ } else {
+ /* Won't render anything till we get a good state from a
+ * client.
+ */
+ sarea_priv->dirty = ~0;
+ drm_freelist_put( dev, &dma->bufs[order].freelist, buf );
+ }
}
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 01b2024c..01c5bdc8 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -162,9 +162,11 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
+ _DRM_DMA_TYPE_MASK = 0x0F000000,
+ _DRM_DMA_GENERAL = 0x00000000, /* the default type */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
- _DRM_DMA_BLIT = 0x04000000
+ _DRM_DMA_BLIT = 0x03000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {
diff --git a/shared/drm.h b/shared/drm.h
index 01b2024c..01c5bdc8 100644
--- a/shared/drm.h
+++ b/shared/drm.h
@@ -162,9 +162,11 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
+ _DRM_DMA_TYPE_MASK = 0x0F000000,
+ _DRM_DMA_GENERAL = 0x00000000, /* the default type */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
- _DRM_DMA_BLIT = 0x04000000
+ _DRM_DMA_BLIT = 0x03000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {