diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c index e9b0e807..87145941 100644 --- a/linux-core/i810_dma.c +++ b/linux-core/i810_dma.c @@ -26,7 +26,7 @@ * * Authors: Rickard E. (Rik) Faith * Jeff Hartmann - * Keith Whitwell + * Keith Whitwell * */ @@ -36,11 +36,6 @@ #include "i810_drv.h" #include /* For task queue support */ -/* in case we don't have a 2.3.99-pre6 kernel or later: */ -#ifndef VM_DONTCOPY -#define VM_DONTCOPY 0 -#endif - #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 #define I810_BUF_HARDWARE 0 @@ -50,29 +45,27 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; -#define BEGIN_LP_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ +#define BEGIN_LP_RING(n) do { \ + if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i810_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ } while (0) -#define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ +#define ADVANCE_LP_RING() do { \ + if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) -#define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ +#define OUT_RING(n) do { \ + if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ } while (0); static inline void i810_print_status_page(drm_device_t *dev) @@ -181,36 +174,31 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp) if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; - if(VM_DONTCOPY != 0) { #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - old_fops = filp->f_op; - filp->f_op = &i810_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, - PROT_READ|PROT_WRITE, - MAP_SHARED, - buf->bus_address); - dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; - if ((unsigned long)buf_priv->virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed int)buf_priv->virtual; - buf_priv->virtual = 0; - } -#if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); -#else - up_write( ¤t->mm->mmap_sem ); -#endif - } else { - buf_priv->virtual = buf_priv->kernel_virtual; - buf_priv->currently_mapped = I810_BUF_MAPPED; + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; } +#if LINUX_VERSION_CODE <= 0x020402 + up( ¤t->mm->mmap_sem ); +#else + up_write( ¤t->mm->mmap_sem ); +#endif return retcode; } @@ -219,23 +207,21 @@ static int i810_unmap_buffer(drm_buf_t *buf) drm_i810_buf_priv_t *buf_priv = buf->dev_private; int retcode = 0; - if(VM_DONTCOPY != 0) { - if(buf_priv->currently_mapped != I810_BUF_MAPPED) - return -EINVAL; + if(buf_priv->currently_mapped != I810_BUF_MAPPED) + return -EINVAL; #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, - (size_t) buf->total); + retcode = do_munmap(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total); #if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); + up( ¤t->mm->mmap_sem ); #else - up_write( ¤t->mm->mmap_sem ); + up_write( ¤t->mm->mmap_sem ); #endif - } buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -444,9 +430,6 @@ static int i810_dma_initialize(drm_device_t *dev, ((u8 *)dev_priv->sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->flush_done, 0); - init_waitqueue_head(&dev_priv->flush_queue); - dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; @@ -536,16 +519,12 @@ int i810_dma_init(struct inode *inode, struct file *filp, /* Most efficient way to verify state for the i810 is as it is * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. */ static void i810EmitContextVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_CTX_SETUP_SIZE ); @@ -557,12 +536,10 @@ static void i810EmitContextVerified( drm_device_t *dev, OUT_RING( code[I810_CTXREG_ST1] ); for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } } @@ -578,7 +555,6 @@ static void i810EmitTexVerified( drm_device_t *dev, { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_TEX_SETUP_SIZE ); @@ -589,12 +565,11 @@ static void i810EmitTexVerified( drm_device_t *dev, OUT_RING( code[I810_TEXREG_MI3] ); for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } } @@ -621,9 +596,7 @@ static void i810EmitDestVerified( drm_device_t *dev, if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( tmp ); - } else - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", - tmp, dev_priv->front_di1, dev_priv->back_di1); + } /* invarient: */ @@ -645,30 +618,24 @@ static void i810EmitDestVerified( drm_device_t *dev, -static void i810EmitState( drm_device_t *dev ) +static void i810EmitState( drm_device_t *dev, + drm_i810_state_t *state, + unsigned int dirty ) { - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - if (dirty & I810_UPLOAD_BUFFERS) { - i810EmitDestVerified( dev, sarea_priv->BufferState ); - sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS; + i810EmitDestVerified( dev, state->BufferSetup ); } if (dirty & I810_UPLOAD_CTX) { - i810EmitContextVerified( dev, sarea_priv->ContextState ); - sarea_priv->dirty &= ~I810_UPLOAD_CTX; + i810EmitContextVerified( dev, state->Setup ); } if (dirty & I810_UPLOAD_TEX0) { - i810EmitTexVerified( dev, sarea_priv->TexState[0] ); - sarea_priv->dirty &= ~I810_UPLOAD_TEX0; + i810EmitTexVerified( dev, state->TexSetup[0] ); } if (dirty & I810_UPLOAD_TEX1) { - i810EmitTexVerified( dev, sarea_priv->TexState[1] ); - sarea_priv->dirty &= ~I810_UPLOAD_TEX1; + i810EmitTexVerified( dev, state->TexSetup[1] ); } } @@ -708,7 +675,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, continue; if ( flags & I810_FRONT ) { - DRM_DEBUG("clear front\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -721,7 +687,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_BACK ) { - DRM_DEBUG("clear back\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -734,7 +699,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_DEPTH ) { - DRM_DEBUG("clear depth\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -760,8 +724,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) int i; RING_LOCALS; - DRM_DEBUG("swapbuffers\n"); - i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) @@ -780,10 +742,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) pbox->y2 > dev_priv->h) continue; - DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", - pbox[i].x1, pbox[i].y1, - pbox[i].x2, pbox[i].y2); - BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); OUT_RING( pitch | (0xCC << 16)); @@ -799,7 +757,10 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf, int discard, - int used) + drm_i810_prim_t *prim, + unsigned int nrprim, + drm_i810_state_t *state, + unsigned int nrstate ) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private; @@ -807,139 +768,92 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_clip_rect_t *box = sarea_priv->boxes; int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; - unsigned long start = address - dev->agp->base; - int i = 0, u; + unsigned long bufstart = address - dev->agp->base; + char *buf_virtual = (char *)buf_priv->virtual; + unsigned int i; RING_LOCALS; + if (nbox > I810_NR_SAREA_CLIPRECTS) + nrprim = 0; + i810_kernel_lost_context(dev); - if (nbox > I810_NR_SAREA_CLIPRECTS) - nbox = I810_NR_SAREA_CLIPRECTS; + for (i = 0 ; i < nrprim ; i++, prim++) { + int j = 0; - if (discard) { - u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_HARDWARE); - if(u != I810_BUF_CLIENT) { - DRM_DEBUG("xxxx 2\n"); - } - } +/* printk("prim %d start %x fin %x\n", i, prim->start, */ +/* prim->finish); */ - if (used > 4*1024) - used = 0; - - if (sarea_priv->dirty) - i810EmitState( dev ); - - DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", - address, used, nbox); - - dev_priv->counter++; - DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG( "i810_dma_dispatch\n"); - DRM_DEBUG( "start : %lx\n", start); - DRM_DEBUG( "used : %d\n", used); - DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | - ((used/4)-2)); - - if (used & 4) { - *(u32 *)((u32)buf_priv->virtual + used) = 0; - used += 4; + if ((unsigned)prim->start >= I810_DMA_BUF_SZ || + prim->start >= prim->finish || + (prim->start & 0x7) != 0x4) { +/* printk("alignment/other\n"); */ + continue; } - i810_unmap_buffer(buf); - } + if (prim->dirty && prim->stateidx < nrstate) { + i810EmitState( dev, + &state[(int)prim->stateidx], + prim->dirty ); + } + + *(int *)&buf_virtual[prim->start-4] = + (GFX_OP_PRIMITIVE | (((int)prim->prim) << 18) | + ((prim->finish - prim->start)/4-1)); + + + if (prim->finish & 0x4) { + *(int *)&buf_virtual[prim->finish] = 0; + prim->finish += 4; + } + + - if (used) { do { - if (i < nbox) { + if (j < nbox) { BEGIN_LP_RING(4); - OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | + OUT_RING( GFX_OP_SCISSOR | + SC_UPDATE_SCISSOR | SC_ENABLE ); OUT_RING( GFX_OP_SCISSOR_INFO ); - OUT_RING( box[i].x1 | (box[i].y1<<16) ); - OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) ); + OUT_RING( box[j].x1 | (box[j].y1<<16) ); + OUT_RING( (box[j].x2-1) | ((box[j].y2-1)<<16) ); ADVANCE_LP_RING(); + if (nbox == 1) nbox = 0; } BEGIN_LP_RING(4); OUT_RING( CMD_OP_BATCH_BUFFER ); - OUT_RING( start | BB1_PROTECTED ); - OUT_RING( start + used - 4 ); + OUT_RING( (bufstart + prim->start - 4) | + BB1_PROTECTED ); + OUT_RING( (bufstart + prim->finish - 4) ); OUT_RING( 0 ); ADVANCE_LP_RING(); - - } while (++i < nbox); + } while (++j < nbox); } - BEGIN_LP_RING(10); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( 0 ); if (discard) { + dev_priv->counter++; + + (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + + BEGIN_LP_RING( 8 ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I810_BUF_FREE ); + OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); + ADVANCE_LP_RING(); } - - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); } -/* Interrupts are only for flushing */ -void i810_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *)device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u16 temp; - - atomic_inc(&dev->counts[_DRM_STAT_IRQ]); - temp = I810_READ16(I810REG_INT_IDENTITY_R); - temp = temp & ~(0x6000); - if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, - temp); /* Clear all interrupts */ - else - return; - - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -void i810_dma_immediate_bh(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -static inline void i810_dma_emit_flush(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -static inline void i810_dma_quiescent_emit(drm_device_t *dev) +void i810_dma_quiescent(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -950,79 +864,27 @@ static inline void i810_dma_quiescent_emit(drm_device_t *dev) OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( 0 ); ADVANCE_LP_RING(); -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -void i810_dma_quiescent(drm_device_t *dev) -{ - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - unsigned long end; - - if(dev_priv == NULL) { - return; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_quiescent_emit(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); - - return; + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); } static int i810_flush_queue(drm_device_t *dev) { - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; - unsigned long end; int i, ret = 0; + RING_LOCALS; + + i810_kernel_lost_context(dev); - if(dev_priv == NULL) { - return 0; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_emit_flush(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - ret = -EINTR; /* Can't restart */ - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1034,7 +896,7 @@ static int i810_flush_queue(drm_device_t *dev) if (used == I810_BUF_HARDWARE) DRM_DEBUG("reclaimed from HARDWARE\n"); if (used == I810_BUF_CLIENT) - DRM_DEBUG("still on client HARDWARE\n"); + DRM_DEBUG("still on client\n"); } return ret; @@ -1074,7 +936,6 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_flush_ioctl\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_flush_ioctl called without lock held\n"); return -EINVAL; @@ -1085,8 +946,32 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, } +/* Copy sarea data into temporary structs. + */ +void i810_copy_state( drm_i810_sarea_t *sarea, drm_i810_state_t *state ) +{ + if (sarea->dirty & I810_UPLOAD_CTX) + memcpy(state->Setup, sarea->ContextState, + sizeof(state->Setup)); + + if (sarea->dirty & I810_UPLOAD_BUFFERS) + memcpy(state->BufferSetup, sarea->BufferState, + sizeof(state->BufferSetup)); + + if (sarea->dirty & I810_UPLOAD_TEX0) + memcpy(state->TexSetup[0], sarea->TexState[0], + sizeof(state->TexSetup[0])); + + if (sarea->dirty & I810_UPLOAD_TEX1) + memcpy(state->TexSetup[1], sarea->TexState[1], + sizeof(state->TexSetup[1])); +} + + +/* Obsolete, backwards compatibility ioctl: + */ int i810_dma_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; @@ -1096,6 +981,12 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; drm_i810_vertex_t vertex; + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + drm_i810_state_t tmpstate; + drm_i810_prim_t tmpprim; + +/* printk("%s\n", __FUNCTION__); */ if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex))) return -EFAULT; @@ -1105,24 +996,116 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, return -EINVAL; } - DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); + buf = dma->buflist[ vertex.idx ]; + buf_priv = buf->dev_private; - if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; + if (vertex.idx < 0 || vertex.idx >= I810_DMA_BUF_NR) { + DRM_ERROR("i810_dma_vertex2 bad buffer idx\n"); + return -EINVAL; + } + + if (sarea_priv->dirty) + i810_copy_state( sarea_priv, &tmpstate ); - i810_dma_dispatch_vertex( dev, - dma->buflist[ vertex.idx ], - vertex.discard, vertex.used ); + tmpprim.start = 0; + tmpprim.finish = vertex.used; + tmpprim.prim = (char) sarea_priv->vertex_prim; + tmpprim.dirty = (char) sarea_priv->dirty; + tmpprim.stateidx = 0; + + i810_dma_dispatch_vertex( dev, buf, + vertex.discard, + &tmpprim, 1, + &tmpstate, 1 ); + + if (buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } - atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]); atomic_inc(&dev->counts[_DRM_STAT_DMA]); + sarea_priv->last_enqueue = dev_priv->counter-1; sarea_priv->last_dispatch = (int) hw_status[5]; - - return 0; + return 0; } +int i810_dma_vertex2(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + drm_i810_vertex2_t vertex; + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + +/* printk("%s\n", __FUNCTION__); */ + + if (copy_from_user(&vertex, (drm_i810_vertex2_t *)arg, sizeof(vertex))) + return -EFAULT; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_dma_vertex2 called without lock held\n"); + return -EINVAL; + } + + if (vertex.idx >= I810_DMA_BUF_NR) { + DRM_ERROR("i810_dma_vertex2 bad buffer idx\n"); + return -EINVAL; + } + + +/* printk("%s buf %d nstates %d nprim %d\n", */ +/* __FUNCTION__, */ +/* vertex.idx, */ +/* vertex.nr_states, */ +/* vertex.nr_prims ); */ + + buf = dma->buflist[ vertex.idx ]; + buf_priv = buf->dev_private; + + if (vertex.nr_states) { + if (vertex.nr_states >= I810_MAX_STATES) + return -EINVAL; + + if (copy_from_user(dev_priv->statetmp, + vertex.state_address, + vertex.nr_states * sizeof(drm_i810_state_t))) + return -EFAULT; + } + + if (vertex.nr_prims) { + if (vertex.nr_prims >= I810_MAX_PRIMS) + return -EINVAL; + + if (copy_from_user(dev_priv->primtmp, + vertex.prim_address, + vertex.nr_prims * sizeof(drm_i810_prim_t))) + return -EFAULT; + } + + i810_dma_dispatch_vertex( dev, buf, + vertex.discard, + dev_priv->primtmp, + vertex.nr_prims, + dev_priv->statetmp, + vertex.nr_states ); + + if (buf_priv->currently_mapped == I810_BUF_MAPPED) + i810_unmap_buffer(buf); + + atomic_inc(&dev->counts[_DRM_STAT_DMA]); + + sarea_priv->last_enqueue = dev_priv->counter-1; + sarea_priv->last_dispatch = (int) hw_status[5]; + return 0; +} + int i810_clear_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -1156,8 +1139,6 @@ int i810_swap_bufs(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_swap_bufs\n"); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_swap_buf called without lock held\n"); return -EINVAL; @@ -1193,7 +1174,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - DRM_DEBUG("getbuf\n"); if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) return -EFAULT; @@ -1206,9 +1186,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); - if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; @@ -1216,46 +1193,18 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, return retcode; } -int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_copybuf(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_i810_copy_t d; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_buf_t *buf; - drm_i810_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma called without lock held\n"); - return -EINVAL; - } - - if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) - return -EFAULT; - - if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; - buf = dma->buflist[ d.idx ]; - buf_priv = buf->dev_private; - if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; - - if(d.used < 0 || d.used > buf->total) return -EINVAL; - - if (copy_from_user(buf_priv->virtual, d.address, d.used)) - return -EFAULT; - - sarea_priv->last_dispatch = (int) hw_status[5]; - + /* Never copy - 2.4.x doesn't need it */ return 0; } int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - if(VM_DONTCOPY == 0) return 1; + /* Never copy - 2.4.x doesn't need it */ return 0; } diff --git a/linux-core/i810_drm.h b/linux-core/i810_drm.h index 5d47adda..3af02be9 100644 --- a/linux-core/i810_drm.h +++ b/linux-core/i810_drm.h @@ -88,6 +88,8 @@ #define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ #define I810_TEX_SETUP_SIZE 8 +/* Flags for clear ioctl + */ #define I810_FRONT 0x1 #define I810_BACK 0x2 #define I810_DEPTH 0x4 @@ -189,6 +191,52 @@ typedef struct _drm_i810_copy_t { void *address; /* Address to copy from */ } drm_i810_copy_t; + +typedef struct _drm_i810_state { + unsigned int Setup[I810_CTX_SETUP_SIZE]; + unsigned int BufferSetup[I810_DEST_SETUP_SIZE]; + unsigned int TexSetup[2][I810_TEX_SETUP_SIZE]; +} drm_i810_state_t; + +#define PR_TRIANGLES (0x0) +#define PR_TRISTRIP_0 (0x1) +#define PR_TRISTRIP_1 (0x2) +#define PR_TRIFAN (0x3) +#define PR_POLYGON (0x4) +#define PR_LINES (0x5) +#define PR_LINESTRIP (0x6) +#define PR_RECTS (0x7) + +typedef struct _drm_i810_prim { + int start; + int finish; + char prim; + char dirty; + char stateidx; +} drm_i810_prim_t; + + +#define I810_MAX_PRIMS 100 +#define I810_MAX_STATES 20 + +/* Still uses the sarea to pass cliprects (fix?). State and primitive + * information are passed directly as pointers to userspace data. + * Copying of vertex data is performed by this ioctl as well. + * + * This obsoletes _drm_i810_vertex, _drm_i810_copy and the state and + * primitive fields in the sarea. + */ +typedef struct _drm_i810_vertex2 { + unsigned int idx; /* buffer index */ + unsigned int discard; /* client is finished with the buffer? */ + void *vertex_address; + unsigned int nr_states; + drm_i810_state_t *state_address; + unsigned int nr_prims; + drm_i810_prim_t *prim_address; +} drm_i810_vertex2_t; + + typedef struct drm_i810_dma { void *virtual; int request_idx; diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index 73df313c..ebed0d66 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -54,7 +54,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX2)] = { i810_dma_vertex2, 1, 0 }, #define __HAVE_COUNTERS 4 diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h index e1b17148..533a6b18 100644 --- a/linux-core/i810_drv.h +++ b/linux-core/i810_drv.h @@ -64,8 +64,6 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; - atomic_t flush_done; - wait_queue_head_t flush_queue; /* Processes waiting until flush */ drm_buf_t *mmap_buffer; @@ -75,6 +73,12 @@ typedef struct drm_i810_private { int depth_offset; int w, h; int pitch; + + /* Temporaries to hold userspace data before submitting to the + * ring. + */ + drm_i810_state_t statetmp[I810_MAX_STATES]; + drm_i810_prim_t primtmp[I810_MAX_STATES]; } drm_i810_private_t; /* i810_dma.c */ @@ -89,19 +93,29 @@ extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); + +/* Obsolete: + */ extern int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +/* Obsolete: + */ extern int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern void i810_dma_quiescent(drm_device_t *dev); -#define I810_VERBOSE 0 - - +/* Obsolete + */ int i810_dma_vertex(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +/* Handles multiple prims/ioctl, does any necessary copying in this + * ioctl: + */ +int i810_dma_vertex2(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + int i810_swap_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux/drm.h b/linux/drm.h index ac9f407a..0d2d762d 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -104,6 +104,7 @@ typedef struct drm_tex_region { #include "i810_drm.h" #include "r128_drm.h" #include "radeon_drm.h" +#include "gamma_drm.h" #ifdef CONFIG_DRM_SIS #include "sis_drm.h" #endif @@ -449,6 +450,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) #define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) #define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) +#define DRM_IOCTL_I810_VERTEX2 DRM_IOW( 0x49, drm_i810_vertex2_t) /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) @@ -466,6 +468,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -483,6 +486,10 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) +/* Gamma specific ioctls */ +#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) +#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t) + #ifdef CONFIG_DRM_SIS /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) diff --git a/linux/i810.h b/linux/i810.h index a5152bc0..4a7f5207 100644 --- a/linux/i810.h +++ b/linux/i810.h @@ -60,50 +60,9 @@ i810_dma_quiescent( dev ); \ } while (0) -#define __HAVE_DMA_IRQ 1 -#define __HAVE_DMA_IRQ_BH 1 -#define __HAVE_SHARED_IRQ 1 -#define DRIVER_PREINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I810_READ16( I810REG_HWSTAM ); \ - tmp = tmp & 0x6000; \ - I810_WRITE16( I810REG_HWSTAM, tmp ); \ - \ - tmp = I810_READ16( I810REG_INT_MASK_R ); \ - tmp = tmp & 0x6000; /* Unmask interrupts */ \ - I810_WRITE16( I810REG_INT_MASK_R, tmp ); \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ -} while (0) - -#define DRIVER_POSTINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; \ - tmp = tmp | 0x0003; /* Enable bp & user interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ -} while (0) - -#define DRIVER_UNINSTALL() do { \ - drm_i810_private_t *dev_priv = \ - (drm_i810_private_t *)dev->dev_private; \ - u16 tmp; \ - if ( dev_priv ) { \ - tmp = I810_READ16( I810REG_INT_IDENTITY_R ); \ - tmp = tmp & ~(0x6000); /* Clear all interrupts */ \ - if ( tmp != 0 ) \ - I810_WRITE16( I810REG_INT_IDENTITY_R, tmp ); \ - \ - tmp = I810_READ16( I810REG_INT_ENABLE_R ); \ - tmp = tmp & 0x6000; /* Disable all interrupts */ \ - I810_WRITE16( I810REG_INT_ENABLE_R, tmp ); \ - } \ -} while (0) +#define __HAVE_DMA_IRQ 0 +#define __HAVE_DMA_IRQ_BH 0 +#define __HAVE_SHARED_IRQ 1 /* Buffer customization: */ diff --git a/linux/i810_dma.c b/linux/i810_dma.c index e9b0e807..87145941 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -26,7 +26,7 @@ * * Authors: Rickard E. (Rik) Faith * Jeff Hartmann - * Keith Whitwell + * Keith Whitwell * */ @@ -36,11 +36,6 @@ #include "i810_drv.h" #include /* For task queue support */ -/* in case we don't have a 2.3.99-pre6 kernel or later: */ -#ifndef VM_DONTCOPY -#define VM_DONTCOPY 0 -#endif - #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 #define I810_BUF_HARDWARE 0 @@ -50,29 +45,27 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; -#define BEGIN_LP_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ +#define BEGIN_LP_RING(n) do { \ + if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i810_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ } while (0) -#define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ +#define ADVANCE_LP_RING() do { \ + if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) -#define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ +#define OUT_RING(n) do { \ + if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ } while (0); static inline void i810_print_status_page(drm_device_t *dev) @@ -181,36 +174,31 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp) if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; - if(VM_DONTCOPY != 0) { #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - old_fops = filp->f_op; - filp->f_op = &i810_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, - PROT_READ|PROT_WRITE, - MAP_SHARED, - buf->bus_address); - dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; - if ((unsigned long)buf_priv->virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed int)buf_priv->virtual; - buf_priv->virtual = 0; - } -#if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); -#else - up_write( ¤t->mm->mmap_sem ); -#endif - } else { - buf_priv->virtual = buf_priv->kernel_virtual; - buf_priv->currently_mapped = I810_BUF_MAPPED; + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; } +#if LINUX_VERSION_CODE <= 0x020402 + up( ¤t->mm->mmap_sem ); +#else + up_write( ¤t->mm->mmap_sem ); +#endif return retcode; } @@ -219,23 +207,21 @@ static int i810_unmap_buffer(drm_buf_t *buf) drm_i810_buf_priv_t *buf_priv = buf->dev_private; int retcode = 0; - if(VM_DONTCOPY != 0) { - if(buf_priv->currently_mapped != I810_BUF_MAPPED) - return -EINVAL; + if(buf_priv->currently_mapped != I810_BUF_MAPPED) + return -EINVAL; #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, - (size_t) buf->total); + retcode = do_munmap(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total); #if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); + up( ¤t->mm->mmap_sem ); #else - up_write( ¤t->mm->mmap_sem ); + up_write( ¤t->mm->mmap_sem ); #endif - } buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -444,9 +430,6 @@ static int i810_dma_initialize(drm_device_t *dev, ((u8 *)dev_priv->sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->flush_done, 0); - init_waitqueue_head(&dev_priv->flush_queue); - dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; @@ -536,16 +519,12 @@ int i810_dma_init(struct inode *inode, struct file *filp, /* Most efficient way to verify state for the i810 is as it is * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. */ static void i810EmitContextVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_CTX_SETUP_SIZE ); @@ -557,12 +536,10 @@ static void i810EmitContextVerified( drm_device_t *dev, OUT_RING( code[I810_CTXREG_ST1] ); for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } } @@ -578,7 +555,6 @@ static void i810EmitTexVerified( drm_device_t *dev, { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_TEX_SETUP_SIZE ); @@ -589,12 +565,11 @@ static void i810EmitTexVerified( drm_device_t *dev, OUT_RING( code[I810_TEXREG_MI3] ); for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } } @@ -621,9 +596,7 @@ static void i810EmitDestVerified( drm_device_t *dev, if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( tmp ); - } else - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", - tmp, dev_priv->front_di1, dev_priv->back_di1); + } /* invarient: */ @@ -645,30 +618,24 @@ static void i810EmitDestVerified( drm_device_t *dev, -static void i810EmitState( drm_device_t *dev ) +static void i810EmitState( drm_device_t *dev, + drm_i810_state_t *state, + unsigned int dirty ) { - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - if (dirty & I810_UPLOAD_BUFFERS) { - i810EmitDestVerified( dev, sarea_priv->BufferState ); - sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS; + i810EmitDestVerified( dev, state->BufferSetup ); } if (dirty & I810_UPLOAD_CTX) { - i810EmitContextVerified( dev, sarea_priv->ContextState ); - sarea_priv->dirty &= ~I810_UPLOAD_CTX; + i810EmitContextVerified( dev, state->Setup ); } if (dirty & I810_UPLOAD_TEX0) { - i810EmitTexVerified( dev, sarea_priv->TexState[0] ); - sarea_priv->dirty &= ~I810_UPLOAD_TEX0; + i810EmitTexVerified( dev, state->TexSetup[0] ); } if (dirty & I810_UPLOAD_TEX1) { - i810EmitTexVerified( dev, sarea_priv->TexState[1] ); - sarea_priv->dirty &= ~I810_UPLOAD_TEX1; + i810EmitTexVerified( dev, state->TexSetup[1] ); } } @@ -708,7 +675,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, continue; if ( flags & I810_FRONT ) { - DRM_DEBUG("clear front\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -721,7 +687,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_BACK ) { - DRM_DEBUG("clear back\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -734,7 +699,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_DEPTH ) { - DRM_DEBUG("clear depth\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -760,8 +724,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) int i; RING_LOCALS; - DRM_DEBUG("swapbuffers\n"); - i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) @@ -780,10 +742,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) pbox->y2 > dev_priv->h) continue; - DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", - pbox[i].x1, pbox[i].y1, - pbox[i].x2, pbox[i].y2); - BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); OUT_RING( pitch | (0xCC << 16)); @@ -799,7 +757,10 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf, int discard, - int used) + drm_i810_prim_t *prim, + unsigned int nrprim, + drm_i810_state_t *state, + unsigned int nrstate ) { drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private; @@ -807,139 +768,92 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_clip_rect_t *box = sarea_priv->boxes; int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; - unsigned long start = address - dev->agp->base; - int i = 0, u; + unsigned long bufstart = address - dev->agp->base; + char *buf_virtual = (char *)buf_priv->virtual; + unsigned int i; RING_LOCALS; + if (nbox > I810_NR_SAREA_CLIPRECTS) + nrprim = 0; + i810_kernel_lost_context(dev); - if (nbox > I810_NR_SAREA_CLIPRECTS) - nbox = I810_NR_SAREA_CLIPRECTS; + for (i = 0 ; i < nrprim ; i++, prim++) { + int j = 0; - if (discard) { - u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_HARDWARE); - if(u != I810_BUF_CLIENT) { - DRM_DEBUG("xxxx 2\n"); - } - } +/* printk("prim %d start %x fin %x\n", i, prim->start, */ +/* prim->finish); */ - if (used > 4*1024) - used = 0; - - if (sarea_priv->dirty) - i810EmitState( dev ); - - DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", - address, used, nbox); - - dev_priv->counter++; - DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG( "i810_dma_dispatch\n"); - DRM_DEBUG( "start : %lx\n", start); - DRM_DEBUG( "used : %d\n", used); - DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | - ((used/4)-2)); - - if (used & 4) { - *(u32 *)((u32)buf_priv->virtual + used) = 0; - used += 4; + if ((unsigned)prim->start >= I810_DMA_BUF_SZ || + prim->start >= prim->finish || + (prim->start & 0x7) != 0x4) { +/* printk("alignment/other\n"); */ + continue; } - i810_unmap_buffer(buf); - } + if (prim->dirty && prim->stateidx < nrstate) { + i810EmitState( dev, + &state[(int)prim->stateidx], + prim->dirty ); + } + + *(int *)&buf_virtual[prim->start-4] = + (GFX_OP_PRIMITIVE | (((int)prim->prim) << 18) | + ((prim->finish - prim->start)/4-1)); + + + if (prim->finish & 0x4) { + *(int *)&buf_virtual[prim->finish] = 0; + prim->finish += 4; + } + + - if (used) { do { - if (i < nbox) { + if (j < nbox) { BEGIN_LP_RING(4); - OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | + OUT_RING( GFX_OP_SCISSOR | + SC_UPDATE_SCISSOR | SC_ENABLE ); OUT_RING( GFX_OP_SCISSOR_INFO ); - OUT_RING( box[i].x1 | (box[i].y1<<16) ); - OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) ); + OUT_RING( box[j].x1 | (box[j].y1<<16) ); + OUT_RING( (box[j].x2-1) | ((box[j].y2-1)<<16) ); ADVANCE_LP_RING(); + if (nbox == 1) nbox = 0; } BEGIN_LP_RING(4); OUT_RING( CMD_OP_BATCH_BUFFER ); - OUT_RING( start | BB1_PROTECTED ); - OUT_RING( start + used - 4 ); + OUT_RING( (bufstart + prim->start - 4) | + BB1_PROTECTED ); + OUT_RING( (bufstart + prim->finish - 4) ); OUT_RING( 0 ); ADVANCE_LP_RING(); - - } while (++i < nbox); + } while (++j < nbox); } - BEGIN_LP_RING(10); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( 0 ); if (discard) { + dev_priv->counter++; + + (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + + BEGIN_LP_RING( 8 ); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I810_BUF_FREE ); + OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); + ADVANCE_LP_RING(); } - - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); } -/* Interrupts are only for flushing */ -void i810_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *)device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u16 temp; - - atomic_inc(&dev->counts[_DRM_STAT_IRQ]); - temp = I810_READ16(I810REG_INT_IDENTITY_R); - temp = temp & ~(0x6000); - if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, - temp); /* Clear all interrupts */ - else - return; - - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -void i810_dma_immediate_bh(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -static inline void i810_dma_emit_flush(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -static inline void i810_dma_quiescent_emit(drm_device_t *dev) +void i810_dma_quiescent(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -950,79 +864,27 @@ static inline void i810_dma_quiescent_emit(drm_device_t *dev) OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( 0 ); ADVANCE_LP_RING(); -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -void i810_dma_quiescent(drm_device_t *dev) -{ - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - unsigned long end; - - if(dev_priv == NULL) { - return; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_quiescent_emit(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); - - return; + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); } static int i810_flush_queue(drm_device_t *dev) { - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; - unsigned long end; int i, ret = 0; + RING_LOCALS; + + i810_kernel_lost_context(dev); - if(dev_priv == NULL) { - return 0; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_emit_flush(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - ret = -EINTR; /* Can't restart */ - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1034,7 +896,7 @@ static int i810_flush_queue(drm_device_t *dev) if (used == I810_BUF_HARDWARE) DRM_DEBUG("reclaimed from HARDWARE\n"); if (used == I810_BUF_CLIENT) - DRM_DEBUG("still on client HARDWARE\n"); + DRM_DEBUG("still on client\n"); } return ret; @@ -1074,7 +936,6 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_flush_ioctl\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_flush_ioctl called without lock held\n"); return -EINVAL; @@ -1085,8 +946,32 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, } +/* Copy sarea data into temporary structs. + */ +void i810_copy_state( drm_i810_sarea_t *sarea, drm_i810_state_t *state ) +{ + if (sarea->dirty & I810_UPLOAD_CTX) + memcpy(state->Setup, sarea->ContextState, + sizeof(state->Setup)); + + if (sarea->dirty & I810_UPLOAD_BUFFERS) + memcpy(state->BufferSetup, sarea->BufferState, + sizeof(state->BufferSetup)); + + if (sarea->dirty & I810_UPLOAD_TEX0) + memcpy(state->TexSetup[0], sarea->TexState[0], + sizeof(state->TexSetup[0])); + + if (sarea->dirty & I810_UPLOAD_TEX1) + memcpy(state->TexSetup[1], sarea->TexState[1], + sizeof(state->TexSetup[1])); +} + + +/* Obsolete, backwards compatibility ioctl: + */ int i810_dma_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; @@ -1096,6 +981,12 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; drm_i810_vertex_t vertex; + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + drm_i810_state_t tmpstate; + drm_i810_prim_t tmpprim; + +/* printk("%s\n", __FUNCTION__); */ if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex))) return -EFAULT; @@ -1105,24 +996,116 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, return -EINVAL; } - DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); + buf = dma->buflist[ vertex.idx ]; + buf_priv = buf->dev_private; - if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; + if (vertex.idx < 0 || vertex.idx >= I810_DMA_BUF_NR) { + DRM_ERROR("i810_dma_vertex2 bad buffer idx\n"); + return -EINVAL; + } + + if (sarea_priv->dirty) + i810_copy_state( sarea_priv, &tmpstate ); - i810_dma_dispatch_vertex( dev, - dma->buflist[ vertex.idx ], - vertex.discard, vertex.used ); + tmpprim.start = 0; + tmpprim.finish = vertex.used; + tmpprim.prim = (char) sarea_priv->vertex_prim; + tmpprim.dirty = (char) sarea_priv->dirty; + tmpprim.stateidx = 0; + + i810_dma_dispatch_vertex( dev, buf, + vertex.discard, + &tmpprim, 1, + &tmpstate, 1 ); + + if (buf_priv->currently_mapped == I810_BUF_MAPPED) { + i810_unmap_buffer(buf); + } - atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]); atomic_inc(&dev->counts[_DRM_STAT_DMA]); + sarea_priv->last_enqueue = dev_priv->counter-1; sarea_priv->last_dispatch = (int) hw_status[5]; - - return 0; + return 0; } +int i810_dma_vertex2(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + u32 *hw_status = (u32 *)dev_priv->hw_status_page; + drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) + dev_priv->sarea_priv; + drm_i810_vertex2_t vertex; + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + +/* printk("%s\n", __FUNCTION__); */ + + if (copy_from_user(&vertex, (drm_i810_vertex2_t *)arg, sizeof(vertex))) + return -EFAULT; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i810_dma_vertex2 called without lock held\n"); + return -EINVAL; + } + + if (vertex.idx >= I810_DMA_BUF_NR) { + DRM_ERROR("i810_dma_vertex2 bad buffer idx\n"); + return -EINVAL; + } + + +/* printk("%s buf %d nstates %d nprim %d\n", */ +/* __FUNCTION__, */ +/* vertex.idx, */ +/* vertex.nr_states, */ +/* vertex.nr_prims ); */ + + buf = dma->buflist[ vertex.idx ]; + buf_priv = buf->dev_private; + + if (vertex.nr_states) { + if (vertex.nr_states >= I810_MAX_STATES) + return -EINVAL; + + if (copy_from_user(dev_priv->statetmp, + vertex.state_address, + vertex.nr_states * sizeof(drm_i810_state_t))) + return -EFAULT; + } + + if (vertex.nr_prims) { + if (vertex.nr_prims >= I810_MAX_PRIMS) + return -EINVAL; + + if (copy_from_user(dev_priv->primtmp, + vertex.prim_address, + vertex.nr_prims * sizeof(drm_i810_prim_t))) + return -EFAULT; + } + + i810_dma_dispatch_vertex( dev, buf, + vertex.discard, + dev_priv->primtmp, + vertex.nr_prims, + dev_priv->statetmp, + vertex.nr_states ); + + if (buf_priv->currently_mapped == I810_BUF_MAPPED) + i810_unmap_buffer(buf); + + atomic_inc(&dev->counts[_DRM_STAT_DMA]); + + sarea_priv->last_enqueue = dev_priv->counter-1; + sarea_priv->last_dispatch = (int) hw_status[5]; + return 0; +} + int i810_clear_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -1156,8 +1139,6 @@ int i810_swap_bufs(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_swap_bufs\n"); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_swap_buf called without lock held\n"); return -EINVAL; @@ -1193,7 +1174,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - DRM_DEBUG("getbuf\n"); if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) return -EFAULT; @@ -1206,9 +1186,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); - if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; @@ -1216,46 +1193,18 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, return retcode; } -int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_copybuf(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_i810_copy_t d; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_buf_t *buf; - drm_i810_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma called without lock held\n"); - return -EINVAL; - } - - if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) - return -EFAULT; - - if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; - buf = dma->buflist[ d.idx ]; - buf_priv = buf->dev_private; - if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; - - if(d.used < 0 || d.used > buf->total) return -EINVAL; - - if (copy_from_user(buf_priv->virtual, d.address, d.used)) - return -EFAULT; - - sarea_priv->last_dispatch = (int) hw_status[5]; - + /* Never copy - 2.4.x doesn't need it */ return 0; } int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - if(VM_DONTCOPY == 0) return 1; + /* Never copy - 2.4.x doesn't need it */ return 0; } diff --git a/linux/i810_drm.h b/linux/i810_drm.h index 5d47adda..3af02be9 100644 --- a/linux/i810_drm.h +++ b/linux/i810_drm.h @@ -88,6 +88,8 @@ #define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ #define I810_TEX_SETUP_SIZE 8 +/* Flags for clear ioctl + */ #define I810_FRONT 0x1 #define I810_BACK 0x2 #define I810_DEPTH 0x4 @@ -189,6 +191,52 @@ typedef struct _drm_i810_copy_t { void *address; /* Address to copy from */ } drm_i810_copy_t; + +typedef struct _drm_i810_state { + unsigned int Setup[I810_CTX_SETUP_SIZE]; + unsigned int BufferSetup[I810_DEST_SETUP_SIZE]; + unsigned int TexSetup[2][I810_TEX_SETUP_SIZE]; +} drm_i810_state_t; + +#define PR_TRIANGLES (0x0) +#define PR_TRISTRIP_0 (0x1) +#define PR_TRISTRIP_1 (0x2) +#define PR_TRIFAN (0x3) +#define PR_POLYGON (0x4) +#define PR_LINES (0x5) +#define PR_LINESTRIP (0x6) +#define PR_RECTS (0x7) + +typedef struct _drm_i810_prim { + int start; + int finish; + char prim; + char dirty; + char stateidx; +} drm_i810_prim_t; + + +#define I810_MAX_PRIMS 100 +#define I810_MAX_STATES 20 + +/* Still uses the sarea to pass cliprects (fix?). State and primitive + * information are passed directly as pointers to userspace data. + * Copying of vertex data is performed by this ioctl as well. + * + * This obsoletes _drm_i810_vertex, _drm_i810_copy and the state and + * primitive fields in the sarea. + */ +typedef struct _drm_i810_vertex2 { + unsigned int idx; /* buffer index */ + unsigned int discard; /* client is finished with the buffer? */ + void *vertex_address; + unsigned int nr_states; + drm_i810_state_t *state_address; + unsigned int nr_prims; + drm_i810_prim_t *prim_address; +} drm_i810_vertex2_t; + + typedef struct drm_i810_dma { void *virtual; int request_idx; diff --git a/linux/i810_drv.c b/linux/i810_drv.c index 73df313c..ebed0d66 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -54,7 +54,8 @@ [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX2)] = { i810_dma_vertex2, 1, 0 }, #define __HAVE_COUNTERS 4 diff --git a/linux/i810_drv.h b/linux/i810_drv.h index e1b17148..533a6b18 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -64,8 +64,6 @@ typedef struct drm_i810_private { unsigned long hw_status_page; unsigned long counter; - atomic_t flush_done; - wait_queue_head_t flush_queue; /* Processes waiting until flush */ drm_buf_t *mmap_buffer; @@ -75,6 +73,12 @@ typedef struct drm_i810_private { int depth_offset; int w, h; int pitch; + + /* Temporaries to hold userspace data before submitting to the + * ring. + */ + drm_i810_state_t statetmp[I810_MAX_STATES]; + drm_i810_prim_t primtmp[I810_MAX_STATES]; } drm_i810_private_t; /* i810_dma.c */ @@ -89,19 +93,29 @@ extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); + +/* Obsolete: + */ extern int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +/* Obsolete: + */ extern int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern void i810_dma_quiescent(drm_device_t *dev); -#define I810_VERBOSE 0 - - +/* Obsolete + */ int i810_dma_vertex(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +/* Handles multiple prims/ioctl, does any necessary copying in this + * ioctl: + */ +int i810_dma_vertex2(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + int i810_swap_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux/radeon_drm.h b/linux/radeon_drm.h index 4ae387ff..ab7b370f 100644 --- a/linux/radeon_drm.h +++ b/linux/radeon_drm.h @@ -26,6 +26,7 @@ * Authors: * Kevin E. Martin * Gareth Hughes + * Keith Whitwell */ #ifndef __RADEON_DRM_H__ @@ -46,7 +47,6 @@ #define RADEON_UPLOAD_MASKS 0x00000010 #define RADEON_UPLOAD_VIEWPORT 0x00000020 #define RADEON_UPLOAD_SETUP 0x00000040 -#define RADEON_UPLOAD_TCL 0x00000080 #define RADEON_UPLOAD_MISC 0x00000100 #define RADEON_UPLOAD_TEX0 0x00000200 #define RADEON_UPLOAD_TEX1 0x00000400 @@ -82,8 +82,6 @@ #define RADEON_SCRATCH_REG_OFFSET 32 -/* Keep these small for testing - */ #define RADEON_NR_SAREA_CLIPRECTS 12 /* There are 2 heaps (local/AGP). Each region within a heap is a @@ -202,8 +200,9 @@ typedef struct { } drm_radeon_tex_region_t; typedef struct { - /* The channel for communication of state information to the kernel - * on firing a vertex buffer. + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. */ drm_radeon_context_regs_t context_state; drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; @@ -296,6 +295,15 @@ typedef struct drm_radeon_vertex { int discard; /* Client finished with buffer? */ } drm_radeon_vertex_t; +typedef struct drm_radeon_vertex { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + typedef struct drm_radeon_indices { int prim; int idx; @@ -319,6 +327,16 @@ typedef struct drm_radeon_texture { drm_radeon_tex_image_t *image; } drm_radeon_texture_t; +typedef struct drm_radeon_texture2 { + int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t blit; + const void *data; +} drm_radeon_texture2_t; + typedef struct drm_radeon_stipple { unsigned int *mask; } drm_radeon_stipple_t; diff --git a/shared-core/drm.h b/shared-core/drm.h index ac9f407a..0d2d762d 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -104,6 +104,7 @@ typedef struct drm_tex_region { #include "i810_drm.h" #include "r128_drm.h" #include "radeon_drm.h" +#include "gamma_drm.h" #ifdef CONFIG_DRM_SIS #include "sis_drm.h" #endif @@ -449,6 +450,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) #define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) #define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) +#define DRM_IOCTL_I810_VERTEX2 DRM_IOW( 0x49, drm_i810_vertex2_t) /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) @@ -466,6 +468,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -483,6 +486,10 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) +/* Gamma specific ioctls */ +#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) +#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t) + #ifdef CONFIG_DRM_SIS /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) diff --git a/shared/drm.h b/shared/drm.h index ac9f407a..0d2d762d 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -104,6 +104,7 @@ typedef struct drm_tex_region { #include "i810_drm.h" #include "r128_drm.h" #include "radeon_drm.h" +#include "gamma_drm.h" #ifdef CONFIG_DRM_SIS #include "sis_drm.h" #endif @@ -449,6 +450,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_SWAP DRM_IO( 0x46) #define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) #define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48) +#define DRM_IOCTL_I810_VERTEX2 DRM_IOW( 0x49, drm_i810_vertex2_t) /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) @@ -466,6 +468,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -483,6 +486,10 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) +/* Gamma specific ioctls */ +#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t) +#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t) + #ifdef CONFIG_DRM_SIS /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)