summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-02-21 01:37:50 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-02-21 01:37:50 +0000
commit5ae11234d9f7701289254c662a29a6f16914b389 (patch)
tree4e77d373640849e435934fb0d1869c0ec2e40361
parent4f4242d4c87088b71eb3bee2cb95b51c860b9cad (diff)
Added multiple outstanding dma requests for the mga
-rw-r--r--linux-core/i810_dma.c37
-rw-r--r--linux/Makefile.linux3
-rw-r--r--linux/i810_dma.c37
-rw-r--r--linux/mga_context.c44
-rw-r--r--linux/mga_dma.c1439
-rw-r--r--linux/mga_dma.h153
-rw-r--r--linux/mga_drm_public.h4
-rw-r--r--linux/mga_drv.h38
-rw-r--r--linux/mga_state.c679
9 files changed, 1066 insertions, 1368 deletions
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 4d431a18..c374493a 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -104,31 +104,16 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
/* Linear search might not be the best solution */
-#if 0
- i810_print_status_page(dev);
-#endif
for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
-#if 0
- printk("idx : %d in_use : %d\n", i, *buf_priv->in_use);
-#endif
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
I810_BUF_USED);
-#if 0
- printk("used : %d\n", used);
-#endif
if(used == I810_BUF_FREE) {
-#if 0
- printk("Got buffer\n");
-#endif
return buf;
}
}
-#if 0
- printk("Didn't get buffer\n");
-#endif
return NULL;
}
@@ -142,9 +127,6 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
int used;
/* In use is already a pointer */
-#if 0
- i810_print_status_page(dev);
-#endif
used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
if(used != I810_BUF_USED) {
DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
@@ -300,9 +282,6 @@ static int i810_freelist_init(drm_device_t *dev)
buf_priv->my_use_idx = my_idx;
my_idx += 4;
}
-#if 0
- i810_print_status_page(dev);
-#endif
return 0;
}
@@ -495,10 +474,7 @@ static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
static inline void i810_dma_quiescent(drm_device_t *dev)
{
-#if 0
/* Not written yet */
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-#endif
}
/* Interrupts are only for flushing */
@@ -600,9 +576,7 @@ int i810_irq_uninstall(drm_device_t *dev)
if (!irq) return -EINVAL;
- DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
-
-
+ DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
DRM_DEBUG("%d\n", irq);
temp = I810_READ16(I810REG_INT_IDENTITY_R);
@@ -669,16 +643,10 @@ static int i810_flush_queue(drm_device_t *dev)
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
int ret = 0;
-#if 0
- printk("i810_flush_queue\n");
-#endif
if(dev_priv == NULL) {
return 0;
}
atomic_set(&dev_priv->flush_done, 0);
-#if 0
- printk("got to flush\n");
-#endif
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
for (;;) {
@@ -779,9 +747,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
-#if 0
- current->policy |= SCHED_YIELD;
-#endif
DRM_DEBUG("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
diff --git a/linux/Makefile.linux b/linux/Makefile.linux
index 41f7a7db..f740220f 100644
--- a/linux/Makefile.linux
+++ b/linux/Makefile.linux
@@ -71,8 +71,7 @@ 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 mga_state.o mga_clear.o \
- mga_context.o
+MGAOBJS= mga_drv.o mga_dma.o mga_bufs.o mga_state.o mga_context.o
MGAHEADERS= mga_drv.h mga_drm_public.h $(DRMHEADERS)
R128OBJS= r128_drv.o r128_context.o
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index 4d431a18..c374493a 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -104,31 +104,16 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
/* Linear search might not be the best solution */
-#if 0
- i810_print_status_page(dev);
-#endif
for (i = 0; i < dma->buf_count; i++) {
drm_buf_t *buf = dma->buflist[ i ];
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
/* In use is already a pointer */
-#if 0
- printk("idx : %d in_use : %d\n", i, *buf_priv->in_use);
-#endif
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
I810_BUF_USED);
-#if 0
- printk("used : %d\n", used);
-#endif
if(used == I810_BUF_FREE) {
-#if 0
- printk("Got buffer\n");
-#endif
return buf;
}
}
-#if 0
- printk("Didn't get buffer\n");
-#endif
return NULL;
}
@@ -142,9 +127,6 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
int used;
/* In use is already a pointer */
-#if 0
- i810_print_status_page(dev);
-#endif
used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
if(used != I810_BUF_USED) {
DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
@@ -300,9 +282,6 @@ static int i810_freelist_init(drm_device_t *dev)
buf_priv->my_use_idx = my_idx;
my_idx += 4;
}
-#if 0
- i810_print_status_page(dev);
-#endif
return 0;
}
@@ -495,10 +474,7 @@ static inline void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
static inline void i810_dma_quiescent(drm_device_t *dev)
{
-#if 0
/* Not written yet */
- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-#endif
}
/* Interrupts are only for flushing */
@@ -600,9 +576,7 @@ int i810_irq_uninstall(drm_device_t *dev)
if (!irq) return -EINVAL;
- DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
-
-
+ DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
DRM_DEBUG("%d\n", irq);
temp = I810_READ16(I810REG_INT_IDENTITY_R);
@@ -669,16 +643,10 @@ static int i810_flush_queue(drm_device_t *dev)
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
int ret = 0;
-#if 0
- printk("i810_flush_queue\n");
-#endif
if(dev_priv == NULL) {
return 0;
}
atomic_set(&dev_priv->flush_done, 0);
-#if 0
- printk("got to flush\n");
-#endif
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
for (;;) {
@@ -779,9 +747,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
-#if 0
- current->policy |= SCHED_YIELD;
-#endif
DRM_DEBUG("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
diff --git a/linux/mga_context.c b/linux/mga_context.c
index 4e793213..aadc846e 100644
--- a/linux/mga_context.c
+++ b/linux/mga_context.c
@@ -194,51 +194,11 @@ int mga_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_ctx_t ctx;
- drm_queue_t *q;
- drm_buf_t *buf;
copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT);
printk("%d\n", ctx.handle);
- if(ctx.handle == DRM_KERNEL_CONTEXT) {
- q = dev->queuelist[ctx.handle];
- atomic_inc(&q->use_count);
- if (atomic_read(&q->use_count) == 1) {
- /* No longer in use */
- atomic_dec(&q->use_count);
- return -EINVAL;
- }
- atomic_inc(&q->finalization); /* Mark queue in finalization state */
- atomic_sub(2, &q->use_count);
- /* Mark queue as unused (pending finalization) */
-
- while (test_and_set_bit(0, &dev->interrupt_flag)) {
- printk("Calling schedule from rmctx\n");
- schedule();
- if (signal_pending(current)) {
- clear_bit(0, &dev->interrupt_flag);
- return -EINTR;
- }
- }
-
- /* Remove queued buffers */
- while ((buf = drm_waitlist_get(&q->waitlist))) {
- drm_free_buffer(dev, buf);
- }
- clear_bit(0, &dev->interrupt_flag);
-
- /* Wakeup blocked processes */
- wake_up_interruptible(&q->read_queue);
- wake_up_interruptible(&q->write_queue);
- wake_up_interruptible(&q->flush_queue);
-
- /* Finalization over. Queue is made
- available when both use_count and
- finalization become 0, which won't
- happen until all the waiting processes
- stop waiting. */
- atomic_dec(&q->finalization);
- } else {
- drm_ctxbitmap_free(dev, ctx.handle);
+ if(ctx.handle != DRM_KERNEL_CONTEXT) {
+ drm_ctxbitmap_free(dev, ctx.handle);
}
return 0;
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index a424e2f6..ec9df633 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -36,7 +36,6 @@
#include "mga_drv.h"
#include "mgareg_flags.h"
#include "mga_dma.h"
-#include "mga_state.h"
#include <linux/interrupt.h> /* For task queue support */
@@ -47,20 +46,8 @@
#define MGA_DEREF(reg) *(__volatile__ int *)MGA_ADDR(reg)
#define MGA_READ(reg) MGA_DEREF(reg)
#define MGA_WRITE(reg,val) do { MGA_DEREF(reg) = val; } while (0)
-#define MGA_DEREF8(reg) *(__volatile__ u8 *)MGA_ADDR(reg)
-#define MGA_READ8(reg) MGA_DEREF8(reg)
-#define MGA_WRITE8(reg,val) do { MGA_DEREF8(reg) = val; } while (0)
#define PDEA_pagpxfer_enable 0x2
-#define MGA_TOP_SYNC_TAG 0x3784f700
-#define MGA_SYNC_TAG 0x423f4200
-
-typedef enum {
- TT_GENERAL,
- TT_BLIT,
- TT_VECTOR,
- TT_VERTEX
-} transferType_t;
static unsigned long mga_alloc_page(drm_device_t *dev)
{
@@ -96,11 +83,320 @@ static void mga_delay(void)
static void mga_flush_write_combine(void)
{
int xchangeDummy;
- __asm__ volatile( " push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
+ __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
__asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;"
" movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;"
" pop %%eax" : /* no outputs */ : /* no inputs */ );
}
+/* These are two age tags that will never be sent to
+ * the hardware */
+#define MGA_BUF_USED 0xffffffff
+#define MGA_BUF_FREE 0
+
+static void mga_freelist_init(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+
+ buf_priv->age = MGA_BUF_FREE;
+ }
+}
+
+unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv)
+{
+ unsigned int temp;
+
+ dev_priv->sync_tag++;
+ if(dev_priv->sync_tag > 0x3fffffff) {
+ /* Make sure we are always at least 1 */
+ dev_priv->sync_tag = 1;
+ /* Do a full dma flush */
+ }
+ temp = dev_priv->sync_tag << 2;
+ DRM_DEBUG("sync_tag : %x\n", temp);
+ return temp;
+}
+
+drm_buf_t *mga_freelist_get(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+ int i;
+
+ /* Linear search might not be the best solution */
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ if(buf_priv->age < status[1]) {
+ buf_priv->age = MGA_BUF_USED;
+ return buf;
+ }
+ }
+ return NULL;
+}
+
+int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+{
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+
+ /* In use is already a pointer */
+ if(buf_priv->age != MGA_BUF_USED) {
+ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+ return -EINVAL;
+ }
+ buf_priv->age = MGA_BUF_FREE;
+
+ return 0;
+}
+
+static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_prim_buf_t *prim_buffer;
+ int i, temp, size_of_buf;
+ int offset = init->reserved_map_agpstart;
+
+ DRM_DEBUG("mga_init_primary_bufs\n");
+ dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
+ PAGE_SIZE) * PAGE_SIZE;
+ DRM_DEBUG("primary_size\n");
+ size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
+ dev_priv->warp_ucode_size = init->warp_ucode_size;
+ dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) *
+ (MGA_NUM_PRIM_BUFS + 1),
+ DRM_MEM_DRIVER);
+ if(dev_priv->prim_bufs == NULL) {
+ DRM_ERROR("Unable to allocate memory for prim_buf\n");
+ return -ENOMEM;
+ }
+ DRM_DEBUG("memset\n");
+ memset(dev_priv->prim_bufs,
+ 0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1));
+
+ temp = init->warp_ucode_size + dev_priv->primary_size;
+ temp = ((temp + PAGE_SIZE - 1) /
+ PAGE_SIZE) * PAGE_SIZE;
+
+ DRM_DEBUG("temp : %x\n", temp);
+ DRM_DEBUG("dev->agp->base: %lx\n", dev->agp->base);
+ DRM_DEBUG("init->reserved_map_agpstart: %x\n",
+ init->reserved_map_agpstart);
+ /* Make sure that ioremap is u8 type */
+ DRM_DEBUG("ioremap\n");
+ dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
+ temp);
+ if(dev_priv->ioremap == NULL) {
+ DRM_DEBUG("Ioremap failed\n");
+ return -ENOMEM;
+ }
+ init_waitqueue_head(&dev_priv->wait_queue);
+
+ for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
+ DRM_DEBUG("For loop\n");
+ prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t), DRM_MEM_DRIVER);
+ if(prim_buffer == NULL) return -ENOMEM;
+ DRM_DEBUG("memset\n");
+ memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t));
+ prim_buffer->phys_head = offset + dev->agp->base;
+ prim_buffer->current_dma_ptr = prim_buffer->head = (u32 *)
+ (dev_priv->ioremap + (offset - init->reserved_map_agpstart));
+ prim_buffer->num_dwords = 0;
+ prim_buffer->max_dwords = size_of_buf / sizeof(u32);
+ prim_buffer->max_dwords -= 5; /* Leave room for the softrap */
+ prim_buffer->sec_used = 0;
+ prim_buffer->idx = i;
+ offset = offset + size_of_buf;
+ dev_priv->prim_bufs[i] = prim_buffer;
+ DRM_DEBUG("Looping\n");
+ }
+ dev_priv->current_prim_idx = 0;
+ dev_priv->next_prim = dev_priv->last_prim = dev_priv->current_prim =
+ dev_priv->prim_bufs[0];
+ set_bit(0, &dev_priv->current_prim->in_use);
+ DRM_DEBUG("init done\n");
+ return 0;
+}
+
+void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int use_agp = PDEA_pagpxfer_enable;
+ PRIMLOCALS;
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
+ /* We never check for overflow, b/c there is always room */
+ PRIMPTR(prim);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMOUTREG( MGAREG_SOFTRAP, prim->idx << 2);
+ PRIMFINISH(prim);
+
+ if(sarea_priv->dirty & MGA_DMA_FLUSH) {
+ /* This needs to be optimized so that it only happens
+ * when the Xserver actually did 2d rendering */
+ DRM_DEBUG("Dma top flush\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
+ sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
+ } else {
+ DRM_DEBUG("Status wait\n");
+ while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) ;
+ }
+
+ mga_flush_write_combine();
+ MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
+ MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
+}
+
+int mga_advance_primary(drm_device_t *dev)
+{
+ DECLARE_WAITQUEUE(entry, current);
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_prim_buf_t *prim_buffer;
+ int next_prim_idx;
+ int ret = 0;
+
+ /* This needs to reset the primary buffer if available,
+ * we should collect stats on how many times it bites
+ * it's tail */
+ next_prim_idx = dev_priv->current_prim_idx + 1;
+ if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
+ next_prim_idx = 0;
+ prim_buffer = dev_priv->prim_bufs[next_prim_idx];
+ /* In use is cleared in interrupt handler */
+ atomic_set(&dev_priv->in_wait, 1);
+ if(test_and_set_bit(0, &prim_buffer->in_use)) {
+ /* We need to wait, we should probably use
+ * a wait queue for this.
+ */
+ add_wait_queue(&dev_priv->wait_queue, &entry);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if(!test_and_set_bit(0, &prim_buffer->in_use)) break;
+ atomic_inc(&dev->total_sleeps);
+ mga_dma_schedule(dev, 0);
+ schedule_timeout(HZ/60);
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->wait_queue, &entry);
+ if(ret) return ret;
+ }
+ atomic_set(&dev_priv->in_wait, 0);
+ /* This primary buffer is now free to use */
+ prim_buffer->current_dma_ptr = prim_buffer->head;
+ prim_buffer->num_dwords = 0;
+ prim_buffer->sec_used = 0;
+ dev_priv->current_prim = prim_buffer;
+ dev_priv->current_prim_idx = next_prim_idx;
+ return 0;
+}
+
+int mga_dma_schedule(drm_device_t *dev, int locked)
+{
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+
+ if (test_and_set_bit(0, &dev->dma_flag)) {
+ atomic_inc(&dma->total_missed_dma);
+ return -EBUSY;
+ }
+
+ if (!locked && !atomic_read(&dev_priv->in_flush) &&
+ !atomic_read(&dev_priv->in_wait) &&
+ !drm_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ atomic_inc(&dma->total_missed_lock);
+ clear_bit(0, &dev->dma_flag);
+ return -EBUSY;
+ }
+
+ if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
+ /* Fire dma buffer */
+ if(dev_priv->next_prim->sec_used >= (MGA_DMA_BUF_NR / 2) ||
+ (dev_priv->next_prim->num_dwords && atomic_read(&dev_priv->in_flush)) ||
+ atomic_read(&dev_priv->next_prim->force_fire)) {
+ DRM_DEBUG("mga_fire_primary\n");
+ atomic_set(&dev_priv->next_prim->force_fire, 0);
+ if(dev_priv->current_prim == dev_priv->next_prim) {
+ mga_advance_primary(dev);
+ }
+ mga_fire_primary(dev,
+ dev_priv->next_prim);
+ DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx);
+ } else {
+ clear_bit(0, &dev_priv->dispatch_lock);
+ }
+ }
+
+ if (!locked && !atomic_read(&dev_priv->in_flush)
+ && !atomic_read(&dev_priv->in_wait)) {
+ if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ }
+
+ clear_bit(0, &dev->dma_flag);
+ return 0;
+}
+
+static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
+{
+ drm_device_t *dev = (drm_device_t *)device;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_prim_buf_t *last_prim_buffer;
+ int softrap_idx;
+ int next_idx;
+
+ softrap_idx = MGA_READ(MGAREG_SECADDRESS);
+ atomic_inc(&dev->total_irq);
+ MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
+ softrap_idx = softrap_idx >> 2;
+ DRM_DEBUG("softrap_idx : %d\n", softrap_idx);
+ next_idx = softrap_idx + 1;
+ if(next_idx >= MGA_NUM_PRIM_BUFS) {
+ next_idx = 0;
+ }
+ dev_priv->next_prim = dev_priv->prim_bufs[next_idx];
+ last_prim_buffer = dev_priv->prim_bufs[softrap_idx];
+ dev_priv->last_prim = last_prim_buffer;
+ last_prim_buffer->num_dwords = 0;
+ clear_bit(0, &last_prim_buffer->in_use);
+ clear_bit(0, &dev_priv->dispatch_lock);
+ queue_task(&dev->tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static void mga_dma_task_queue(void *device)
+{
+ /* This needs to do primary buffer ping-ponging as well
+ * as flushing */
+ drm_device_t *dev = (drm_device_t *) device;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ wake_up_interruptible(&dev_priv->wait_queue);
+ mga_dma_schedule(dev, 0);
+ if(atomic_read(&dev_priv->in_flush) == 1 &&
+ dev_priv->next_prim->num_dwords == 0) {
+ /* Everything is on the hardware */
+ atomic_set(&dev_priv->in_flush, 0);
+ wake_up_interruptible(&dev_priv->flush_queue);
+ }
+}
int mga_dma_cleanup(drm_device_t *dev)
{
@@ -121,6 +417,20 @@ int mga_dma_cleanup(drm_device_t *dev)
if(dev_priv->real_status_page != 0UL) {
mga_free_page(dev, dev_priv->real_status_page);
}
+ if(dev_priv->prim_bufs != NULL) {
+ int i;
+ for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
+ if(dev_priv->prim_bufs[i] != NULL) {
+ drm_free(dev_priv->prim_bufs[i],
+ sizeof(drm_mga_prim_buf_t),
+ DRM_MEM_DRIVER);
+ }
+ }
+ drm_free(dev_priv->prim_bufs, sizeof(void *) *
+ (MGA_NUM_PRIM_BUFS + 1),
+ DRM_MEM_DRIVER);
+ }
+
drm_free(dev->dev_private, sizeof(drm_mga_private_t),
DRM_MEM_DRIVER);
@@ -130,80 +440,9 @@ int mga_dma_cleanup(drm_device_t *dev)
return 0;
}
-static int mga_alloc_kernel_queue(drm_device_t *dev)
-{
- drm_queue_t *queue = NULL;
-
- /* Allocate a new queue */
- down(&dev->struct_sem);
-
- if(dev->queue_count != 0) {
- /* Reseting the kernel context here is not
- * a race, since it can only happen when that
- * queue is empty.
- */
- queue = dev->queuelist[DRM_KERNEL_CONTEXT];
- DRM_DEBUG("Kernel queue already allocated\n");
- } else {
- queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
- if(!queue) {
- up(&dev->struct_sem);
- DRM_DEBUG("out of memory\n");
- return -ENOMEM;
- }
- ++dev->queue_count;
- dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
- DRM_MEM_QUEUES);
- if(!dev->queuelist) {
- up(&dev->struct_sem);
- drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
- DRM_DEBUG("out of memory\n");
- return -ENOMEM;
- }
- }
-
- memset(queue, 0, sizeof(*queue));
- atomic_set(&queue->use_count, 1);
- atomic_set(&queue->finalization, 0);
- atomic_set(&queue->block_count, 0);
- atomic_set(&queue->block_read, 0);
- atomic_set(&queue->block_write, 0);
- atomic_set(&queue->total_queued, 0);
- atomic_set(&queue->total_flushed, 0);
- atomic_set(&queue->total_locks, 0);
-
- init_waitqueue_head(&queue->write_queue);
- init_waitqueue_head(&queue->read_queue);
- init_waitqueue_head(&queue->flush_queue);
-
- queue->flags = 0;
-
- drm_waitlist_create(&queue->waitlist, dev->dma->buf_count);
-
- dev->queue_slots = 1;
- dev->queuelist[DRM_KERNEL_CONTEXT] = queue;
- dev->queue_count--;
-
- up(&dev->struct_sem);
- DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
- return DRM_KERNEL_CONTEXT;
-}
-
-static unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv)
-{
- unsigned int temp;
-
- dev_priv->sync_tag++;
- temp = dev_priv->sync_tag << 2;
- DRM_DEBUG("sync_tag : %x\n", temp);
- return temp;
-}
-
static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
drm_mga_private_t *dev_priv;
- drm_map_t *prim_map = NULL;
drm_map_t *sarea_map = NULL;
- int temp;
int i;
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
@@ -213,7 +452,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
DRM_DEBUG("dev_private\n");
memset(dev_priv, 0, sizeof(drm_mga_private_t));
- atomic_set(&dev_priv->pending_bufs, 0);
atomic_set(&dev_priv->in_flush, 0);
if((init->reserved_map_idx >= dev->map_count) ||
@@ -223,12 +461,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
return -EINVAL;
}
- if(mga_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
- mga_dma_cleanup(dev);
- DRM_ERROR("Kernel context queue not present\n");
- return -ENOMEM;
- }
-
dev_priv->reserved_map_idx = init->reserved_map_idx;
dev_priv->buffer_map_idx = init->buffer_map_idx;
sarea_map = dev->maplist[0];
@@ -238,9 +470,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
DRM_DEBUG("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_ucode_size = init->warp_ucode_size;
dev_priv->chipset = init->chipset;
dev_priv->frontOffset = init->frontOffset;
dev_priv->backOffset = init->backOffset;
@@ -252,58 +481,33 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
dev_priv->stride = init->stride;
dev_priv->mAccess = init->mAccess;
-
+ init_waitqueue_head(&dev_priv->flush_queue);
dev_priv->WarpPipe = -1;
- if (MGA_VERBOSE) {
- DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
+ DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
dev_priv->chipset, dev_priv->warp_ucode_size,
dev_priv->backOffset, dev_priv->depthOffset);
- DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
+ DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
dev_priv->cpp, dev_priv->sgram, dev_priv->stride,
dev_priv->mAccess);
- }
-
memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
sizeof(mgaWarpIndex) * MGA_MAX_WARP_PIPES);
- if (MGA_VERBOSE)
- for (i = 0 ; i < MGA_MAX_WARP_PIPES ; i++)
- DRM_DEBUG("warp pipe %d: installed: %d phys_addr: %lx size: %x\n",
- i,
- dev_priv->WarpIndex[i].installed,
- dev_priv->WarpIndex[i].phys_addr,
- dev_priv->WarpIndex[i].size);
-
-
- prim_map = dev->maplist[init->reserved_map_idx];
- dev_priv->prim_phys_head = dev->agp->base + init->reserved_map_agpstart;
- temp = init->warp_ucode_size + dev_priv->primary_size;
- temp = ((temp + PAGE_SIZE - 1) /
- PAGE_SIZE) * PAGE_SIZE;
-
- if (MGA_VERBOSE) {
- DRM_DEBUG("temp : %x\n", temp);
- DRM_DEBUG("dev->agp->base: %lx\n", dev->agp->base);
- DRM_DEBUG("init->reserved_map_agpstart: %x\n",
- init->reserved_map_agpstart);
- }
+ for (i = 0 ; i < MGA_MAX_WARP_PIPES ; i++)
+ DRM_DEBUG("warp pipe %d: installed: %d phys_addr: %lx size: %x\n",
+ i,
+ dev_priv->WarpIndex[i].installed,
+ dev_priv->WarpIndex[i].phys_addr,
+ dev_priv->WarpIndex[i].size);
- dev_priv->ioremap = drm_ioremap(dev->agp->base + init->reserved_map_agpstart,
- temp);
- if(dev_priv->ioremap == NULL) {
- DRM_DEBUG("Ioremap failed\n");
- mga_dma_cleanup(dev);
- return -ENOMEM;
+ DRM_DEBUG("Doing init prim buffers\n");
+ if(mga_init_primary_bufs(dev, init) != 0) {
+ DRM_ERROR("Can not initialize primary buffers\n");
+ mga_dma_cleanup(dev);
+ return -ENOMEM;
}
-
-
-
- dev_priv->prim_head = (u32 *)dev_priv->ioremap;
- dev_priv->current_dma_ptr = dev_priv->prim_head;
- dev_priv->prim_num_dwords = 0;
- dev_priv->prim_max_dwords = dev_priv->primary_size / 4;
+ DRM_DEBUG("Done with init prim buffers\n");
dev_priv->real_status_page = mga_alloc_page(dev);
if(dev_priv->real_status_page == 0UL) {
mga_dma_cleanup(dev);
@@ -330,16 +534,12 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
return -EINVAL;
}
-
- if (MGA_VERBOSE)
- DRM_DEBUG("dma initialization\n");
+ DRM_DEBUG("dma initialization\n");
/* Private is now filled in, initialize the hardware */
{
__volatile__ unsigned int *status = (unsigned int *)dev_priv->status_page;
PRIMLOCALS;
- PRIMRESET( dev_priv );
-
PRIMGETPTR( dev_priv );
dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
@@ -348,16 +548,15 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
PRIMOUTREG(MGAREG_SOFTRAP, 0);
-
+/*
PRIMADVANCE( dev_priv );
-
+*/
/* Poll for the first buffer to insure that
* the status register will be correct
*/
DRM_DEBUG("phys_head : %lx\n", (unsigned long)phys_head);
status[1] = 0;
-
mga_flush_write_combine();
MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
@@ -367,12 +566,12 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
while(MGA_READ(MGAREG_DWGSYNC) != dev_priv->last_sync_tag) ;
DRM_DEBUG("status[0] after initialization : %x\n", status[0]);
DRM_DEBUG("status[1] after initialization : %x\n", status[1]);
- DRM_DEBUG("status[2] after initialization : %x\n", status[2]);
- DRM_DEBUG("status[3] after initialization : %x\n", status[3]);
+ /* Reset the buffer structure */
+
}
-
- if (MGA_VERBOSE)
- DRM_DEBUG("dma init was successful\n");
+
+ mga_freelist_init(dev);
+ DRM_DEBUG("dma init was successful\n");
return 0;
}
@@ -395,359 +594,6 @@ int mga_dma_init(struct inode *inode, struct file *filp,
return -EINVAL;
}
-
-#if 0
-static void __mga_iload_small(drm_device_t *dev, drm_buf_t *buf)
-{
- int use_agp = PDEA_pagpxfer_enable;
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int y1 = buf_priv->boxes[0].y1;
- int x1 = buf_priv->boxes[0].x1;
- int y2 = buf_priv->boxes[0].y2;
- int x2 = buf_priv->boxes[0].x2;
- int dstorg = buf_priv->ContextState[MGA_CTXREG_DSTORG];
- int maccess = buf_priv->ContextState[MGA_CTXREG_MACCESS];
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
-
- dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
-
- PRIMOUTREG(MGAREG_DSTORG, dstorg );
- PRIMOUTREG(MGAREG_MACCESS, maccess);
- PRIMOUTREG(MGAREG_PITCH, (1 << 15));
- PRIMOUTREG(MGAREG_YDST, y1 * (x2 - x1));
-
- PRIMOUTREG(MGAREG_LEN, 1);
- PRIMOUTREG(MGAREG_FXBNDRY, ((x2 - x1) * (y2 - y1) - 1) << 16);
- PRIMOUTREG(MGAREG_AR0, (x2 - x1) * (y2 - y1) - 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, ((__u32)address) | TT_BLIT);
- PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
-
- PRIMADVANCE(dev_priv);
-#if 0
- /* For now we need to set this in the ioctl */
- sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
-#endif
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- PRIMADVANCE(dev_priv);
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
-static void __mga_iload_xy(drm_device_t *dev, drm_buf_t *buf )
-{
- int use_agp = PDEA_pagpxfer_enable;
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int y1 = buf_priv->boxes[0].y1;
- int x1 = buf_priv->boxes[0].x1;
- int y2 = buf_priv->boxes[0].y2;
- int x2 = buf_priv->boxes[0].x2;
- int dstorg = buf_priv->ContextState[MGA_CTXREG_DSTORG];
- int maccess = buf_priv->ContextState[MGA_CTXREG_MACCESS];
- int pitch = buf_priv->ServerState[MGA_2DREG_PITCH];
- int width, height;
- int texperdword = 0;
- PRIMLOCALS;
-
- width = (x2 - x1);
- height = (y2 - y1);
- switch((maccess & 0x00000003)) {
- case 0:
- texperdword = 4;
- break;
- case 1:
- texperdword = 2;
- break;
- case 2:
- texperdword = 1;
- break;
- default:
- DRM_ERROR("Invalid maccess value passed to __mga_iload_xy\n");
- return;
- }
-
- x2 = x1 + width;
- x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
- x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
- width = x2 - x1;
-
- dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG(MGAREG_DSTORG, dstorg);
- PRIMOUTREG(MGAREG_MACCESS, maccess);
- PRIMOUTREG(MGAREG_PITCH, pitch);
- PRIMOUTREG(MGAREG_YDSTLEN, (y1 << 16) | height);
-
- PRIMOUTREG(MGAREG_FXBNDRY, ((x1+width-1) << 16) | x1);
- PRIMOUTREG(MGAREG_AR0, width * height - 1);
- PRIMOUTREG(MGAREG_AR3, 0 );
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_SECADDRESS, ((__u32)address) | TT_BLIT);
- PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-#if 0
- /* For now we need to set this in the ioctl */
- sarea_priv->dirty |= MGASAREA_NEW_CONTEXT;
-#endif
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
-
-static void mga_dma_dispatch_iload(drm_device_t *dev, drm_buf_t *buf)
-{
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-
- int x1 = buf_priv->boxes[0].x1;
- int x2 = buf_priv->boxes[0].x2;
-
-
- if((x2 - x1) < 32) {
- if (MGA_VERBOSE) DRM_DEBUG("using iload small\n");
- __mga_iload_small(dev, buf);
- } else {
- if (MGA_VERBOSE) DRM_DEBUG("using iload xy\n");
- __mga_iload_xy(dev, buf);
- }
-}
-#endif
-
-static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf )
-{
- int use_agp = PDEA_pagpxfer_enable;
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_buf_priv_t *buf_priv = buf->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int y1 = buf_priv->boxes[0].y1;
- int x1 = buf_priv->boxes[0].x1;
- int y2 = buf_priv->boxes[0].y2;
- int x2 = buf_priv->boxes[0].x2;
- int dstorg = buf_priv->ContextState[MGA_CTXREG_DSTORG];
- int maccess = buf_priv->ContextState[MGA_CTXREG_MACCESS];
- int pitch = buf_priv->ServerState[MGA_2DREG_PITCH];
- int width, height;
- int texperdword = 0;
- PRIMLOCALS;
-
- switch((maccess & 0x00000003)) {
- case 0:
- texperdword = 4;
- break;
- case 1:
- texperdword = 2;
- break;
- case 2:
- texperdword = 1;
- break;
- }
-
- x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
- x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
- width = x2 - x1;
- height = y2 - y1;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
- PRIMOUTREG(MGAREG_DSTORG, dstorg);
- PRIMOUTREG(MGAREG_MACCESS, maccess);
- PRIMOUTREG(MGAREG_PITCH, pitch);
- PRIMOUTREG(MGAREG_YDSTLEN, (y1 << 16) | height);
-
- PRIMOUTREG(MGAREG_FXBNDRY, ((x1+width-1) << 16) | x1);
- PRIMOUTREG(MGAREG_AR0, width * height - 1);
- PRIMOUTREG(MGAREG_AR3, 0 );
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
-
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_SRCORG, ((__u32)address) | TT_BLIT);
- PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
-
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
- PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
- PRIMOUTREG(MGAREG_PITCH, dev_priv->stride);
- PRIMOUTREG(MGAREG_AR0, 0 );
-
- PRIMOUTREG(MGAREG_AR3, 0 );
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-
-}
-
-static void mga_dma_dispatch_vertex(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_sarea_t *sarea_priv = dev_priv->sarea_priv;
-
- drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ];
- unsigned long address = (unsigned long)real_buf->bus_address;
- int length = buf->used;
- int use_agp = PDEA_pagpxfer_enable;
- int i = 0;
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
-
- DRM_DEBUG("dispatch vertex %d addr 0x%lx, length 0x%x nbox %d\n",
- buf->idx, address, length, buf_priv->nbox);
-
- if (!buf_priv->vertex_discard) {
-
- mgaEmitState( dev_priv, buf_priv );
-
- do {
- if (i < buf_priv->nbox) {
- if (0)
- DRM_DEBUG("idx %d Emit box %d/%d:"
- "%d,%d - %d,%d\n",
- buf->idx,
- i, buf_priv->nbox,
- buf_priv->boxes[i].x1,
- buf_priv->boxes[i].y1,
- buf_priv->boxes[i].x2,
- buf_priv->boxes[i].y2);
-
-
- mgaEmitClipRect( dev_priv,
- &buf_priv->boxes[i] );
- }
-
- PRIMGETPTR(dev_priv);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SECADDRESS,
- ((__u32)address) | TT_VERTEX);
- PRIMOUTREG( MGAREG_SECEND,
- (((__u32)(address + length)) |
- use_agp));
- PRIMADVANCE( dev_priv );
- } while (++i < buf_priv->nbox);
- }
-
-
- dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
-
- PRIMGETPTR( dev_priv );
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
- PRIMOUTREG(MGAREG_SOFTRAP, 0);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- PRIMADVANCE( dev_priv );
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
-
-/* Not currently used
- */
-static void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
-{
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned long address = (unsigned long)buf->bus_address;
- int length = buf->used;
- int use_agp = PDEA_pagpxfer_enable;
- PRIMLOCALS;
-
- PRIMRESET(dev_priv);
- PRIMGETPTR(dev_priv);
-
- dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SECADDRESS, ((__u32)address) | TT_GENERAL);
- PRIMOUTREG( MGAREG_SECEND, (((__u32)(address + length)) | use_agp));
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
void mga_wait_usec(int waittime)
{
struct timeval timep;
@@ -792,196 +638,6 @@ void mga_reset_abort(drm_device_t *dev)
}
}
-static void mga_dma_dispatch_clear( 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_sarea_t *sarea_priv = dev_priv->sarea_priv;
- int nbox = buf_priv->nbox;
- xf86drmClipRectRec *pbox = buf_priv->boxes;
- int flags = buf_priv->clear_flags;
- unsigned int cmd;
- int use_agp = PDEA_pagpxfer_enable;
- int i;
- PRIMLOCALS;
-
- if ( dev_priv->sgram )
- cmd = MGA_CLEAR_CMD | DC_atype_blk;
- else
- cmd = MGA_CLEAR_CMD | DC_atype_rstr;
-
-
- PRIMRESET( dev_priv );
- PRIMGETPTR( dev_priv );
-
- for (i = 0 ; i < nbox ; i++) {
- unsigned int height = pbox[i].y2 - pbox[i].y1;
-
- if (MGA_VERBOSE)
- DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
- pbox[i].x1,
- pbox[i].y1,
- pbox[i].x2,
- pbox[i].y2,
- flags);
-
-
- if ( flags & MGA_CLEAR_FRONT )
- {
- if (MGA_VERBOSE)
- DRM_DEBUG("clear front\n");
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
- PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_FCOL, buf_priv->clear_color);
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
- }
-
- if ( flags & MGA_CLEAR_BACK ) {
- if (MGA_VERBOSE) DRM_DEBUG("clear back\n");
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
- PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_FCOL, buf_priv->clear_color);
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
- }
-
- if ( flags & MGA_CLEAR_DEPTH )
- {
- if (MGA_VERBOSE) DRM_DEBUG("clear depth\n");
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
- PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_FCOL, buf_priv->clear_zval);
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
- PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
- }
- }
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
-static void mga_dma_dispatch_swap( 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_sarea_t *sarea_priv = dev_priv->sarea_priv;
- int nbox = buf_priv->nbox;
- xf86drmClipRectRec *pbox = buf_priv->boxes;
- int use_agp = PDEA_pagpxfer_enable;
- int i;
-
- PRIMLOCALS;
- PRIMRESET( dev_priv );
- PRIMGETPTR( dev_priv );
-
- PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
- PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
- PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
- PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2);
-
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG(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/2;
-
- if (MGA_VERBOSE)
- DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
- pbox[i].x1,
- pbox[i].y1,
- pbox[i].x2,
- pbox[i].y2);
-
- PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
- PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
- PRIMOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16));
- PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h);
- }
-
- PRIMOUTREG( MGAREG_SRCORG, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
-#if 0
-void mga_force_reset(drm_device_t *dev)
-{
- DRM_DEBUG("mga_force_reset\n");
- MGA_WRITE(0x1e40, 0x00000001);
- mga_wait_usec(10);
- MGA_WRITE(0x1e40, 0x00000000);
-}
-#endif
-
-static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf )
-{
- drm_mga_private_t *dev_priv = dev->dev_private;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- int use_agp = PDEA_pagpxfer_enable;
-
- PRIMLOCALS;
- PRIMRESET( dev_priv );
- PRIMGETPTR( dev_priv );
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_DMAPAD, 0);
- PRIMOUTREG( MGAREG_SOFTRAP, 0);
- PRIMADVANCE(dev_priv);
-
- if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
- while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) ;
- sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
- }
-
- mga_flush_write_combine();
- MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL);
- MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-}
-
/* Frees dispatch lock */
static inline void mga_dma_quiescent(drm_device_t *dev)
{
@@ -989,13 +645,10 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
__volatile__ unsigned int *status =
(__volatile__ unsigned int *)dev_priv->status_page;
-
+
while(1) {
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- break;
- } else {
- atomic_dec(&dev_priv->dispatch_lock);
+ if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
+ break;
}
}
@@ -1005,298 +658,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1],
dev_priv->last_sync_tag);
sarea_priv->dirty |= MGA_DMA_FLUSH;
- atomic_dec(&dev_priv->dispatch_lock);
-}
-
-/* Keeps dispatch lock held */
-
-static inline int mga_dma_is_ready(drm_device_t *dev)
-{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-
- mga_reset_abort(dev);
-
- atomic_inc(&dev_priv->dispatch_lock);
- if(atomic_read(&dev_priv->dispatch_lock) == 1) {
- /* We got the lock */
- while((MGA_READ(MGAREG_STATUS) & 0x00020000) != 0x00020000) ;
- 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_inc(&dev->total_irq);
- MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
- atomic_dec(&dev_priv->dispatch_lock);
-
- /* 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);
-
- /* Dispatch new buffer */
- queue_task(&dev->tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
-
-}
-
-/* Only called by mga_dma_schedule. */
-static int mga_do_dma(drm_device_t *dev, int locked)
-{
- drm_buf_t *buf;
- int retcode = 0;
- drm_device_dma_t *dma = dev->dma;
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_mga_buf_priv_t *buf_priv;
- drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-
- if (MGA_VERBOSE) DRM_DEBUG("mga_do_dma\n");
- if (test_and_set_bit(0, &dev->dma_flag)) {
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_do_dma - busy\n");
- atomic_inc(&dma->total_missed_dma);
- return -EBUSY;
- }
-
- if (!dma->next_buffer) {
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_do_dma - no next buffer\n");
- DRM_ERROR("No next_buffer\n");
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- buf = dma->next_buffer;
-
- if (MGA_VERBOSE)
- DRM_DEBUG("context %d, buffer %d\n", buf->context, buf->idx);
-
- if (buf->list == DRM_LIST_RECLAIM) {
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_do_dma - reclaim\n");
-
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- atomic_dec(&dev_priv->pending_bufs);
- if(!(atomic_read(&dev_priv->pending_bufs))) {
- wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue);
- }
- clear_bit(0, &dev->dma_flag);
- return -EINVAL;
- }
-
- if (!buf->used) {
- DRM_ERROR("0 length buffer\n");
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- clear_bit(0, &dev->dma_flag);
- return 0;
- }
-
- if (mga_dma_is_ready(dev) == 0) {
- DRM_DEBUG("mga_do_dma - not ready\n");
- clear_bit(0, &dev->dma_flag);
- return -EBUSY;
- }
-
- /* Always hold the hardware lock while dispatching.
- */
- if ( !locked &&
- !atomic_read(&dev_priv->in_flush) &&
- !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT))
- {
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_do_dma - didn't get lock\n");
- atomic_inc(&dma->total_missed_lock);
- clear_bit(0, &dev->dma_flag);
- atomic_dec(&dev_priv->dispatch_lock);
- DRM_DEBUG("NOT LOCKED\n");
- return -EBUSY;
- }
-
- dma->next_queue = dev->queuelist[DRM_KERNEL_CONTEXT];
- drm_clear_next_buffer(dev);
- buf->pending = 1;
- buf->waiting = 0;
- buf->list = DRM_LIST_PEND;
-
- buf_priv = buf->dev_private;
- sarea_priv->last_dispatch = buf_priv->age;
-
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_do_dma - type %d age %d\n",
- buf_priv->dma_type,
- buf_priv->age);
-
-
- switch (buf_priv->dma_type) {
- case MGA_DMA_GENERAL:
- mga_dma_dispatch_general(dev, buf);
- break;
- case MGA_DMA_VERTEX:
- mga_dma_dispatch_vertex(dev, buf);
- break;
-/* case MGA_DMA_SETUP: */
-/* mga_dma_dispatch_setup(dev, address, length); */
-/* break; */
- case MGA_DMA_ILOAD:
- mga_dma_dispatch_tex_blit(dev, buf);
- break;
- case MGA_DMA_SWAP:
- mga_dma_dispatch_swap(dev, buf);
- break;
- case MGA_DMA_CLEAR:
- mga_dma_dispatch_clear(dev, buf);
- break;
- case MGA_DMA_DISCARD:
- mga_dma_dispatch_bad(dev, buf);
- break;
- default:
- DRM_DEBUG("bad buffer type %x in dispatch\n", buf_priv->dma_type);
- break;
- }
-
- atomic_dec(&dev_priv->pending_bufs);
-
- if(dma->this_buffer) {
- if (MGA_VERBOSE) DRM_DEBUG("mga_do_dma - freeing this_buffer\n");
- drm_free_buffer(dev, dma->this_buffer);
- }
-
- dma->this_buffer = buf;
-
- atomic_add(buf->used, &dma->total_bytes);
- atomic_inc(&dma->total_dmas);
- if (!locked &&
- !atomic_read(&dev_priv->in_flush)) {
- if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
- }
-
- clear_bit(0, &dev->dma_flag);
-
- if(!(atomic_read(&dev_priv->pending_bufs))) {
- wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue);
- }
-
- /* We hold the dispatch lock until the interrupt handler
- * frees it
- */
- return retcode;
-}
-
-static void mga_dma_schedule_tq_wrapper(void *dev)
-{
- mga_dma_schedule(dev, 0);
-}
-
-int mga_dma_schedule(drm_device_t *dev, int locked)
-{
- drm_queue_t *q;
- drm_buf_t *buf;
- int retcode = 0;
- int processed = 0;
- int missed;
- int expire = 20;
- drm_device_dma_t *dma = dev->dma;
- drm_mga_private_t *dev_priv = dev->dev_private;
-
-
- if (MGA_VERBOSE)
- DRM_DEBUG("mga_dma_schedule\n");
-
- if (test_and_set_bit(0, &dev->interrupt_flag)) {
- /* Not reentrant */
- atomic_inc(&dma->total_missed_sched);
- return -EBUSY;
- }
- missed = atomic_read(&dma->total_missed_sched);
-
-again:
- /* There is only one queue:
- */
- if (!dma->next_buffer && DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
- q = dev->queuelist[DRM_KERNEL_CONTEXT];
- buf = drm_waitlist_get(&q->waitlist);
- dma->next_buffer = buf;
- dma->next_queue = q;
- if (buf && buf->list == DRM_LIST_RECLAIM) {
- if (MGA_VERBOSE)
- DRM_DEBUG("reclaiming in mga_dma_schedule\n");
- drm_clear_next_buffer(dev);
- drm_free_buffer(dev, buf);
- atomic_dec(&dev_priv->pending_bufs);
- if (MGA_VERBOSE)
- DRM_DEBUG("pending bufs : %d\n", atomic_read(&dev_priv->pending_bufs));
- if(!(atomic_read(&dev_priv->pending_bufs))) {
- wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue);
- }
- dma->next_buffer = NULL;
- goto again;
- }
- }
-
- if (dma->next_buffer) {
- if (!(retcode = mga_do_dma(dev, locked)))
- ++processed;
- }
- if(!(atomic_read(&dev_priv->pending_bufs))) {
- wake_up_interruptible(&dev->queuelist[DRM_KERNEL_CONTEXT]->flush_queue);
- }
-
-
- /* Try again if we succesfully dispatched a buffer, or if someone
- * tried to schedule while we were working.
- */
- if (--expire) {
- if (missed != atomic_read(&dma->total_missed_sched)) {
- atomic_inc(&dma->total_lost);
- if (mga_dma_is_ready_no_hold(dev))
- goto again;
- }
-
- if (processed && mga_dma_is_ready_no_hold(dev)) {
- atomic_inc(&dma->total_lost);
- processed = 0;
- goto again;
- }
- }
-
- clear_bit(0, &dev->interrupt_flag);
-
- return retcode;
+ clear_bit(0, &dev_priv->dispatch_lock);
}
int mga_irq_install(drm_device_t *dev, int irq)
@@ -1323,15 +685,11 @@ int mga_irq_install(drm_device_t *dev, int irq)
dev->dma->this_buffer = NULL;
dev->tq.next = NULL;
dev->tq.sync = 0;
- dev->tq.routine = mga_dma_schedule_tq_wrapper;
+ dev->tq.routine = mga_dma_task_queue;
dev->tq.data = dev;
/* Before installing handler */
-#if 0
- MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
-#endif
MGA_WRITE(MGAREG_IEN, 0);
-
/* Install handler */
if ((retcode = request_irq(dev->irq,
mga_dma_service,
@@ -1343,11 +701,9 @@ int mga_irq_install(drm_device_t *dev, int irq)
up(&dev->struct_sem);
return retcode;
}
-
/* After installing handler */
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0x00000001);
-
return 0;
}
@@ -1361,17 +717,10 @@ int mga_irq_uninstall(drm_device_t *dev)
up(&dev->struct_sem);
if (!irq) return -EINVAL;
-
- if (MGA_VERBOSE)
- DRM_DEBUG("remove irq handler %d\n", irq);
-
+ DRM_DEBUG("remove irq handler %d\n", irq);
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
MGA_WRITE(MGAREG_IEN, 0);
-#if 0
- MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
-#endif
free_irq(irq, dev);
-
return 0;
}
@@ -1394,46 +743,58 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
}
}
-int mga_flush_queue(drm_device_t *dev)
+static int mga_flush_queue(drm_device_t *dev)
{
DECLARE_WAITQUEUE(entry, current);
- drm_queue_t *q = dev->queuelist[DRM_KERNEL_CONTEXT];
- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
int ret = 0;
-
- if (MGA_VERBOSE) {
- DRM_DEBUG("mga_flush_queue\n");
- DRM_DEBUG("pending_bufs : %d\n",
- atomic_read(&dev_priv->pending_bufs));
- }
- if(atomic_read(&dev_priv->pending_bufs) != 0) {
- if (MGA_VERBOSE)
- DRM_DEBUG("got to flush\n");
- current->state = TASK_INTERRUPTIBLE;
- add_wait_queue(&q->flush_queue, &entry);
- for (;;) {
- if (!atomic_read(&dev_priv->pending_bufs)) break;
- if (MGA_VERBOSE)
- DRM_DEBUG("Calling schedule from flush_queue : %d\n",
- atomic_read(&dev_priv->pending_bufs));
+ if(dev_priv == NULL) {
+ return 0;
+ }
+
+ if(dev_priv->next_prim->num_dwords != 0) {
+ atomic_set(&dev_priv->in_flush, 1);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&dev_priv->flush_queue, &entry);
+ for (;;) {
+ if (atomic_read(&dev_priv->in_flush) == 0) break;
mga_dma_schedule(dev, 0);
- schedule_timeout((HZ/60));
- atomic_inc(&dev->total_sleeps);
- if (signal_pending(current)) {
- ret = -EINTR; /* Can't restart */
- break;
+ schedule_timeout(HZ/60);
+ if (signal_pending(current)) {
+ ret = -EINTR; /* Can't restart */
+ break;
}
}
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev_priv->flush_queue, &entry);
+ }
+ return ret;
+}
- if (MGA_VERBOSE)
- DRM_DEBUG("Exited out of schedule from flush_queue\n");
+/* Must be called with the lock held */
+void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
- current->state = TASK_RUNNING;
- remove_wait_queue(&q->flush_queue, &entry);
+ if (!dma) return;
+ if(dev->dev_private == NULL) return;
+
+ mga_flush_queue(dev);
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[ i ];
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+
+ if (buf->pid == pid) {
+ if(buf_priv == NULL) return;
+ /* Only buffers that need to get reclaimed ever
+ * get set to free */
+ if(buf_priv->age == MGA_BUF_USED)
+ buf_priv->age = MGA_BUF_FREE;
+ }
}
-
- return ret;
}
int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -1442,7 +803,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
DECLARE_WAITQUEUE(entry, current);
int ret = 0;
drm_lock_t lock;
@@ -1459,7 +819,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
lock.context, current->pid, dev->lock.hw_lock->lock,
lock.flags);
-
if (lock.context < 0) {
return -EINVAL;
}
@@ -1486,7 +845,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
/* Contention */
atomic_inc(&dev->total_sleeps);
current->state = TASK_INTERRUPTIBLE;
- current->policy |= SCHED_YIELD;
DRM_DEBUG("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
@@ -1501,10 +859,8 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
if (!ret) {
if (lock.flags & _DRM_LOCK_QUIESCENT) {
DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
- atomic_set(&dev_priv->in_flush, 1);
mga_flush_queue(dev);
mga_dma_quiescent(dev);
- atomic_set(&dev_priv->in_flush, 0);
}
}
@@ -1520,11 +876,6 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp,
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
DRM_DEBUG("mga_flush_ioctl\n");
- atomic_set(&dev_priv->in_flush, 1);
mga_flush_queue(dev);
-#if 0
- mga_dma_quiescent(dev);
-#endif
- atomic_set(&dev_priv->in_flush, 0);
return 0;
}
diff --git a/linux/mga_dma.h b/linux/mga_dma.h
index e91f608b..99fdf4a5 100644
--- a/linux/mga_dma.h
+++ b/linux/mga_dma.h
@@ -2,35 +2,17 @@
#define MGA_DMA_H
#include "mga_drm_public.h"
+typedef enum {
+ TT_GENERAL,
+ TT_BLIT,
+ TT_VECTOR,
+ TT_VERTEX
+} transferType_t;
-
-/* Isn't this fun - we copy the outstanding card state for every
- * MGA_DMA_VERTEX buffer. This has to be fixed asap by emitting
- * primary dma commands in the 'vertex_dma' ioctl.
- */
typedef struct {
- int dma_type;
-
- unsigned int ContextState[MGA_CTX_SETUP_SIZE];
- unsigned int ServerState[MGA_2D_SETUP_SIZE];
- unsigned int TexState[2][MGA_TEX_SETUP_SIZE];
- unsigned int WarpPipe;
- unsigned int dirty;
-
- unsigned short clear_color;
- unsigned short clear_zval;
- unsigned int clear_flags;
-
- unsigned int vertex_real_idx;
- unsigned int vertex_discard;
-
unsigned int age;
-
- unsigned int nbox;
- xf86drmClipRectRec boxes[MGA_NR_SAREA_CLIPRECTS];
} drm_mga_buf_priv_t;
-
#define MGA_DMA_GENERAL 0 /* not used */
#define MGA_DMA_VERTEX 1
#define MGA_DMA_SETUP 2
@@ -39,7 +21,6 @@ typedef struct {
#define MGA_DMA_SWAP 5 /* placeholder */
#define MGA_DMA_DISCARD 6
-
#define DWGREG0 0x1c00
#define DWGREG0_END 0x1dff
#define DWGREG1 0x2c00
@@ -50,93 +31,72 @@ typedef struct {
#define ADRINDEX1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
#define ADRINDEX(r) (ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
-
-
#define MGA_VERBOSE 0
+#define MGA_NUM_PRIM_BUFS 4
+/* Primary buffer versions of above -- pretty similar really.
+ */
+#define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
+ int outcount, num_dwords
-/* 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; \
- if (MGA_VERBOSE) \
- printk(KERN_INFO "DMAGETPTR in %s, start %d\n", \
- __FUNCTION__, num_dwords); \
+#define PRIM_OVERFLOW(dev, dev_priv, length) do { \
+drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+if( (tmp_buf->max_dwords - tmp_buf->num_dwords) < length || \
+ tmp_buf->sec_used > (MGA_DMA_BUF_NR / 2)) { \
+ mga_advance_primary(dev); \
+ mga_dma_schedule(dev, 1); \
+ } \
} while(0)
-#define DMAADVANCE(buf) do { \
- if (MGA_VERBOSE) \
- printk(KERN_INFO "DMAADVANCE\n"); \
- buf->used = num_dwords * 4; \
+#define PRIMGETPTR(dev_priv) do { \
+drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+if(MGA_VERBOSE) \
+printk("PRIMGETPTR in %s\n", __FUNCTION__); \
+dma_ptr = tmp_buf->current_dma_ptr; \
+num_dwords = tmp_buf->num_dwords; \
+phys_head = tmp_buf->phys_head; \
+outcount = 0; \
} while(0)
-#define DMAOUTREG(reg, val) do { \
- tempIndex[outcount]=ADRINDEX(reg); \
- dma_ptr[++outcount] = val; \
- if (MGA_VERBOSE) \
- printk(KERN_INFO \
- " DMAOUT %d: 0x%x -- 0x%x\n", \
- num_dwords +1+outcount, ADRINDEX(reg), val); \
- if (outcount == 4) { \
- outcount = 0; \
- dma_ptr[0] = *(u32 *)tempIndex; \
- dma_ptr+=5; \
- num_dwords += 5; \
- } \
-}while (0)
-
-
-
-/* Primary buffer versions of above -- pretty similar really.
- */
-#define PRIMLOCALS u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
- int outcount, num_dwords
-
-#define PRIMRESET(dev_priv) do { \
- dev_priv->prim_num_dwords = 0; \
- dev_priv->current_dma_ptr = dev_priv->prim_head; \
-} while (0)
-
-#define PRIMGETPTR(dev_priv) do { \
- dma_ptr = dev_priv->current_dma_ptr; \
- phys_head = dev_priv->prim_phys_head; \
- num_dwords = dev_priv->prim_num_dwords; \
- outcount = 0; \
- if (MGA_VERBOSE) \
- printk(KERN_INFO "PRIMGETPTR in %s, start %d\n", \
- __FUNCTION__, num_dwords); \
-} while (0)
+#define PRIMPTR(prim_buf) do { \
+if(MGA_VERBOSE) \
+printk("PRIMPTR in %s\n", __FUNCTION__); \
+dma_ptr = prim_buf->current_dma_ptr; \
+num_dwords = prim_buf->num_dwords; \
+phys_head = prim_buf->phys_head; \
+outcount = 0; \
+} while(0)
-#define PRIMADVANCEPAD(dev_priv) do { \
- while(outcount & 3) { \
- if (MGA_VERBOSE) \
- printk(KERN_INFO "PAD %d\n", \
- num_dwords + 1 + outcount); \
- tempIndex[outcount++]=0x15; \
- } \
- \
- if (MGA_VERBOSE) \
- printk(KERN_INFO "PRIMADVANCEPAD\n"); \
- dev_priv->prim_num_dwords = num_dwords; \
- dev_priv->current_dma_ptr = dma_ptr; \
-} while (0)
+#define PRIMFINISH(prim_buf) do { \
+ if (MGA_VERBOSE) { \
+ printk(KERN_INFO "PRIMFINISH in %s\n", __FUNCTION__); \
+ if (outcount & 3) \
+ printk(KERN_INFO " --- truncation\n"); \
+ } \
+ prim_buf->num_dwords = num_dwords; \
+ prim_buf->current_dma_ptr = dma_ptr; \
+} while(0)
#define PRIMADVANCE(dev_priv) do { \
+drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
if (MGA_VERBOSE) { \
- printk(KERN_INFO "PRIMADVANCE\n"); \
+ printk(KERN_INFO "PRIMADVANCE in %s\n", __FUNCTION__); \
if (outcount & 3) \
printk(KERN_INFO " --- truncation\n"); \
} \
- dev_priv->prim_num_dwords = num_dwords; \
- dev_priv->current_dma_ptr = dma_ptr; \
+ tmp_buf->num_dwords = num_dwords; \
+ tmp_buf->current_dma_ptr = dma_ptr; \
} while (0)
+#define PRIMUPDATE(dev_priv) do { \
+drm_mga_prim_buf_t *tmp_buf = \
+ dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
+ tmp_buf->sec_used++; \
+} while (0)
#define PRIMOUTREG(reg, val) do { \
tempIndex[outcount]=ADRINDEX(reg); \
@@ -153,9 +113,6 @@ typedef struct {
} \
}while (0)
-
-
-
#define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | \
DC_sgnzero_enable | DC_shftzero_enable | \
(0xC << DC_bop_SHIFT) | DC_clipdis_enable | \
diff --git a/linux/mga_drm_public.h b/linux/mga_drm_public.h
index 7a69afc2..1c0a4a9e 100644
--- a/linux/mga_drm_public.h
+++ b/linux/mga_drm_public.h
@@ -204,10 +204,6 @@ typedef struct
int ctxOwner;
mgaTexRegion texList[MGA_NR_TEX_REGIONS+1];
int texAge;
-
-
-
-
} drm_mga_sarea_t;
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index c4eb6cf3..fbc07b5a 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -33,6 +33,18 @@
#define _MGA_DRV_H_
#include "mga_drm_public.h"
+typedef struct {
+ unsigned int num_dwords;
+ unsigned int max_dwords;
+ u32 *current_dma_ptr;
+ u32 *head;
+ u32 phys_head;
+ int sec_used;
+ int idx;
+ u32 in_use;
+ atomic_t force_fire;
+} drm_mga_prim_buf_t;
+
typedef struct _drm_mga_private {
int reserved_map_idx;
int buffer_map_idx;
@@ -52,26 +64,26 @@ typedef struct _drm_mga_private {
mgaWarpIndex WarpIndex[MGA_MAX_G400_PIPES];
unsigned int WarpPipe;
__volatile__ unsigned long softrap_age;
- atomic_t dispatch_lock;
- atomic_t pending_bufs;
+ u32 dispatch_lock;
atomic_t in_flush;
+ atomic_t in_wait;
unsigned int last_sync_tag;
unsigned int sync_tag;
void *status_page;
unsigned long real_status_page;
- void *ioremap;
- u32 *prim_head;
- u32 *current_dma_ptr;
- u32 prim_phys_head;
- int prim_num_dwords;
- int prim_max_dwords;
+ u8 *ioremap;
+ drm_mga_prim_buf_t **prim_bufs;
+ drm_mga_prim_buf_t *next_prim;
+ drm_mga_prim_buf_t *last_prim;
+ drm_mga_prim_buf_t *current_prim;
+ int current_prim_idx;
struct pci_dev *device;
-
+ wait_queue_head_t flush_queue; /* Processes waiting until flush */
+ wait_queue_head_t wait_queue; /* Processes waiting until interrupt */
/* Some validated register values:
*/
u32 mAccess;
-
} drm_mga_private_t;
/* mga_drv.c */
@@ -97,13 +109,17 @@ extern int mga_control(struct inode *inode, struct file *filp,
extern int mga_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+/* mga_dma_init does init and release */
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);
extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-/* mga_dma_init does init and release */
+extern unsigned int mga_create_sync_tag(drm_mga_private_t *dev_priv);
+extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
+extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+extern int mga_advance_primary(drm_device_t *dev);
/* mga_bufs.c */
diff --git a/linux/mga_state.c b/linux/mga_state.c
index ad72a4dd..ef3f7668 100644
--- a/linux/mga_state.c
+++ b/linux/mga_state.c
@@ -35,13 +35,13 @@
#include "mga_drv.h"
#include "mgareg_flags.h"
#include "mga_dma.h"
-#include "mga_state.h"
#include "drm.h"
-void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
+static void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
{
PRIMLOCALS;
+ /* This takes a max of 10 dwords */
PRIMGETPTR( dev_priv );
/* The G400 seems to have an issue with the second WARP not
@@ -52,8 +52,8 @@ void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
PRIMOUTREG( MGAREG_DMAPAD, 0 );
PRIMOUTREG( MGAREG_DMAPAD, 0 );
- PRIMOUTREG( MGAREG_DWGSYNC, 0 );
- PRIMOUTREG( MGAREG_DWGSYNC, 0 );
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
}
PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) );
@@ -64,13 +64,13 @@ void mgaEmitClipRect( drm_mga_private_t *dev_priv, xf86drmClipRectRec *box )
PRIMADVANCE( dev_priv );
}
-
-static void mgaEmitContext(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+static void mgaEmitContext(drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->ContextState;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->ContextState;
PRIMLOCALS;
+ /* This takes a max of 15 dwords */
PRIMGETPTR( dev_priv );
PRIMOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] );
@@ -81,9 +81,7 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv,
PRIMOUTREG( MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL] );
PRIMOUTREG( MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR] );
PRIMOUTREG( MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG] );
-
PRIMOUTREG( MGAREG_ZORG, dev_priv->depthOffset ); /* invarient */
-/* PRIMOUTREG( MGAREG_DMAPAD, 0 ); */
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] );
@@ -92,16 +90,18 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv,
PRIMOUTREG( MGAREG_DMAPAD, 0 );
}
- PRIMADVANCE( dev_priv ); /* padded */
+ PRIMADVANCE( dev_priv );
}
-static void mgaG200EmitTex( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG200EmitTex( drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->TexState[0];
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->TexState[0];
PRIMLOCALS;
PRIMGETPTR( dev_priv );
+
+ /* This takes 20 dwords */
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
@@ -126,14 +126,16 @@ static void mgaG200EmitTex( drm_mga_private_t *dev_priv,
PRIMADVANCE( dev_priv );
}
-static void mgaG400EmitTex0( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG400EmitTex0( drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->TexState[0];
- int multitex = buf_priv->WarpPipe & MGA_T2;
-
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->TexState[0];
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
PRIMLOCALS;
+
PRIMGETPTR( dev_priv );
+
+ /* This takes a max of 30 dwords */
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
@@ -167,21 +169,20 @@ static void mgaG400EmitTex0( drm_mga_private_t *dev_priv,
PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
-
PRIMADVANCE( dev_priv );
}
#define TMC_map1_enable 0x80000000
-
-static void mgaG400EmitTex1( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG400EmitTex1( drm_mga_private_t *dev_priv )
{
- unsigned int *regs = buf_priv->TexState[1];
-
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int *regs = sarea_priv->TexState[1];
PRIMLOCALS;
+
PRIMGETPTR(dev_priv);
+ /* This takes 25 dwords */
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable);
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
@@ -207,19 +208,19 @@ static void mgaG400EmitTex1( drm_mga_private_t *dev_priv,
PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
- PRIMADVANCE( dev_priv ); /* padded */
+ PRIMADVANCE( dev_priv );
}
-
-static void mgaG400EmitPipe(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+static void mgaG400EmitPipe(drm_mga_private_t *dev_priv )
{
- unsigned int pipe = buf_priv->WarpPipe;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->WarpPipe;
float fParam = 12800.0f;
PRIMLOCALS;
PRIMGETPTR(dev_priv);
+ /* This takes 25 dwords */
/* Establish vertex size.
*/
@@ -259,13 +260,15 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv,
PRIMADVANCE(dev_priv);
}
-static void mgaG200EmitPipe( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv )
+static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
{
- unsigned int pipe = buf_priv->WarpPipe;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->WarpPipe;
PRIMLOCALS;
PRIMGETPTR(dev_priv);
+
+ /* This takes 15 dwords */
PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
PRIMOUTREG(MGAREG_WVRTXSZ, 7);
@@ -287,60 +290,94 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv,
PRIMADVANCE(dev_priv);
}
-void mgaEmitState( drm_mga_private_t *dev_priv, drm_mga_buf_priv_t *buf_priv )
+static void mgaEmitState( drm_mga_private_t *dev_priv )
{
- unsigned int dirty = buf_priv->dirty;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
- int multitex = buf_priv->WarpPipe & MGA_T2;
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
-/* printk("BUF PIPE: %x LOADED PIPE: %x\n", */
-/* buf_priv->WarpPipe, dev_priv->WarpPipe); */
+/* DRM_DEBUG("BUF PIPE: %x LOADED PIPE: %x\n", */
+/* sarea_priv->WarpPipe, dev_priv->WarpPipe); */
- if (buf_priv->WarpPipe != dev_priv->WarpPipe) {
- mgaG400EmitPipe( dev_priv, buf_priv );
- dev_priv->WarpPipe = buf_priv->WarpPipe;
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ mgaG400EmitPipe( dev_priv );
+ dev_priv->WarpPipe = sarea_priv->WarpPipe;
}
if (dirty & MGA_UPLOAD_CTX)
- mgaEmitContext( dev_priv, buf_priv );
+ mgaEmitContext( dev_priv );
if (dirty & MGA_UPLOAD_TEX0)
- mgaG400EmitTex0( dev_priv, buf_priv );
+ mgaG400EmitTex0( dev_priv );
if ((dirty & MGA_UPLOAD_TEX1) && multitex)
- mgaG400EmitTex1( dev_priv, buf_priv );
+ mgaG400EmitTex1( dev_priv );
} else {
- if (buf_priv->WarpPipe != dev_priv->WarpPipe) {
- mgaG200EmitPipe( dev_priv, buf_priv );
- dev_priv->WarpPipe = buf_priv->WarpPipe;
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ mgaG200EmitPipe( dev_priv );
+ dev_priv->WarpPipe = sarea_priv->WarpPipe;
}
if (dirty & MGA_UPLOAD_CTX)
- mgaEmitContext( dev_priv, buf_priv );
+ mgaEmitContext( dev_priv );
if (dirty & MGA_UPLOAD_TEX0)
- mgaG200EmitTex( dev_priv, buf_priv );
- }
+ mgaG200EmitTex( dev_priv );
+ }
+
+ sarea_priv->dirty = 0;
}
+/* WARNING if you change any of the state functions
+ * verify these numbers */
+static int mgaCalcState( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ int size = 0;
+
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
+
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ size += 25;
+ }
+ if (dirty & MGA_UPLOAD_CTX) {
+ size += 15;
+ }
+ if (dirty & MGA_UPLOAD_TEX0) {
+ size += 30;
+ }
+ if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+ size += 25;
+ }
+ } else {
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
+ size += 15;
+ }
+ if (dirty & MGA_UPLOAD_CTX) {
+ size += 15;
+ }
+ if (dirty & MGA_UPLOAD_TEX0) {
+ size += 20;
+ }
+ }
+ return size;
+}
/* Disallow all write destinations except the front and backbuffer.
*/
-static int mgaCopyContext(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv)
+static int mgaVerifyContext(drm_mga_private_t *dev_priv )
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned int *regs = buf_priv->ContextState;
-
- memcpy(regs,
- sarea_priv->ContextState,
- sizeof(buf_priv->ContextState));
+ unsigned int *regs = sarea_priv->ContextState;
if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
- printk("BAD DSTORG: %x (front %x, back %x)\n\n",
+ DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
dev_priv->backOffset);
regs[MGA_CTXREG_DSTORG] = 0;
@@ -350,79 +387,531 @@ static int mgaCopyContext(drm_mga_private_t *dev_priv,
return 0;
}
-
/* Disallow texture reads from PCI space.
*/
-static int mgaCopyTex(drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv,
+static int mgaVerifyTex(drm_mga_private_t *dev_priv,
int unit)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- memcpy(buf_priv->TexState[unit], sarea_priv->TexState[unit],
- sizeof(buf_priv->TexState[0]));
-
- if ((buf_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
- printk("BAD TEXREG_ORG: %x, unit %d\n",
+ if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
+ DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
sarea_priv->TexState[unit][MGA_TEXREG_ORG],
unit);
- buf_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
+ sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
return -1;
}
return 0;
}
-
-int mgaCopyAndVerifyState( drm_mga_private_t *dev_priv,
- drm_mga_buf_priv_t *buf_priv,
- unsigned int interested )
+static int mgaVerifyState( drm_mga_private_t *dev_priv )
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned int dirty = interested & sarea_priv->dirty;
+ unsigned int dirty = sarea_priv->dirty;
int rv = 0;
- buf_priv->dirty = dirty;
- sarea_priv->dirty &= ~interested;
-
- buf_priv->WarpPipe = sarea_priv->WarpPipe;
-
-/* if (interested & MGA_UPLOAD_CLIPRECTS) */
- {
- buf_priv->nbox = sarea_priv->nbox;
-
- if (buf_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
- buf_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
-
- if (buf_priv->nbox)
- memcpy( buf_priv->boxes,
- sarea_priv->boxes,
- buf_priv->nbox * sizeof(xf86drmClipRectRec));
- }
+ if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
if (dirty & MGA_UPLOAD_CTX)
- rv |= mgaCopyContext( dev_priv, buf_priv );
+ rv |= mgaVerifyContext( dev_priv );
if (dirty & MGA_UPLOAD_TEX0)
- rv |= mgaCopyTex( dev_priv, buf_priv, 0 );
+ rv |= mgaVerifyTex( dev_priv, 0 );
if (dev_priv->chipset == MGA_CARD_TYPE_G400)
{
if (dirty & MGA_UPLOAD_TEX1)
- rv |= mgaCopyTex( dev_priv, buf_priv, 1 );
+ rv |= mgaVerifyTex( dev_priv, 1 );
if (dirty & MGA_UPLOAD_PIPE)
- rv |= (buf_priv->WarpPipe > MGA_MAX_G400_PIPES);
+ rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
}
else
{
if (dirty & MGA_UPLOAD_PIPE)
- rv |= (buf_priv->WarpPipe > MGA_MAX_G200_PIPES);
+ rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
}
+ return rv == 0;
+}
+#if 0
+/* This is very broken */
- return rv == 0;
+static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf, u16 x1,
+ u16 x2, u16 y1, u16 y2, unsigned int destOrg,
+ unsigned int mAccess, unsigned int pitch)
+{
+ int use_agp = PDEA_pagpxfer_enable;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned long address = (unsigned long)buf->bus_address;
+ int length;
+ int width, height;
+ int texperdword = 0;
+ PRIMLOCALS;
+
+ switch((maccess & 0x00000003)) {
+ case 0:
+ texperdword = 4;
+ break;
+ case 1:
+ texperdword = 2;
+ break;
+ case 2:
+ texperdword = 1;
+ break;
+ }
+
+ length = (y2 - y1) * (x2 - x1) / texperdword;
+
+ x2 = (x2 + (texperdword - 1)) & ~(texperdword - 1);
+ x1 = (x1 + (texperdword - 1)) & ~(texperdword - 1);
+ width = x2 - x1;
+ height = y2 - y1;
+
+ PRIMRESET(dev_priv);
+ PRIMGETPTR(dev_priv);
+ PRIMOUTREG(MGAREG_DSTORG, dstorg);
+ PRIMOUTREG(MGAREG_MACCESS, maccess);
+ PRIMOUTREG(MGAREG_PITCH, pitch);
+ PRIMOUTREG(MGAREG_YDSTLEN, (y1 << 16) | height);
+
+ PRIMOUTREG(MGAREG_FXBNDRY, ((x1+width-1) << 16) | x1);
+ PRIMOUTREG(MGAREG_AR0, width * height - 1);
+ PRIMOUTREG(MGAREG_AR3, 0 );
+ PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, MGA_ILOAD_CMD);
+
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_SRCORG, ((__u32)address) | TT_BLIT);
+ PRIMOUTREG(MGAREG_SECEND, ((__u32)(address + length)) | use_agp);
+
+ PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
+ PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
+ PRIMOUTREG(MGAREG_PITCH, dev_priv->stride);
+ PRIMOUTREG(MGAREG_AR0, 0 );
+
+ PRIMOUTREG(MGAREG_AR3, 0 );
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_SOFTRAP, 0);
+ PRIMADVANCE(dev_priv);
}
+#endif
+
+static inline void mga_dma_dispatch_vertex(drm_device_t *dev,
+ drm_buf_t *buf, int real_idx,
+ int idx)
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned long address = (unsigned long)buf->bus_address;
+ int length = buf->used;
+ int use_agp = PDEA_pagpxfer_enable;
+ int i = 0;
+ PRIMLOCALS;
+ int primary_needed;
+
+ DRM_DEBUG("dispatch vertex %d addr 0x%lx, length 0x%x nbox %d dirty %x\n",
+ buf->idx, address, length, sarea_priv->nbox, sarea_priv->dirty);
+
+ primary_needed = mgaCalcState( dev_priv );
+ /* Primary needed is in dwords */
+ if (sarea_priv->nbox == 0) {
+ primary_needed += 5;
+ } else {
+ primary_needed += (5 * sarea_priv->nbox);
+ primary_needed += (10 * sarea_priv->nbox);
+ }
+ primary_needed += 5; /* For the dwgsync */
+ PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+ if(real_idx == idx) {
+ buf_priv->age = dev_priv->last_sync_tag;
+ }
+ mgaEmitState( dev_priv );
+ do {
+ if (i < sarea_priv->nbox) {
+ DRM_DEBUG("idx %d Emit box %d/%d:"
+ "%d,%d - %d,%d\n",
+ buf->idx,
+ i, sarea_priv->nbox,
+ sarea_priv->boxes[i].x1,
+ sarea_priv->boxes[i].y1,
+ sarea_priv->boxes[i].x2,
+ sarea_priv->boxes[i].y2);
+
+ mgaEmitClipRect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+ PRIMGETPTR(dev_priv);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SECADDRESS,
+ ((__u32)address) | TT_VERTEX);
+ PRIMOUTREG( MGAREG_SECEND,
+ (((__u32)(address + length)) |
+ use_agp));
+ PRIMADVANCE( dev_priv );
+ } while (++i < sarea_priv->nbox);
+
+ PRIMGETPTR( dev_priv );
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMADVANCE( dev_priv );
+}
+/* Not currently used
+ */
+static inline void mga_dma_dispatch_general(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;
+ unsigned long address = (unsigned long)buf->bus_address;
+ int length = buf->used;
+ int use_agp = PDEA_pagpxfer_enable;
+ PRIMLOCALS;
+
+ PRIM_OVERFLOW(dev, dev_priv, 10);
+ PRIMGETPTR(dev_priv);
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+ buf_priv->age = dev_priv->last_sync_tag;
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_SECADDRESS, ((__u32)address) | TT_GENERAL);
+ PRIMOUTREG( MGAREG_SECEND, (((__u32)(address + length)) | use_agp));
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMADVANCE(dev_priv);
+}
+
+static inline void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_zval )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ xf86drmClipRectRec *pbox = sarea_priv->boxes;
+ unsigned int cmd;
+ int i;
+ int primary_needed;
+ PRIMLOCALS;
+
+ if ( dev_priv->sgram )
+ cmd = MGA_CLEAR_CMD | DC_atype_blk;
+ else
+ cmd = MGA_CLEAR_CMD | DC_atype_rstr;
+
+ primary_needed = nbox * 35;
+ if(primary_needed == 0) primary_needed = 35;
+ PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ PRIMGETPTR( dev_priv );
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
+ for (i = 0 ; i < nbox ; i++) {
+ unsigned int height = pbox[i].y2 - pbox[i].y1;
+
+ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
+ pbox[i].x1, pbox[i].y1, pbox[i].x2,
+ pbox[i].y2, flags);
+
+ if ( flags & MGA_CLEAR_FRONT ) {
+ DRM_DEBUG("clear front\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
+ PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_FCOL, clear_color);
+ PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
+ PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_CLEAR_BACK ) {
+ DRM_DEBUG("clear back\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
+ PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_FCOL, clear_color);
+ PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
+ PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+
+ if ( flags & MGA_CLEAR_DEPTH ) {
+ DRM_DEBUG("clear depth\n");
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
+ PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_FCOL, clear_zval);
+ PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
+ PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
+ }
+ }
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMADVANCE(dev_priv);
+}
+
+static inline void mga_dma_dispatch_swap( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ xf86drmClipRectRec *pbox = sarea_priv->boxes;
+ int i;
+ int primary_needed;
+ PRIMLOCALS;
+
+ primary_needed = nbox * 5;
+ primary_needed += 15;
+ PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+ PRIMGETPTR( dev_priv );
+
+ dev_priv->last_sync_tag = mga_create_sync_tag(dev_priv);
+
+ PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
+ PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
+ PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
+ PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2);
+
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG(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/2;
+
+ DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+ pbox[i].x1, pbox[i].y1,
+ pbox[i].x2, pbox[i].y2);
+
+ PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
+ PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
+ PRIMOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16));
+ PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h);
+ }
+
+ PRIMOUTREG( MGAREG_SRCORG, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DMAPAD, 0);
+ PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+ PRIMADVANCE(dev_priv);
+}
+
+int mga_clear_bufs(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 = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+
+ drm_mga_clear_t clear;
+
+ copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear),
+ -EFAULT);
+
+ if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
+ mga_dma_dispatch_clear( dev, clear.flags,
+ clear.clear_color,
+ clear.clear_depth );
+ PRIMUPDATE(dev_priv);
+ mga_dma_schedule(dev, 1);
+ sarea_priv->last_dispatch = status[1];
+ return 0;
+}
+
+int mga_swap_bufs(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 = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+
+ if (sarea_priv->nbox >= MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
+ mga_dma_dispatch_swap( dev );
+ PRIMUPDATE(dev_priv);
+ atomic_set(&dev_priv->current_prim->force_fire, 1);
+ mga_dma_schedule(dev, 1);
+ sarea_priv->last_dispatch = status[1];
+ return 0;
+}
+
+/* This is very broken */
+int mga_iload(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_device_dma_t *dma = dev->dma;
+ 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;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+ drm_mga_iload_t iload;
+
+ copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload),
+ -EFAULT);
+ buf = dma->buflist[iload.idx];
+#if 0
+ sarea_priv->dirty |= (MGA_UPLOAD_CTX | MGA_UPLOAD_2D);
+
+ DRM_DEBUG("buf->used : %d\n", buf->used);
+
+ mga_dma_dispatch_tex_blit(dev, buf, iload.x1, iload.x2, iload.y1, iload.y2,
+ iload.destOrg, iload.mAccess, iload.pitch);
+
+ mga_dma_schedule(dev, 1);
+#endif
+ mga_freelist_put(dev, buf);
+ sarea_priv->last_dispatch = status[1];
+ return 0;
+}
+
+int mga_vertex(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 = (drm_mga_private_t *)dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_vertex_t vertex;
+
+ copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex),
+ -EFAULT);
+
+ buf = dma->buflist[ vertex.real_idx ];
+ buf_priv = buf->dev_private;
+
+ if (!mgaVerifyState(dev_priv)) {
+ if(vertex.real_idx == vertex.idx)
+ buf_priv->age = dev_priv->last_sync_tag;
+ return -EINVAL;
+ }
+
+ buf->used = vertex.real_used;
+ if(vertex.discard) {
+ buf_priv->age = dev_priv->last_sync_tag;
+ } else {
+ mga_dma_dispatch_vertex(dev, buf, vertex.real_idx,
+ vertex.idx);
+ }
+ PRIMUPDATE(dev_priv);
+ mga_dma_schedule(dev, 1);
+ sarea_priv->last_dispatch = status[1];
+ return 0;
+}
+
+static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
+{
+ int i;
+ drm_buf_t *buf;
+
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = mga_freelist_get(dev);
+ if (!buf) break;
+ buf->pid = current->pid;
+ copy_to_user_ret(&d->request_indices[i],
+ &buf->idx,
+ sizeof(buf->idx),
+ -EFAULT);
+ copy_to_user_ret(&d->request_sizes[i],
+ &buf->total,
+ sizeof(buf->total),
+ -EFAULT);
+ ++d->granted_count;
+ }
+ return 0;
+}
+
+int mga_dma(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_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;
+ __volatile__ unsigned int *status =
+ (__volatile__ unsigned int *)dev_priv->status_page;
+ int retcode = 0;
+ drm_dma_t d;
+
+ copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
+ DRM_DEBUG("%d %d: %d send, %d req\n",
+ current->pid, d.context, d.send_count, d.request_count);
+
+ /* Please don't send us buffers.
+ */
+ if (d.send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ current->pid, d.send_count);
+ return -EINVAL;
+ }
+
+ /* We'll send you buffers.
+ */
+ if (d.request_count < 0 || d.request_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ current->pid, d.request_count, dma->buf_count);
+ return -EINVAL;
+ }
+
+ d.granted_count = 0;
+
+ if (d.request_count) {
+ retcode = mga_dma_get_buffers(dev, &d);
+ }
+
+ DRM_DEBUG("%d returning, granted = %d\n",
+ current->pid, d.granted_count);
+ copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
+ sarea_priv->last_dispatch = status[1];
+ return retcode;
+}