summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/r128_drv.c165
-rw-r--r--linux/drm.h15
-rw-r--r--linux/fops.c22
-rw-r--r--linux/r128_cce.c91
-rw-r--r--linux/r128_drm.h26
-rw-r--r--linux/r128_drv.c165
-rw-r--r--linux/r128_drv.h24
-rw-r--r--linux/r128_state.c478
-rw-r--r--shared-core/drm.h15
-rw-r--r--shared/drm.h15
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