summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-01-27 23:48:40 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-01-27 23:48:40 +0000
commit621f166c9d0127f94610e4c3a6a14b8176702a2a (patch)
treea2d239624796cb1c608661292baad1ccde4b721d
parent8663acd3b5f8f6515b388930a961f630d7f6ef57 (diff)
Updates to get dma working + support for Xserver changes
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/mga_drv.c1
-rw-r--r--linux/bufs.c4
-rw-r--r--linux/dma.c2
-rw-r--r--linux/drm.h1
-rw-r--r--linux/drmP.h2
-rw-r--r--linux/lists.c2
-rw-r--r--linux/mga_bufs.c42
-rw-r--r--linux/mga_dma.c333
-rw-r--r--linux/mga_drm_public.h160
-rw-r--r--linux/mga_drv.c1
-rw-r--r--linux/mga_drv.h35
-rw-r--r--linux/mga_state.c209
-rw-r--r--shared-core/drm.h1
-rw-r--r--shared/drm.h1
15 files changed, 693 insertions, 103 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 042de764..97d2539a 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -522,7 +522,7 @@ typedef struct drm_device {
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
- void *SAREAprivate;
+ void *dev_private;
} drm_device_t;
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index d037b1b1..81c08e81 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -104,6 +104,7 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 },
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
diff --git a/linux/bufs.c b/linux/bufs.c
index c016734c..7b0cd757 100644
--- a/linux/bufs.c
+++ b/linux/bufs.c
@@ -60,7 +60,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
return -EFAULT;
}
- DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ DRM_INFO("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
map->offset, map->size, map->type);
if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
@@ -111,6 +111,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL;
}
+ printk("Past switch\n");
down(&dev->struct_sem);
if (dev->maplist) {
++dev->map_count;
@@ -135,6 +136,7 @@ int drm_addmap(struct inode *inode, struct file *filp, unsigned int cmd,
sizeof(map->offset),
-EFAULT);
}
+ printk("AddMap succeeded\n");
return 0;
}
diff --git a/linux/dma.c b/linux/dma.c
index 0d19792a..53e7941b 100644
--- a/linux/dma.c
+++ b/linux/dma.c
@@ -425,8 +425,10 @@ int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *d)
current->pid, buf->idx, buf->list);
}
buf->used = d->send_sizes[i];
+#if 0
buf->bus_address = dev->agp->base + 65536 +
(idx * 524288);
+#endif
buf->while_locked = while_locked;
buf->context = d->context;
if (!buf->used) {
diff --git a/linux/drm.h b/linux/drm.h
index 17fe54fc..77d4efb8 100644
--- a/linux/drm.h
+++ b/linux/drm.h
@@ -327,4 +327,5 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t)
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
+/* 0x40 is reserved for mga dma init */
#endif
diff --git a/linux/drmP.h b/linux/drmP.h
index 042de764..97d2539a 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -522,7 +522,7 @@ typedef struct drm_device {
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
- void *SAREAprivate;
+ void *dev_private;
} drm_device_t;
diff --git a/linux/lists.c b/linux/lists.c
index 6c9f9767..6917527b 100644
--- a/linux/lists.c
+++ b/linux/lists.c
@@ -154,7 +154,7 @@ int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
buf->list = DRM_LIST_FREE;
do {
old = bl->next;
- bl->next = old;
+ buf->next = old;
prev = cmpxchg(&bl->next, old, buf);
if (++count > DRM_LOOPING_LIMIT) {
DRM_ERROR("Looping\n");
diff --git a/linux/mga_bufs.c b/linux/mga_bufs.c
index cd608dd2..46219a31 100644
--- a/linux/mga_bufs.c
+++ b/linux/mga_bufs.c
@@ -32,6 +32,7 @@
#define __NO_VERSION__
#include "drmP.h"
+#include "mga_drv.h"
#include "linux/un.h"
int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -69,7 +70,7 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
-
+#if 0
printk("count: %d\n", count);
printk("order: %d\n", order);
printk("size: %d\n", size);
@@ -78,7 +79,7 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
printk("page_order: %d\n", page_order);
printk("total: %d\n", total);
printk("byte_count: %d\n", byte_count);
-
+#endif
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
spin_lock(&dev->count_lock);
@@ -116,10 +117,12 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
buf->total = alignment;
buf->order = order;
buf->used = 0;
+#if 0
printk("offset : %d\n", offset);
- buf->offset = agp_offset + offset;
+#endif
+ buf->offset = offset; /* Hrm */
buf->bus_address = dev->agp->base + agp_offset + offset;
- buf->address = agp_offset + offset + dev->agp->base;
+ buf->address = (void *)(agp_offset + offset + dev->agp->base);
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
@@ -148,10 +151,13 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
dma->buf_count += entry->buf_count;
+#if 0
printk("dma->buf_count : %d\n", dma->buf_count);
+#endif
dma->byte_count += byte_count;
-
+#if 0
printk("entry->buf_count : %d\n", entry->buf_count);
+#endif
drm_freelist_create(&entry->freelist, entry->buf_count);
for (i = 0; i < entry->buf_count; i++) {
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
@@ -168,7 +174,7 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
-EFAULT);
atomic_dec(&dev->buf_alloc);
-
+#if 0
printk("count: %d\n", count);
printk("order: %d\n", order);
printk("size: %d\n", size);
@@ -177,9 +183,11 @@ int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
printk("page_order: %d\n", page_order);
printk("total: %d\n", total);
printk("byte_count: %d\n", byte_count);
-
+#endif
dma->flags = _DRM_DMA_USE_AGP;
+#if 0
printk("dma->flags : %lx\n", dma->flags);
+#endif
return 0;
}
@@ -541,28 +549,29 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
(drm_buf_map_t *)arg,
sizeof(request),
-EFAULT);
+#if 0
printk("mga_mapbufs\n");
printk("dma->flags : %lx\n", dma->flags);
+#endif
if (request.count >= dma->buf_count) {
if(dma->flags & _DRM_DMA_USE_AGP) {
- /* This is an ugly vicious hack */
+ drm_mga_private_t *dev_priv = dev->dev_private;
drm_map_t *map = NULL;
- for(i = 0; i < dev->map_count; i++) {
- map = dev->maplist[i];
- if(map->type == _DRM_AGP) break;
- }
- if (i >= dev->map_count || !map) {
- printk("i : %d\n", i);
+
+ map = dev->maplist[dev_priv->buffer_map_idx];
+ if (!map) {
+ printk("map is null\n");
retcode = -EINVAL;
goto done;
}
+#if 0
printk("map->offset : %lx\n", map->offset);
printk("map->size : %lx\n", map->size);
printk("map->type : %d\n", map->type);
printk("map->flags : %x\n", map->flags);
printk("map->handle : %lx\n", map->handle);
printk("map->mtrr : %d\n", map->mtrr);
-
+#endif
virtual = do_mmap(filp, 0, map->size, PROT_READ|PROT_WRITE,
MAP_SHARED, (unsigned long)map->offset);
} else {
@@ -613,7 +622,8 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
&request,
sizeof(request),
-EFAULT);
-
+#if 0
printk("retcode : %d\n", retcode);
+#endif
return retcode;
}
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index f6b237bd..2c4856ed 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -54,22 +54,37 @@
#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 DMAOUTREG(reg, val) do { \
-buffer.tempIndex[buffer.outcount]=ADRINDEX(reg); \
-buffer.dma_ptr[1+buffer.outcount] = val; \
-if( ++buffer.outcount == 4) { \
-buffer.outcount = 0; \
-buffer.dma_ptr[0] = *(u32 *)buffer.tempIndex; \
-buffer.dma_ptr+=5; \
-buffer.num_dwords += 5; \
-} \
+#define DMALOCALS() u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
+ int outcount, num_dwords; unsigned long flags
+
+#define DMAGETPTR() 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 { \
+dev_priv->prim_num_dwords = num_dwords; \
+dev_priv->current_dma_ptr = dma_ptr; \
+} while(0);
+
+#define DMAOUTREG(reg, val) do { \
+tempIndex[outcount]=ADRINDEX(reg); \
+dma_ptr[1+outcount] = val; \
+if( ++outcount == 4) { \
+outcount = 0; \
+dma_ptr[0] = *(u32 *)tempIndex; \
+dma_ptr+=5; \
+num_dwords += 5; \
+} \
}while (0)
-#define CHECK_OVERFLOW(length) do { \
-if((buffer.max_dwords - buffer.num_dwords) < length) { \
- mga_prim_overflow(dev); \
-} \
+#define CHECK_OVERFLOW(length) do { \
+if((dev_priv->prim_max_dwords - dev_priv->prim_num_dwords) < \
+ length) { \
+ mga_prim_overflow(dev); \
+} \
}while(0)
#define PDEA_pagpxfer_enable 0x2
@@ -78,17 +93,6 @@ if((buffer.max_dwords - buffer.num_dwords) < length) { \
#define MGA_FXBNDRY(x1,x2) DMAOUTREG(MGAREG_FXBNDRY,((x2) << 16) | (x1))
#define MGA_DWGCTL_EXEC(x) DMAOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC,x)
-typedef struct _mga_primary_buffer {
- u32 *head;
- u32 *dma_ptr;
- u8 tempIndex[4];
- int outcount;
- int num_dwords;
- int max_dwords;
- unsigned long phys_head;
-} mgaPrimBuf;
-
-static mgaPrimBuf buffer;
typedef enum {
TT_GENERAL,
TT_BLIT,
@@ -96,12 +100,14 @@ typedef enum {
TT_VERTEX
} transferType_t;
+/* MUST BE CALLED WITH DISPATCH LOCK HELD */
static inline void mga_prim_overflow(drm_device_t *dev)
{
- buffer.num_dwords = 0;
- buffer.outcount = 0;
- buffer.dma_ptr = buffer.head;
- MGA_WRITE(MGAREG_PRIMADDRESS, buffer.phys_head | TT_GENERAL);
+ drm_mga_private_t *dev_private_ptr = dev->dev_private;
+
+ dev_private_ptr->prim_num_dwords = 0;
+ dev_private_ptr->current_dma_ptr = dev_private_ptr->prim_head;
+ MGA_WRITE(MGAREG_PRIMADDRESS, dev_private_ptr->prim_phys_head | TT_GENERAL);
}
static void mga_delay(void)
@@ -109,19 +115,98 @@ static void mga_delay(void)
return;
}
-void mga_dma_init(drm_device_t *dev)
+int mga_dma_cleanup(drm_device_t *dev)
{
- int i;
+ if(dev->dev_private) {
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ int temp;
+
+ if(dev_priv->ioremap) {
+ temp = dev_priv->warp_mc_size + dev_priv->primary_size;
+ temp = ((temp + PAGE_SIZE - 1) /
+ PAGE_SIZE) * PAGE_SIZE;
+ drm_ioremapfree((void *) dev_priv->ioremap, temp);
+ }
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ }
+ return 0;
+}
- memset(&buffer, 0, sizeof(mgaPrimBuf));
- buffer.phys_head = dev->agp->agp_info.aper_base;
- buffer.head = (u32 *) drm_ioremap(buffer.phys_head, 65536);
- buffer.max_dwords = 16383;
- mga_prim_overflow(dev);
- DMAOUTREG(MGAREG_DMAPAD, 0);
+static int mga_dma_initialize(drm_device_t *dev, drm_mga_private_t *dev_priv,
+ drm_mga_init_t *init) {
+ drm_map_t *prim_map = NULL;
+ drm_map_t *sarea_map = NULL;
+ int temp;
+
+ dev->dev_private = (void *) dev_priv;
+ printk("dev_private\n");
+ memset(dev_priv, 0, sizeof(drm_mga_private_t));
+ if((init->reserved_map_idx >= dev->map_count) ||
+ (init->buffer_map_idx >= dev->map_count)) {
+ mga_dma_cleanup(dev);
+ printk("reserved_map or buffer_map are invalid\n");
+ return -EINVAL;
+ }
+
+ dev_priv->reserved_map_idx = init->reserved_map_idx;
+ dev_priv->buffer_map_idx = init->buffer_map_idx;
+ sarea_map = dev->maplist[0];
+ dev_priv->sarea_priv = (drm_mga_sarea_t *)
+ ((u8 *)sarea_map->handle +
+ init->sarea_priv_offset);
+ printk("sarea_priv\n");
+
+ /* 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->fbOffset = init->fbOffset;
+ dev_priv->backOffset = init->backOffset;
+ dev_priv->depthOffset = init->depthOffset;
+ dev_priv->textureOffset = init->textureOffset;
+ dev_priv->textureSize = init->textureSize;
+ dev_priv->cpp = init->cpp;
+ dev_priv->sgram = init->sgram;
+ dev_priv->stride = init->stride;
+
+ printk("memcpy\n");
+ memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
+ sizeof(mgaWarpIndex) * MGA_MAX_WARP_PIPES);
+ 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 = ((temp + PAGE_SIZE - 1) /
+ PAGE_SIZE) * PAGE_SIZE;
+ printk("temp : %x\n", temp);
+ printk("dev->agp->base: %lx\n", dev->agp->base);
+ printk("init->reserved_map_agpstart: %lx\n", init->reserved_map_agpstart);
+ dev_priv->ioremap = drm_ioremap(dev->agp->base + init->reserved_map_agpstart,
+ temp);
+ if(dev_priv->ioremap == NULL) {
+ printk("Ioremap failed\n");
+ mga_dma_cleanup(dev);
+ return -ENOMEM;
+ }
+ dev_priv->prim_head = (u32 *)dev_priv->ioremap;
+ printk("dev_priv->prim_head : %lx\n", dev_priv->prim_head);
+ dev_priv->current_dma_ptr = dev_priv->prim_head;
+ dev_priv->prim_num_dwords = 0;
+ dev_priv->prim_max_dwords = dev_priv->primary_size / sizeof(unsigned long);
+
+ printk("dma initialization\n");
+ /* Private is now filled in, initialize the hardware */
+ {
+ DMALOCALS();
+ mga_prim_overflow(dev);
+ DMAGETPTR();
+ DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_DWGSYNC, 0);
DMAOUTREG(MGAREG_SOFTRAP, 0);
+ DMAADVANCE();
/* Poll for the first buffer to insure that
* the status register will be correct
@@ -129,32 +214,62 @@ void mga_dma_init(drm_device_t *dev)
MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) {
+ int i;
for(i = 0 ; i < 4096; i++) mga_delay();
}
- MGA_WRITE(MGAREG_PRIMEND, (buffer.phys_head +
- (buffer.num_dwords*sizeof(unsigned long))) |
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head +
+ (num_dwords*sizeof(unsigned long))) |
PDEA_pagpxfer_enable);
while(MGA_READ(MGAREG_DWGSYNC) == MGA_SYNC_TAG) {
+ int i;
for(i = 0; i < 4096; i++) mga_delay();
}
+
+ }
+
+ printk("dma init was successful\n");
+ return 0;
}
-void mga_dma_cleanup(drm_device_t *dev)
+int mga_dma_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- if(buffer.head != NULL)
- drm_ioremapfree((void *)buffer.head, 65536);
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_mga_private_t *dev_priv;
+ drm_mga_init_t init;
+ int retcode = 0;
+
+ copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT);
+
+ switch(init.func) {
+ case MGA_INIT_DMA:
+ dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ if(dev_priv == NULL) return -ENOMEM;
+ retcode = mga_dma_initialize(dev, dev_priv, &init);
+ break;
+ case MGA_CLEANUP_DMA:
+ retcode = mga_dma_cleanup(dev);
+ break;
+ default:
+ retcode = -EINVAL;
+ break;
+ }
+ return retcode;
}
static void mga_dma_dispatch(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 */
@@ -179,63 +294,113 @@ static void mga_dma_dispatch(drm_device_t *dev, unsigned long address,
DMAOUTREG(MGAREG_SECEND, (address + length) | use_agp);
DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_DMAPAD, 0);
- DMAOUTREG(MGAREG_DMAPAD, 0);
+ DMAOUTREG(MGAREG_DWGSYNC, 0);
DMAOUTREG(MGAREG_SOFTRAP, 0);
+ DMAADVANCE();
+
+ MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
+ while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
- MGA_WRITE(MGAREG_PRIMEND, (buffer.phys_head +
- (buffer.num_dwords*sizeof(unsigned long))) |
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head +
+ (num_dwords*sizeof(unsigned long))) |
use_agp);
+
k += 20;
j += 5;
if( j < 1280-512) j = 0;
if( k < 512) k = 0;
}
+/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
- while((MGA_READ(MGAREG_STATUS) & 0x00020000) == 0) ;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ while(1) {
+ atomic_inc(&dev_priv->dispatch_lock);
+ if(atomic_read(&dev_priv->dispatch_lock) == 1) {
+ break;
+ } else {
+ atomic_dec(&dev_priv->dispatch_lock);
+ }
+ }
+ while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) ;
MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ;
+ atomic_dec(&dev_priv->dispatch_lock);
}
static inline void mga_dma_ready(drm_device_t *dev)
{
- while((MGA_READ(MGAREG_STATUS) & 0x00020000) == 0) ;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ while(1) {
+ atomic_inc(&dev_priv->dispatch_lock);
+ if(atomic_read(&dev_priv->dispatch_lock) == 1) {
+ atomic_dec(&dev_priv->dispatch_lock);
+ break;
+ } else {
+ atomic_dec(&dev_priv->dispatch_lock);
+ }
+ }
}
+/* Keeps dispatch lock held */
+
static inline int mga_dma_is_ready(drm_device_t *dev)
{
- if((MGA_READ(MGAREG_STATUS) & 0x00020000) == 0)
- return 0;
- else
- return 1;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ atomic_inc(&dev_priv->dispatch_lock);
+ if(atomic_read(&dev_priv->dispatch_lock) == 1) {
+ /* We got the lock */
+ return 1;
+ } else {
+ atomic_dec(&dev_priv->dispatch_lock);
+ return 0;
+ }
+}
+
+static inline int mga_dma_is_ready_no_hold(drm_device_t *dev)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ atomic_inc(&dev_priv->dispatch_lock);
+ if(atomic_read(&dev_priv->dispatch_lock) == 1) {
+ /* We got the lock, but free it */
+ atomic_dec(&dev_priv->dispatch_lock);
+ return 1;
+ } else {
+ atomic_dec(&dev_priv->dispatch_lock);
+ return 0;
+ }
}
static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
{
drm_device_t *dev = (drm_device_t *)device;
drm_device_dma_t *dma = dev->dma;
-
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ atomic_dec(&dev_priv->dispatch_lock);
atomic_inc(&dev->total_irq);
+ MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
- if (mga_dma_is_ready(dev)) {
/* Free previous buffer */
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_free);
- return;
- }
- if (dma->this_buffer) {
- drm_free_buffer(dev, dma->this_buffer);
- dma->this_buffer = NULL;
- }
- clear_bit(0, &dev->dma_flag);
+ if (test_and_set_bit(0, &dev->dma_flag)) {
+ atomic_inc(&dma->total_missed_free);
+ return;
+ }
+ if (dma->this_buffer) {
+ drm_free_buffer(dev, dma->this_buffer);
+ dma->this_buffer = NULL;
+ }
+ clear_bit(0, &dev->dma_flag);
/* Dispatch new buffer */
- queue_task(&dev->tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- }
+ queue_task(&dev->tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
- MGA_WRITE(MGAREG_ICLEAR, 0xfa7);
}
/* Only called by mga_dma_schedule. */
@@ -250,6 +415,8 @@ static int mga_do_dma(drm_device_t *dev, int locked)
#if DRM_DMA_HISTOGRAM
cycles_t dma_start, dma_stop;
#endif
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
if (test_and_set_bit(0, &dev->dma_flag)) {
atomic_inc(&dma->total_missed_dma);
return -EBUSY;
@@ -288,11 +455,11 @@ static int mga_do_dma(drm_device_t *dev, int locked)
return 0;
}
- if (!mga_dma_is_ready(dev)) {
+ if (mga_dma_is_ready(dev) == 0) {
clear_bit(0, &dev->dma_flag);
return -EBUSY;
}
-
+
if (buf->while_locked) {
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("Dispatching buffer %d from pid %d"
@@ -304,6 +471,7 @@ static int mga_do_dma(drm_device_t *dev, int locked)
DRM_KERNEL_CONTEXT)) {
atomic_inc(&dma->total_missed_lock);
clear_bit(0, &dev->dma_flag);
+ atomic_dec(&dev_priv->dispatch_lock);
return -EBUSY;
}
}
@@ -317,6 +485,7 @@ static int mga_do_dma(drm_device_t *dev, int locked)
drm_free_buffer(dev, buf);
}
retcode = -EBUSY;
+ atomic_dec(&dev_priv->dispatch_lock);
goto cleanup;
/* POST: we will wait for the context
@@ -355,7 +524,9 @@ cleanup:
dma_stop = get_cycles();
atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]);
#endif
-
+ /* We hold the dispatch lock until the interrupt handler
+ * frees it
+ */
return retcode;
}
@@ -435,9 +606,9 @@ again:
if (--expire) {
if (missed != atomic_read(&dma->total_missed_sched)) {
atomic_inc(&dma->total_lost);
- if (mga_dma_is_ready(dev)) goto again;
+ if (mga_dma_is_ready_no_hold(dev)) goto again;
}
- if (processed && mga_dma_is_ready(dev)) {
+ if (processed && mga_dma_is_ready_no_hold(dev)) {
atomic_inc(&dma->total_lost);
processed = 0;
goto again;
@@ -587,7 +758,7 @@ static int mga_dma_priority(drm_device_t *dev, drm_dma_t *d)
buf->time_queued = get_cycles();
buf->time_dispatched = buf->time_queued;
#endif
- address = dev->agp->base + 65536 + (idx * 524288);
+ address = buf->bus_address;
#if 0
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT)) {
@@ -710,15 +881,10 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
}
if (d.send_count) {
-#if 1
if (d.flags & _DRM_DMA_PRIORITY)
retcode = mga_dma_priority(dev, &d);
else
retcode = mga_dma_send_buffers(dev, &d);
-#endif
-#if 0
- retcode = mga_dma_priority(dev, &d);
-#endif
}
d.granted_count = 0;
@@ -817,9 +983,6 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
drm_control_t ctl;
int retcode;
-#if 1
- mga_dma_init(dev);
-#endif
copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
switch (ctl.func) {
@@ -915,10 +1078,14 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
if (!ret) {
- if (lock.flags & _DRM_LOCK_READY)
+ if (lock.flags & _DRM_LOCK_READY) {
+ printk("_DRM_LOCK_READY\n");
mga_dma_ready(dev);
- if (lock.flags & _DRM_LOCK_QUIESCENT)
+ }
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ printk("_DRM_LOCK_QUIESCENT\n");
mga_dma_quiescent(dev);
+ }
}
printk("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
diff --git a/linux/mga_drm_public.h b/linux/mga_drm_public.h
new file mode 100644
index 00000000..8c066dd6
--- /dev/null
+++ b/linux/mga_drm_public.h
@@ -0,0 +1,160 @@
+/* mga_drm_public.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
+ * Created: Tue Jan 25 01:50:01 1999 by jhartmann@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.
+ *
+ * Author: Jeff Hartmann <jhartmann@precisioninsight.com>
+ *
+ * $XFree86$
+ */
+
+#ifndef _MGA_DRM_PUBLIC_H_
+#define _MGA_DRM_PUBLIC_H_
+
+/* These defines must match the Xserver code */
+#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_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;
+ unsigned long phys_addr;
+ int size;
+} mgaWarpIndex;
+
+typedef struct drm_mga_init {
+ enum {
+ MGA_INIT_DMA = 0x01,
+ MGA_CLEANUP_DMA = 0x02
+ } func;
+ int reserved_map_agpstart;
+ int reserved_map_idx;
+ int buffer_map_idx;
+ int sarea_priv_offset;
+ int primary_size;
+ int warp_mc_size;
+ int type;
+ int fbOffset;
+ int backOffset;
+ int depthOffset;
+ int textureOffset;
+ int textureSize;
+ int cpp;
+ int stride;
+ int sgram;
+ mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
+} drm_mga_init_t;
+
+typedef struct _xf86drmClipRectRec {
+ unsigned short x1;
+ unsigned short y1;
+ unsigned short x2;
+ 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
+
+
+
+typedef struct _drm_mga_sarea {
+ int CtxOwner;
+ 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)
+
+#endif
diff --git a/linux/mga_drv.c b/linux/mga_drv.c
index d037b1b1..81c08e81 100644
--- a/linux/mga_drv.c
+++ b/linux/mga_drv.c
@@ -104,6 +104,7 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 },
};
#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index f29fa5e2..5cf61883 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -31,6 +31,33 @@
#ifndef _MGA_DRV_H_
#define _MGA_DRV_H_
+#include "mga_drm_public.h"
+
+typedef struct _drm_mga_private {
+ int reserved_map_idx;
+ int buffer_map_idx;
+ drm_mga_sarea_t *sarea_priv;
+ int primary_size;
+ int warp_mc_size;
+ int type;
+ int fbOffset;
+ int backOffset;
+ int depthOffset;
+ int textureOffset;
+ int textureSize;
+ int cpp;
+ int stride;
+ int sgram;
+ mgaWarpIndex WarpIndex[MGA_MAX_WARP_PIPES];
+ __volatile__ unsigned long softrap_age;
+ atomic_t dispatch_lock;
+ void *ioremap;
+ u32 *prim_head;
+ u32 *current_dma_ptr;
+ u32 prim_phys_head;
+ int prim_num_dwords;
+ int prim_max_dwords;
+} drm_mga_private_t;
/* mga_drv.c */
extern int mga_init(void);
@@ -54,9 +81,17 @@ extern int mga_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+#if 0
extern void mga_dma_init(drm_device_t *dev);
extern void mga_dma_cleanup(drm_device_t *dev);
+#endif
+extern int mga_dma_init(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int mga_dma_cleanup(drm_device_t *dev);
+
+/* mga_dma_init does init and release */
+
/* mga_bufs.c */
extern int mga_addbufs(struct inode *inode, struct file *filp,
diff --git a/linux/mga_state.c b/linux/mga_state.c
new file mode 100644
index 00000000..1a1ed4fc
--- /dev/null
+++ b/linux/mga_state.c
@@ -0,0 +1,209 @@
+/* mga_state.c -- State support for mga g200/g400 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by jhartmann@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: Jeff Hartmann <jhartmann@precisioninsight.com>
+ * Keith Whitwell <keithw@precisioninsight.com>
+ *
+ * $XFree86$
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "mga_drv.h"
+#include "mgareg_flags.h"
+
+void mga2drefresh(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 mgaContextRefresh(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 mgaTex0Refresh(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 mgaTex1Refresh(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;
+
+}
+
+/* WIADDR might not work in sec bufs, might need to use
+ * the primary buffer
+ */
+int mgaG400SwitchPipe(drm_device_t *dev, void *code)
+{
+ 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);
+
+ /* This needs to get a buffer to fill */
+
+ 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);
+ }
+
+ DMAOUTREG(MGAREG_WFLAG, 0);
+ DMAOUTREG(MGAREG_WFLAG1, 0);
+
+ DMAOUTREG(0x2d00 + 56*4, *((mgaUI32 *)(&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 + 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;
+}
+
+int mgaG200SwitchPipe(drm_device_t *dev, void *code)
+{
+ 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;
+
+ /* 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
+
+ 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;
+}
+
+void mgaWarpPipeRefresh(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);
+ }
+}
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 17fe54fc..77d4efb8 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -327,4 +327,5 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t)
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
+/* 0x40 is reserved for mga dma init */
#endif
diff --git a/shared/drm.h b/shared/drm.h
index 17fe54fc..77d4efb8 100644
--- a/shared/drm.h
+++ b/shared/drm.h
@@ -327,4 +327,5 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_AGP_BIND DRM_IOWR(0x36, drm_agp_binding_t)
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
+/* 0x40 is reserved for mga dma init */
#endif