diff options
author | Gareth Hughes <gareth@users.sourceforge.net> | 2000-11-05 14:50:04 +0000 |
---|---|---|
committer | Gareth Hughes <gareth@users.sourceforge.net> | 2000-11-05 14:50:04 +0000 |
commit | 81f4398ed712a6e26c49da2c231549f36222cd25 (patch) | |
tree | bc50e67bdd3d11546515fcf4855f976386c0cb1a | |
parent | 79857ad822f65aa9e5037feffcd993f4bb830b2d (diff) |
Greatly improve interactivity with MMIO-based 2D acceleration by only
turning CCE off when the X server actually has to do some 2D rendering.
We test if the CCE is running at the start of each accel routine, and
if so we shut it down. If we've shut it down, we start it up again in
LeaveServer(). An extra if statement in the accel routines is worth it,
IMNSHO.
Updates to the elt path code. Allow indirect buffer firing to specify start
and end parameters for buffer reuse. DRM ioctls and wrappers adjusted
accordingly. Still disabled by default.
-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 |