diff --git a/linux/mga_clear.c b/linux/mga_clear.c index a4e2c501..e52ef743 100644 --- a/linux/mga_clear.c +++ b/linux/mga_clear.c @@ -42,33 +42,23 @@ * With Jeff's ringbuffer idea, it might make sense if there are only * one or two cliprects to emit straight to the primary buffer. */ -static int mgaClearBuffers(drm_device_t *dev, - int clear_color, - int clear_depth, - int flags) +static int mgaClearBuffers(drm_device_t *dev, drm_mga_clear_t *args) { drm_device_dma_t *dma = dev->dma; - drm_freelist_t *freelist = &dma->bufs[MGA_DMA_BUF_ORDER].freelist; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_buf_priv_t *buf_priv; drm_buf_t *buf; drm_dma_t d; - buf = drm_freelist_get(freelist, _DRM_DMA_WAIT); - if (!buf) return -1; - - buf->pid = current->pid; - + buf = dma->buflist[ args->idx ]; buf_priv = buf->dev_private; buf_priv->dma_type = MGA_DMA_CLEAR; - buf_priv->clear_color = clear_color; - buf_priv->clear_zval = clear_depth; - buf_priv->clear_flags = flags; + buf_priv->clear_color = args->clear_color; + buf_priv->clear_zval = args->clear_depth; + buf_priv->clear_flags = args->flags; - if (!mgaCopyAndVerifyState(dev_priv, buf_priv, MGA_UPLOAD_CLIPRECTS)) { - drm_freelist_put( dev, freelist, buf ); - return -EINVAL; - } + if (!mgaCopyAndVerifyState(dev_priv, buf_priv, MGA_UPLOAD_CLIPRECTS)) + buf_priv->dma_type = MGA_DMA_DISCARD; /* Make sure we restore the 3D state next time. @@ -95,26 +85,25 @@ static int mgaClearBuffers(drm_device_t *dev, return 0; } -int mgaSwapBuffers(drm_device_t *dev, int flags) +int mgaSwapBuffers(drm_device_t *dev, drm_mga_swap_t *args) { drm_device_dma_t *dma = dev->dma; - drm_freelist_t *freelist = &dma->bufs[MGA_DMA_BUF_ORDER].freelist; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_mga_buf_priv_t *buf_priv; drm_buf_t *buf; drm_dma_t d; - buf = drm_freelist_get(freelist, _DRM_DMA_WAIT); - if (!buf) return -1; + printk("swap buf idx %d\n", args->idx); - buf->pid = current->pid; + buf = dma->buflist[ args->idx ]; buf_priv = buf->dev_private; buf_priv->dma_type = MGA_DMA_SWAP; if (!mgaCopyAndVerifyState(dev_priv, buf_priv, MGA_UPLOAD_CLIPRECTS)) { - drm_freelist_put( dev, freelist, buf ); - return -EINVAL; + printk("mgaCopyAndVerifyState faild for swap\n"); + buf_priv->dma_type = MGA_DMA_DISCARD; } + /* Make sure we restore the 3D state next time. @@ -134,6 +123,8 @@ int mgaSwapBuffers(drm_device_t *dev, int flags) d.request_sizes = NULL; d.granted_count = 0; + printk("enqueue swap buf, idx %d\n", buf->idx); + atomic_inc(&dev_priv->pending_bufs); if((drm_dma_enqueue(dev, &d)) != 0) atomic_dec(&dev_priv->pending_bufs); @@ -209,14 +200,10 @@ int mga_clear_bufs(struct inode *inode, struct file *filp, drm_mga_clear_t clear; int retcode; - return 0; - - copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, - sizeof(clear), -EFAULT); + copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), + -EFAULT); - retcode = mgaClearBuffers(dev, clear.clear_color, - clear.clear_depth, - clear.flags); + retcode = mgaClearBuffers(dev, &clear); return retcode; } @@ -229,12 +216,11 @@ int mga_swap_bufs(struct inode *inode, struct file *filp, drm_mga_swap_t swap; int retcode = 0; - return 0; - - copy_from_user_ret(&swap, (drm_mga_swap_t *)arg, - sizeof(swap), -EFAULT); + copy_from_user_ret(&swap, (drm_mga_swap_t *)arg, sizeof(swap), -EFAULT); - retcode = mgaSwapBuffers(dev, swap.flags); + printk("(a) swap buf idx %d\n", swap.idx); + + retcode = mgaSwapBuffers(dev, &swap); return retcode; } @@ -247,8 +233,8 @@ int mga_iload(struct inode *inode, struct file *filp, drm_mga_iload_t iload; int retcode = 0; - copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, - sizeof(iload), -EFAULT); + copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload), + -EFAULT); retcode = mgaIload(dev, &iload); diff --git a/linux/mga_dma.c b/linux/mga_dma.c index 4cb2eadb..40d77cb2 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -570,14 +570,14 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf ) flags); -/* if ( flags & MGA_CLEAR_FRONT ) */ + if ( flags & MGA_CLEAR_FRONT ) { - 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); - printk("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); @@ -585,12 +585,12 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf ) } if ( flags & MGA_CLEAR_BACK ) { - 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); - printk("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); @@ -599,12 +599,12 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf ) if ( flags & MGA_CLEAR_DEPTH ) { - 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); - printk("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); @@ -624,6 +624,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf ) + static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf ) { drm_mga_private_t *dev_priv = dev->dev_private; @@ -640,7 +641,7 @@ static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf ) PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset); PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess); PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset); - PRIMOUTREG(MGAREG_AR5, dev_priv->stride); + PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2); PRIMOUTREG( MGAREG_DMAPAD, 0); PRIMOUTREG( MGAREG_DMAPAD, 0); @@ -649,7 +650,7 @@ static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf ) for (i = 0 ; i < nbox; i++) { unsigned int h = pbox[i].y2 - pbox[i].y1; - unsigned int start = pbox[i].y1 * dev_priv->stride; + unsigned int start = pbox[i].y1 * dev_priv->stride/2; printk("dispatch swap %d,%d-%d,%d!\n", pbox[i].x1, @@ -673,26 +674,45 @@ static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf ) MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } + +static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf ) +{ + drm_mga_private_t *dev_priv = dev->dev_private; + 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); + + 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) { - 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; - 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(1) { + atomic_inc(&dev_priv->dispatch_lock); + if(atomic_read(&dev_priv->dispatch_lock) == 1) { + break; + } else { + atomic_dec(&dev_priv->dispatch_lock); + } } #if 1 - MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG); - while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ; - MGA_WRITE(MGAREG_DWGSYNC, 0); - while(MGA_READ(MGAREG_DWGSYNC) != 0) ; + MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG); + while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG) ; + MGA_WRITE(MGAREG_DWGSYNC, 0); + while(MGA_READ(MGAREG_DWGSYNC) != 0) ; #endif - atomic_dec(&dev_priv->dispatch_lock); + atomic_dec(&dev_priv->dispatch_lock); } /* Keeps dispatch lock held */ @@ -730,6 +750,7 @@ 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); @@ -764,11 +785,13 @@ static int mga_do_dma(drm_device_t *dev, int locked) printk("mga_do_dma\n"); if (test_and_set_bit(0, &dev->dma_flag)) { + printk("mga_do_dma - busy\n"); atomic_inc(&dma->total_missed_dma); return -EBUSY; } if (!dma->next_buffer) { + printk("mga_do_dma - no next buffer\n"); DRM_ERROR("No next_buffer\n"); clear_bit(0, &dev->dma_flag); return -EINVAL; @@ -779,6 +802,8 @@ static int mga_do_dma(drm_device_t *dev, int locked) printk("context %d, buffer %d\n", buf->context, buf->idx); if (buf->list == DRM_LIST_RECLAIM) { + printk("mga_do_dma - reclaim\n"); + drm_clear_next_buffer(dev); drm_free_buffer(dev, buf); atomic_dec(&dev_priv->pending_bufs); @@ -798,6 +823,7 @@ static int mga_do_dma(drm_device_t *dev, int locked) } if (mga_dma_is_ready(dev) == 0) { + printk("mga_do_dma - not ready\n"); clear_bit(0, &dev->dma_flag); return -EBUSY; } @@ -807,12 +833,14 @@ static int mga_do_dma(drm_device_t *dev, int locked) if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) { + printk("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); return -EBUSY; } + dma->next_queue = dev->queuelist[DRM_KERNEL_CONTEXT]; drm_clear_next_buffer(dev); buf->pending = 1; @@ -820,6 +848,7 @@ static int mga_do_dma(drm_device_t *dev, int locked) buf->list = DRM_LIST_PEND; buf_priv = buf->dev_private; + printk("mga_do_dma - type %d\n", buf_priv->dma_type); switch (buf_priv->dma_type) { case MGA_DMA_GENERAL: @@ -840,6 +869,9 @@ static int mga_do_dma(drm_device_t *dev, int locked) case MGA_DMA_CLEAR: mga_dma_dispatch_clear(dev, buf); break; + case MGA_DMA_DISCARD: + mga_dma_dispatch_bad(dev, buf); + break; default: printk("bad buffer type %x in dispatch\n", buf_priv->dma_type); break; @@ -848,7 +880,8 @@ static int mga_do_dma(drm_device_t *dev, int locked) atomic_dec(&dev_priv->pending_bufs); if(dma->this_buffer) { - drm_free_buffer(dev, dma->this_buffer); + printk("mga_do_dma - freeing this_buffer\n"); + drm_free_buffer(dev, dma->this_buffer); } dma->this_buffer = buf; diff --git a/linux/mga_dma.h b/linux/mga_dma.h index a6868cef..c9507d3d 100644 --- a/linux/mga_dma.h +++ b/linux/mga_dma.h @@ -31,7 +31,7 @@ typedef struct { #define MGA_DMA_ILOAD 3 #define MGA_DMA_CLEAR 4 /* placeholder */ #define MGA_DMA_SWAP 5 /* placeholder */ -#define MGA_DMA_BAD 6 +#define MGA_DMA_DISCARD 6 #define DWGREG0 0x1c00 diff --git a/linux/mga_drm_public.h b/linux/mga_drm_public.h index 09152648..16b6cc28 100644 --- a/linux/mga_drm_public.h +++ b/linux/mga_drm_public.h @@ -170,12 +170,12 @@ typedef struct _xf86drmClipRectRec { /* Upto 128 regions. Minimum region size of 256k. */ #define MGA_NR_TEX_REGIONS 128 -#define MGA_MIN_LOG_TEX_GRANULARITY 18 +#define MGA_LOG_MIN_TEX_REGION_SIZE 18 typedef struct { - unsigned char next, prev; - unsigned char in_use; - int age; + unsigned char next, prev; + unsigned char in_use; + int age; } mgaTexRegion; typedef struct @@ -200,6 +200,7 @@ typedef struct /* Device specific ioctls: */ typedef struct { + int idx; int clear_color; int clear_depth; int flags; @@ -207,6 +208,7 @@ typedef struct { typedef struct { + int idx; int flags; /* not actually used? */ } drm_mga_swap_t;