diff options
-rw-r--r-- | linux-core/r128_drv.c | 165 | ||||
-rw-r--r-- | linux/drm.h | 15 | ||||
-rw-r--r-- | linux/fops.c | 22 | ||||
-rw-r--r-- | linux/r128_cce.c | 91 | ||||
-rw-r--r-- | linux/r128_drm.h | 26 | ||||
-rw-r--r-- | linux/r128_drv.c | 165 | ||||
-rw-r--r-- | linux/r128_drv.h | 24 | ||||
-rw-r--r-- | linux/r128_state.c | 478 | ||||
-rw-r--r-- | shared-core/drm.h | 15 | ||||
-rw-r--r-- | shared/drm.h | 15 |
10 files changed, 665 insertions, 351 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index a4fd2f6b..66bdf36e 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -37,9 +37,9 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001027" -#define R128_MAJOR 1 -#define R128_MINOR 1 +#define R128_DATE "20001106" +#define R128_MAJOR 2 +#define R128_MINOR 0 #define R128_PATCHLEVEL 0 static drm_device_t r128_device; @@ -67,58 +67,59 @@ static struct miscdevice r128_misc = { }; static drm_ioctl_desc_t r128_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) @@ -515,7 +516,6 @@ int r128_release(struct inode *inode, struct file *filp) } /* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */ - int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -550,6 +550,12 @@ int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, } } +#if 0 + if ( retcode ) { + DRM_INFO( "%s 0x%x ret = %d\n", __FUNCTION__, nr, retcode ); + } +#endif + atomic_dec(&dev->ioctl_count); return retcode; } @@ -581,33 +587,10 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, lock.context, current->pid, dev->lock.hw_lock->lock, lock.flags); -#if 0 - /* dev->queue_count == 0 right now for - r128. FIXME? */ - if (lock.context < 0 || lock.context >= dev->queue_count) + if (lock.context < 0) return -EINVAL; -#endif if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = jiffies - dev->lock.lock_time; - - if (lock.context == r128_res_ctx.handle && - j >= 0 && j < DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n", - lock.context, current->pid, j, - dev->lock.lock_time, jiffies); - current->state = TASK_INTERRUPTIBLE; - current->policy |= SCHED_YIELD; - schedule_timeout(DRM_LOCK_SLICE-j); - DRM_DEBUG("jiffies=%d\n", jiffies); - } - } -#endif add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { current->state = TASK_INTERRUPTIBLE; @@ -626,9 +609,6 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); -#if 1 - current->policy |= SCHED_YIELD; -#endif schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -639,32 +619,6 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, remove_wait_queue(&dev->lock.lock_queue, &entry); } -#if 0 - if (!ret && dev->last_context != lock.context && - lock.context != r128_res_ctx.handle && - dev->last_context != r128_res_ctx.handle) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; - /* PRE: dev->last_context != lock.context */ - r128_context_switch(dev, dev->last_context, lock.context); - /* POST: we will wait for the context - switch and will dispatch on a later call - when dev->last_context == lock.context - NOTE WE HOLD THE LOCK THROUGHOUT THIS - TIME! */ - current->policy |= SCHED_YIELD; - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - ret = -EINTR; - } else if (dev->last_context != lock.context) { - DRM_ERROR("Context mismatch: %d %d\n", - dev->last_context, lock.context); - } - } -#endif - if (!ret) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); @@ -679,6 +633,7 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (lock.flags & _DRM_LOCK_QUIESCENT) { /* Make hardware quiescent */ + DRM_DEBUG( "not quiescent!\n" ); #if 0 r128_quiescent(dev); #endif diff --git a/linux/drm.h b/linux/drm.h index cf0618e4..6a4099bd 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -364,14 +364,15 @@ typedef struct drm_agp_info { /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) -#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x48, drm_r128_vertex_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x49, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x50, drm_r128_packet_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) #endif diff --git a/linux/fops.c b/linux/fops.c index 8e373e5a..d91cc9ed 100644 --- a/linux/fops.c +++ b/linux/fops.c @@ -11,11 +11,11 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -23,7 +23,7 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * + * * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * Daryll Strauss <daryll@valinux.com> @@ -69,7 +69,7 @@ int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev) dev->file_last = priv; } up(&dev->struct_sem); - + return 0; } @@ -103,7 +103,7 @@ int drm_release(struct inode *inode, struct file *filp) drm_lock_free(dev, &dev->lock.hw_lock->lock, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - + /* FIXME: may require heavy-handed reset of hardware at this point, possibly processed via a callback to the X @@ -119,9 +119,9 @@ int drm_release(struct inode *inode, struct file *filp) if (priv->next) priv->next->prev = priv->prev; else dev->file_last = priv->prev; up(&dev->struct_sem); - + drm_free(priv, sizeof(*priv), DRM_MEM_FILES); - + return 0; } @@ -130,7 +130,7 @@ int drm_fasync(int fd, struct file *filp, int on) drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; int retcode; - + DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; @@ -152,7 +152,7 @@ ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off) int cur; DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp); - + while (dev->buf_rp == dev->buf_wp) { DRM_DEBUG(" sleeping\n"); if (filp->f_flags & O_NONBLOCK) { @@ -182,7 +182,7 @@ ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off) if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf; send -= cur; } - + wake_up_interruptible(&dev->buf_writers); return DRM_MIN(avail, count);; } @@ -195,7 +195,7 @@ int drm_write_string(drm_device_t *dev, const char *s) DRM_DEBUG("%d left, %d to send (%p, %p)\n", left, send, dev->buf_rp, dev->buf_wp); - + if (left == 1 || dev->buf_wp != dev->buf_rp) { DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n", left, diff --git a/linux/r128_cce.c b/linux/r128_cce.c index 3820c14d..0fed514b 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -115,18 +115,20 @@ int R128_READ_PLL(drm_device_t *dev, int addr) } -static void r128_status(drm_device_t *dev) +static void r128_status( drm_r128_private_t *dev_priv ) { - drm_r128_private_t *dev_priv = dev->dev_private; - - printk("GUI_STAT = 0x%08x\n", - (unsigned int)R128_READ(R128_GUI_STAT)); - printk("PM4_STAT = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_STAT)); - printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); - printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); + printk( "GUI_STAT = 0x%08x\n", + (unsigned int)R128_READ( R128_GUI_STAT ) ); + printk( "PM4_STAT = 0x%08x\n", + (unsigned int)R128_READ( R128_PM4_STAT ) ); + printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n", + (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) ); + printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n", + (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) ); + printk( "PM4_MICRO_CNTL = 0x%08x\n", + (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) ); + printk( "PM4_BUFFER_CNTL = 0x%08x\n", + (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) ); } @@ -163,7 +165,7 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries ) udelay( 1 ); } - DRM_DEBUG( "%s failed!\n", __FUNCTION__ ); + DRM_ERROR( "%s failed!\n", __FUNCTION__ ); return -EBUSY; } @@ -182,7 +184,7 @@ static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) udelay( 1 ); } - DRM_DEBUG( "%s failed!\n", __FUNCTION__ ); + DRM_ERROR( "%s failed!\n", __FUNCTION__ ); return -EBUSY; } @@ -238,7 +240,10 @@ static int r128_do_cce_idle( drm_r128_private_t *dev_priv ) udelay( 1 ); } - DRM_DEBUG( "%s failed!\n", __FUNCTION__ ); +#if 0 + DRM_ERROR( "failed!\n" ); + r128_status( dev_priv ); +#endif return -EBUSY; } @@ -391,6 +396,10 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) dev_priv->cce_mode = init->cce_mode; dev_priv->cce_secure = init->cce_secure; + /* GH: Simple idle check. + */ + atomic_set( &dev_priv->idle_count, 0 ); + /* We don't support anything other than bus-mastering ring mode, * but the ring can be in either AGP or PCI space for the ring * read pointer. @@ -549,59 +558,63 @@ int r128_cce_start( struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); return -EINVAL; } - if ( !dev_priv ) - return -EINVAL; - - if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) + if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) { + DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ ); return 0; + } r128_do_cce_start( dev_priv ); return 0; } +/* Stop the CCE. The engine must have been idled before calling this + * routine. + */ int r128_cce_stop( 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_r128_private_t *dev_priv = dev->dev_private; + drm_r128_cce_stop_t stop; int ret; + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); return -EINVAL; } - if ( !dev_priv ) { - DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); - return -EINVAL; - } - if ( !dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ){ - DRM_DEBUG( "%s while CCE not running\n", __FUNCTION__ ); - return 0; - } + if ( copy_from_user( &stop, (drm_r128_init_t *)arg, sizeof(stop) ) ) + return -EFAULT; /* Flush any pending CCE commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ - r128_do_cce_flush( dev_priv ); + if ( stop.flush ) { + r128_do_cce_flush( dev_priv ); + } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ - ret = r128_do_cce_idle( dev_priv ); - if ( ret < 0 ) return ret; + if ( stop.idle ) { + ret = r128_do_cce_idle( dev_priv ); + if ( ret < 0 ) return ret; + } - /* Finally, if we've managed to make the engine go idle, we - * can turn off the CCE. + /* Finally, we can turn off the CCE. If the engine isn't idle, + * we will get some dropped triangles as they won't be fully + * rendered before the CCE is shut down. */ r128_do_cce_stop( dev_priv ); @@ -619,6 +632,7 @@ int r128_cce_reset( struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { @@ -629,12 +643,6 @@ int r128_cce_reset( struct inode *inode, struct file *filp, DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); return -EINVAL; } -#if 0 - if ( !dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ){ - DRM_DEBUG( "%s while CCE not running\n", __FUNCTION__ ); - return 0; - } -#endif r128_do_cce_reset( dev_priv ); @@ -650,6 +658,7 @@ int r128_cce_idle( struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { @@ -657,7 +666,6 @@ int r128_cce_idle( struct inode *inode, struct file *filp, return -EINVAL; } - r128_do_cce_flush( dev_priv ); return r128_do_cce_idle( dev_priv ); } @@ -666,6 +674,7 @@ int r128_engine_reset( struct inode *inode, struct file *filp, { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { @@ -790,7 +799,7 @@ int r128_wait_ring( drm_r128_private_t *dev_priv, int n ) int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - ring->space = *ring->head - dev_priv->ring.tail; + ring->space = *ring->head - ring->tail; if ( ring->space <= 0 ) ring->space += ring->size; @@ -807,7 +816,9 @@ void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ) { drm_r128_ring_buffer_t *ring = &dev_priv->ring; - ring->space = *ring->head - dev_priv->ring.tail; + ring->space = *ring->head - ring->tail; + if ( ring->space == 0 ) + atomic_inc( &dev_priv->idle_count ); if ( ring->space <= 0 ) ring->space += ring->size; } diff --git a/linux/r128_drm.h b/linux/r128_drm.h index 54a7375c..aefe03b4 100644 --- a/linux/r128_drm.h +++ b/linux/r128_drm.h @@ -69,11 +69,20 @@ /* Vertex/indirect buffer size */ +#if 1 #define R128_BUFFER_SIZE 16384 +#else +#define R128_BUFFER_SIZE (128 * 1024) +#endif + +/* Byte offsets for indirect buffer data + */ +#define R128_INDEX_PRIM_OFFSET 20 +#define R128_HOSTDATA_BLIT_OFFSET 32 /* 2048x2048 @ 32bpp texture requires this many indirect buffers */ -#define R128_MAX_BLIT_BUFFERS 256 +#define R128_MAX_BLIT_BUFFERS ((2048 * 2048 * 4) / R128_BUFFER_SIZE) /* Keep these small for testing. */ @@ -202,6 +211,11 @@ typedef struct drm_r128_init { unsigned int agp_textures_offset; } drm_r128_init_t; +typedef struct drm_r128_cce_stop { + int flush; + int idle; +} drm_r128_cce_stop_t; + typedef struct drm_r128_clear { unsigned int flags; int x, y, w, h; @@ -214,10 +228,18 @@ typedef struct drm_r128_clear { typedef struct drm_r128_vertex { int prim; int idx; /* Index of vertex buffer */ - int used; /* Amount of buffer used */ + int count; /* Number of vertices in buffer */ int discard; /* Client finished with buffer? */ } drm_r128_vertex_t; +typedef struct drm_r128_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_r128_indices_t; + typedef struct drm_r128_blit_rect { int index; unsigned short x, y; diff --git a/linux/r128_drv.c b/linux/r128_drv.c index a4fd2f6b..66bdf36e 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -37,9 +37,9 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001027" -#define R128_MAJOR 1 -#define R128_MINOR 1 +#define R128_DATE "20001106" +#define R128_MAJOR 2 +#define R128_MINOR 0 #define R128_PATCHLEVEL 0 static drm_device_t r128_device; @@ -67,58 +67,59 @@ static struct miscdevice r128_misc = { }; static drm_ioctl_desc_t r128_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) @@ -515,7 +516,6 @@ int r128_release(struct inode *inode, struct file *filp) } /* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */ - int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -550,6 +550,12 @@ int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, } } +#if 0 + if ( retcode ) { + DRM_INFO( "%s 0x%x ret = %d\n", __FUNCTION__, nr, retcode ); + } +#endif + atomic_dec(&dev->ioctl_count); return retcode; } @@ -581,33 +587,10 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, lock.context, current->pid, dev->lock.hw_lock->lock, lock.flags); -#if 0 - /* dev->queue_count == 0 right now for - r128. FIXME? */ - if (lock.context < 0 || lock.context >= dev->queue_count) + if (lock.context < 0) return -EINVAL; -#endif if (!ret) { -#if 0 - if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) - != lock.context) { - long j = jiffies - dev->lock.lock_time; - - if (lock.context == r128_res_ctx.handle && - j >= 0 && j < DRM_LOCK_SLICE) { - /* Can't take lock if we just had it and - there is contention. */ - DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n", - lock.context, current->pid, j, - dev->lock.lock_time, jiffies); - current->state = TASK_INTERRUPTIBLE; - current->policy |= SCHED_YIELD; - schedule_timeout(DRM_LOCK_SLICE-j); - DRM_DEBUG("jiffies=%d\n", jiffies); - } - } -#endif add_wait_queue(&dev->lock.lock_queue, &entry); for (;;) { current->state = TASK_INTERRUPTIBLE; @@ -626,9 +609,6 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); -#if 1 - current->policy |= SCHED_YIELD; -#endif schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -639,32 +619,6 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, remove_wait_queue(&dev->lock.lock_queue, &entry); } -#if 0 - if (!ret && dev->last_context != lock.context && - lock.context != r128_res_ctx.handle && - dev->last_context != r128_res_ctx.handle) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; - /* PRE: dev->last_context != lock.context */ - r128_context_switch(dev, dev->last_context, lock.context); - /* POST: we will wait for the context - switch and will dispatch on a later call - when dev->last_context == lock.context - NOTE WE HOLD THE LOCK THROUGHOUT THIS - TIME! */ - current->policy |= SCHED_YIELD; - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - ret = -EINTR; - } else if (dev->last_context != lock.context) { - DRM_ERROR("Context mismatch: %d %d\n", - dev->last_context, lock.context); - } - } -#endif - if (!ret) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); @@ -679,6 +633,7 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, } if (lock.flags & _DRM_LOCK_QUIESCENT) { /* Make hardware quiescent */ + DRM_DEBUG( "not quiescent!\n" ); #if 0 r128_quiescent(dev); #endif diff --git a/linux/r128_drv.h b/linux/r128_drv.h index 727c268b..7f044a33 100644 --- a/linux/r128_drv.h +++ b/linux/r128_drv.h @@ -68,6 +68,8 @@ typedef struct drm_r128_private { int usec_timeout; int is_pci; + atomic_t idle_count; + unsigned int fb_bpp; unsigned int front_offset; unsigned int front_pitch; @@ -101,20 +103,6 @@ typedef struct drm_r128_buf_priv { drm_r128_freelist_t *list_entry; } drm_r128_buf_priv_t; -#define R128_BLIT_PACKET_DATA_SIZE ((R128_BUFFER_SIZE / sizeof(u32)) - 8) - -typedef struct drm_r128_blit_packet { - u32 header; - u32 gui_master_cntl; - u32 dst_pitch_offset; - u32 fg_color; - u32 bg_color; - u16 x, y; /* HACK: endian specific */ - u16 width, height; - u32 dwords; - u32 data[R128_BLIT_PACKET_DATA_SIZE]; -} drm_r128_blit_packet_t; - /* r128_drv.c */ extern int r128_version( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -158,6 +146,8 @@ extern int r128_cce_swap( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int r128_cce_vertex( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int r128_cce_indices( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern int r128_cce_blit( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -386,6 +376,8 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1 #define R128_MAX_VB_AGE 0xffffffff +#define R128_MAX_VB_VERTS (0xffff) + #define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) #define R128_ADDR(reg) (R128_BASE(reg) + reg) @@ -439,9 +431,9 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); r128_wait_ring( dev_priv, n * sizeof(u32) ); \ } \ dev_priv->ring.space -= n * sizeof(u32); \ + ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ - ring = dev_priv->ring.start; \ } while (0) #define ADVANCE_RING() do { \ @@ -463,4 +455,6 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); write &= mask; \ } while (0) +#define R128_PERFORMANCE_BOXES 0 + #endif /* __R128_DRV_H__ */ diff --git a/linux/r128_state.c b/linux/r128_state.c index 4eec9f9d..58228040 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -33,6 +33,10 @@ #include "r128_drv.h" #include "drm.h" +#define USE_OLD_BLITS 1 + +static drm_r128_blit_rect_t rects[R128_MAX_BLIT_BUFFERS]; + /* ================================================================ * CCE hardware state programming functions @@ -56,7 +60,6 @@ static void r128_emit_clip_rects( drm_r128_private_t *dev_priv, aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR); } - if ( count >= 2 ) { OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) ); OUT_RING( boxes[1].x1 ); @@ -275,6 +278,72 @@ static inline void r128_emit_state( drm_r128_private_t *dev_priv ) } +#if R128_PERFORMANCE_BOXES +/* ================================================================ + * Performance monitoring functions + */ + +static void r128_clear_box( drm_r128_private_t *dev_priv, + int x, int y, int w, int h, + int r, int g, int b ) +{ + u32 pitch, offset; + u32 fb_bpp, color; + RING_LOCALS; + + switch ( dev_priv->fb_bpp ) { + case 16: + fb_bpp = R128_GMC_DST_16BPP; + color = (((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + ((b & 0xf8) >> 3)); + break; + case 24: + fb_bpp = R128_GMC_DST_24BPP; + color = ((r << 16) | (g << 8) | b); + break; + case 32: + default: + fb_bpp = R128_GMC_DST_32BPP; + color = (((0xff) << 24) | (r << 16) | (g << 8) | b); + break; + } + + offset = dev_priv->back_offset; + pitch = dev_priv->back_pitch >> 3; + + BEGIN_RING( 6 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + + OUT_RING( (pitch << 21) | (offset >> 5) ); + OUT_RING( color ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); +} + +static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv ) +{ + if ( atomic_read( &dev_priv->idle_count ) == 0 ) { + r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 ); + } else { + atomic_set( &dev_priv->idle_count, 0 ); + } +} + +#endif + + /* ================================================================ * CCE command dispatch functions */ @@ -312,6 +381,8 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + r128_update_ring_snapshot( dev_priv ); + switch ( dev_priv->fb_bpp ) { case 16: fb_bpp = R128_GMC_DST_16BPP; @@ -349,7 +420,7 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, pbox[i].y2, flags ); if ( flags & (R128_FRONT | R128_BACK) ) { - BEGIN_RING( 7 ); + BEGIN_RING( 2 ); OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); OUT_RING( color_mask ); @@ -357,6 +428,7 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, ADVANCE_RING(); } +#if USE_OLD_BLITS if ( flags & R128_FRONT ) { int fx = x + dev_priv->front_x; int fy = y + dev_priv->front_y; @@ -425,6 +497,76 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, ADVANCE_RING(); } +#else + if ( flags & R128_FRONT ) { + BEGIN_RING( 6 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + + OUT_RING( ((dev_priv->front_pitch/8) << 21) | + (dev_priv->front_offset >> 5) ); + OUT_RING( clear_color ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_BACK ) { + BEGIN_RING( 6 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + + OUT_RING( ((dev_priv->back_pitch/8) << 21) | + (dev_priv->back_offset >> 5) ); + OUT_RING( clear_color ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_DEPTH ) { + BEGIN_RING( 8 ); + + OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); + OUT_RING( depth_mask ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_SOLID_COLOR + | depth_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + + OUT_RING( ((dev_priv->depth_pitch/8) << 21) | + (dev_priv->depth_offset >> 5) ); + OUT_RING( clear_depth ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } +#endif } } @@ -439,6 +581,14 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + r128_update_ring_snapshot( dev_priv ); + +#if R128_PERFORMANCE_BOXES + /* Do some trivial performance monitoring... + */ + r128_cce_performance_boxes( dev_priv ); +#endif + switch ( dev_priv->fb_bpp ) { case 16: fb_bpp = R128_GMC_DST_16BPP; @@ -457,6 +607,7 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) int fy = pbox[i].y1; int fw = pbox[i].x2 - fx; int fh = pbox[i].y2 - fy; +#if USE_OLD_BLITS int bx = fx + dev_priv->back_x; int by = fy + dev_priv->back_y; @@ -480,6 +631,32 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) OUT_RING( (fw << 16) | fh ); ADVANCE_RING(); +#else + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL + | R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_DP_SRC_SOURCE_MEMORY + | fb_bpp + | R128_ROP3_S + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS + | R128_GMC_WR_MSK_DIS ); + + OUT_RING( ((dev_priv->back_pitch/8) << 21) | + (dev_priv->back_offset >> 5) ); + OUT_RING( ((dev_priv->front_pitch/8) << 21) | + (dev_priv->front_offset >> 5) ); + + OUT_RING( (fx << 16) | fy ); + OUT_RING( (fx << 16) | fy ); + OUT_RING( (fw << 16) | fh ); + + ADVANCE_RING(); +#endif } /* Increment the frame counter. The client-side 3D driver must @@ -506,7 +683,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, int format = sarea_priv->vc_format; int index = buf->idx; int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base; - int size = buf->used / (vertsize * sizeof(u32)); + int size = buf->used; int prim = buf_priv->prim; int i = 0; RING_LOCALS; @@ -514,8 +691,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, DRM_DEBUG( "vertex buffer index = %d\n", index ); DRM_DEBUG( "vertex buffer offset = 0x%x\n", offset ); - DRM_DEBUG( "vertex buffer size = %d vertices, %d bytes\n", - size, buf->used ); + DRM_DEBUG( "vertex buffer size = %d vertices\n", size ); DRM_DEBUG( "vertex size = %d\n", vertsize ); DRM_DEBUG( "vertex format = 0x%x\n", format ); @@ -524,10 +700,6 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, if ( 0 ) r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); -#if 0 - prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; -#endif - if ( buf->used ) { buf_priv->dispatched = 1; @@ -564,8 +736,10 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, /* Emit the vertex buffer age */ BEGIN_RING( 2 ); + OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); OUT_RING( buf_priv->age ); + ADVANCE_RING(); buf->pending = 1; @@ -584,25 +758,57 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, r128_freelist_reset( dev ); } #endif + + sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; + sarea_priv->nbox = 0; } -static void r128_cce_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf ) +static void r128_cce_dispatch_indirect( drm_device_t *dev, + drm_buf_t *buf, + int start, int end ) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; - int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base; - int size = ((buf->used / sizeof(u32)) + 1) & ~0x1; RING_LOCALS; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", + buf->idx, start, end ); r128_update_ring_snapshot( dev_priv ); - if ( buf->used ) { - DRM_DEBUG( "%s: offset=0x%x size=%d used=%d\n", - __FUNCTION__, offset, size, buf->used ); + if ( start != end ) { + int offset = (dev_priv->buffers->offset - dev->agp->base + + buf->offset + start); + int dwords = (end - start + 3) / sizeof(u32); + + /* Indirect buffer data must be an even number of + * dwords, so if we've been given an odd number we must + * pad the data with a Type-2 CCE packet. + */ + if ( dwords & 1 ) { + u32 *data = (u32 *) + ((char *)dev_priv->buffers->handle + + buf->offset + start); + data[dwords++] = R128_CCE_PACKET2; + } + + DRM_DEBUG( "indirect: offset=0x%x dwords=%d\n", + offset, dwords ); + + if ( 0 ) { + u32 *data = (u32 *) + ((char *)dev_priv->buffers->handle + + buf->offset + start); + int i; + DRM_INFO( "data = %p\n", data ); + for ( i = 0 ; i < dwords ; i++ ) { + DRM_INFO( "data[0x%x] = 0x%08x\n", + i, data[i] ); + } + } + buf_priv->dispatched = 1; /* Fire off the indirect buffer */ @@ -610,7 +816,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf ) OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) ); OUT_RING( offset ); - OUT_RING( size ); + OUT_RING( dwords ); ADVANCE_RING(); } @@ -627,7 +833,110 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf ) ADVANCE_RING(); buf->pending = 1; + /* FIXME: Check dispatched field */ + buf_priv->dispatched = 0; + } + + dev_priv->sarea_priv->last_dispatch++; + +#if 0 + if ( dev_priv->submit_age == R128_MAX_VB_AGE ) { + ret = r128_do_cce_idle( dev_priv ); + if ( ret < 0 ) return ret; + dev_priv->submit_age = 0; + r128_freelist_reset( dev ); + } +#endif +} + +static void r128_cce_dispatch_indices( drm_device_t *dev, + drm_buf_t *buf, + int start, int end ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv = buf->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + + int vertsize = sarea_priv->vertsize; + int format = sarea_priv->vc_format; + int index = buf->idx; + int offset = dev_priv->buffers->offset - dev->agp->base; + int prim = buf_priv->prim; + + u32 *data; + + int dwords; + int i = 0; + RING_LOCALS; + DRM_DEBUG( "%s: start=%d end=%d\n", __FUNCTION__, start, end ); + + r128_update_ring_snapshot( dev_priv ); + + if ( 0 ) + r128_print_dirty( "dispatch_indices", sarea_priv->dirty ); + + if ( start != end ) { + buf_priv->dispatched = 1; + + if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) { + r128_emit_state( dev_priv ); + } + + /* Adjust start offset to include packet header + */ + start -= R128_INDEX_PRIM_OFFSET; + dwords = (end - start + 3) / sizeof(u32); + + data = (u32 *)((char *)dev_priv->buffers->handle + + buf->offset + start); + + data[0] = CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); + + data[1] = offset; + data[2] = R128_MAX_VB_VERTS; + data[3] = format; + data[4] = (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | + (R128_MAX_VB_VERTS << 16)); + + if ( (end - start) & 0x3 ) { + data[dwords-1] &= 0x0000ffff; + } + + if ( 0 ) { + int i; + DRM_INFO( "data = %p\n", data ); + for ( i = 0 ; i < dwords ; i++ ) { + DRM_INFO( "data[0x%x] = 0x%08x\n", + i, data[i] ); + } + } + + do { + /* Emit the next set of up to three cliprects */ + if ( i < sarea_priv->nbox ) { + r128_emit_clip_rects( dev_priv, + &sarea_priv->boxes[i], + sarea_priv->nbox - i ); + } + + r128_cce_dispatch_indirect( dev, buf, start, end ); + + i += 3; + } while ( i < sarea_priv->nbox ); + } + + if ( buf_priv->discard ) { + buf_priv->age = dev_priv->sarea_priv->last_dispatch; + /* Emit the vertex buffer age */ + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); + OUT_RING( buf_priv->age ); + + ADVANCE_RING(); + + buf->pending = 1; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } @@ -642,6 +951,9 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf ) r128_freelist_reset( dev ); } #endif + + sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; + sarea_priv->nbox = 0; } static int r128_cce_dispatch_blit( drm_device_t *dev, @@ -653,12 +965,18 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_blit_rect_t *rect; - drm_r128_blit_packet_t *blit; + u32 *data; int dword_shift, dwords; int i; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + r128_update_ring_snapshot( dev_priv ); + + /* The compiler won't optimize away a division by a variable, + * even if the only legal values are powers of two. Thus, we'll + * use a shift instead. + */ switch ( format ) { case R128_DATATYPE_ARGB1555: case R128_DATATYPE_RGB565: @@ -707,38 +1025,30 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, dwords = (rect->width * rect->height) >> dword_shift; - blit = (drm_r128_blit_packet_t *) - ((char *)dev_priv->buffers->handle + buf->offset); - - blit->header = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, - dwords + 6 ); - blit->gui_master_cntl = ( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_NONE - | (format << 8) - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_S - | R128_DP_SRC_SOURCE_HOST_DATA - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS - | R128_GMC_WR_MSK_DIS ); - - blit->dst_pitch_offset = (pitch << 21) | (offset >> 5); - blit->fg_color = 0xffffffff; - blit->bg_color = 0xffffffff; - blit->x = rect->x; - blit->y = rect->y; - blit->width = rect->width; - blit->height = rect->height; - blit->dwords = dwords; - - /* FIXME: This should really go in the function call... - */ - if ( dwords & 1 ) { - blit->data[dwords++] = R128_CCE_PACKET2; - } + data = (u32 *)((char *)dev_priv->buffers->handle + + buf->offset); + + data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ); + data[1] = ( R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_NONE + | (format << 8) + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_S + | R128_DP_SRC_SOURCE_HOST_DATA + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS + | R128_GMC_WR_MSK_DIS ); + + data[2] = (pitch << 21) | (offset >> 5); + data[3] = 0xffffffff; + data[4] = 0xffffffff; + data[5] = (rect->y << 16) | rect->x; + data[6] = (rect->height << 16) | rect->width; + data[7] = dwords; + buf->used = (dwords + 8) * sizeof(u32); - r128_cce_dispatch_indirect( dev, buf ); + r128_cce_dispatch_indirect( dev, buf, 0, buf->used ); } /* Flush the pixel cache after the blit completes. This ensures @@ -847,9 +1157,9 @@ int r128_cce_vertex( struct inode *inode, struct file *filp, sizeof(vertex) ) ) return -EFAULT; - DRM_DEBUG( "%s: pid=%d index=%d used=%d discard=%d\n", + DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", __FUNCTION__, current->pid, - vertex.idx, vertex.used, vertex.discard ); + vertex.idx, vertex.count, vertex.discard ); if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", @@ -875,7 +1185,7 @@ int r128_cce_vertex( struct inode *inode, struct file *filp, return -EINVAL; } - buf->used = vertex.used; + buf->used = vertex.count; buf_priv->prim = vertex.prim; buf_priv->discard = vertex.discard; @@ -884,6 +1194,71 @@ int r128_cce_vertex( struct inode *inode, struct file *filp, return 0; } +int r128_cce_indices( 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_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_r128_buf_priv_t *buf_priv; + drm_r128_indices_t elts; + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } + if ( !dev_priv || dev_priv->is_pci ) { + DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( &elts, (drm_r128_indices_t *)arg, + sizeof(elts) ) ) + return -EFAULT; + + DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n", + __FUNCTION__, current->pid, + elts.idx, elts.start, elts.end, elts.discard ); + + if ( elts.idx < 0 || elts.idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + elts.idx, dma->buf_count - 1 ); + return -EINVAL; + } + if ( elts.prim < 0 || + elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { + DRM_ERROR( "buffer prim %d\n", elts.prim ); + return -EINVAL; + } + + buf = dma->buflist[elts.idx]; + buf_priv = buf->dev_private; + + if ( buf->pid != current->pid ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + current->pid, buf->pid ); + return -EINVAL; + } + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", elts.idx ); + return -EINVAL; + } + if ( (buf->offset + elts.start) & 0x3 ) { + DRM_ERROR( "buffer start 0x%x\n", buf->offset + elts.start ); + return -EINVAL; + } + + buf_priv->prim = elts.prim; + buf_priv->discard = elts.discard; + + r128_cce_dispatch_indices( dev, buf, elts.start, elts.end ); + + return 0; +} + int r128_cce_blit( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { @@ -891,7 +1266,6 @@ int r128_cce_blit( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; drm_r128_blit_t blit; - drm_r128_blit_rect_t rects[R128_MAX_BLIT_BUFFERS]; if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { diff --git a/shared-core/drm.h b/shared-core/drm.h index cf0618e4..6a4099bd 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -364,14 +364,15 @@ typedef struct drm_agp_info { /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) -#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x48, drm_r128_vertex_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x49, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x50, drm_r128_packet_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) #endif diff --git a/shared/drm.h b/shared/drm.h index cf0618e4..6a4099bd 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -364,14 +364,15 @@ typedef struct drm_agp_info { /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) -#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t) #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x48, drm_r128_vertex_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x49, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x50, drm_r128_packet_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x46) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) #endif |