summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Hughes <gareth@users.sourceforge.net>2000-09-19 16:40:02 +0000
committerGareth Hughes <gareth@users.sourceforge.net>2000-09-19 16:40:02 +0000
commitcc57f63b8f9ab759a1217e9532a9d7c48b7f684f (patch)
treea8ae06651c911ed9c81a13b5a3903f3d69400574
parent83253109dc9400daece9111d9a832587ce3690ed (diff)
Somewhat unstable development work. Use at your own risk.
-rw-r--r--linux-core/Makefile.kernel3
-rw-r--r--linux-core/r128_drv.c36
-rw-r--r--linux/Makefile.kernel3
-rw-r--r--linux/Makefile.linux8
-rw-r--r--linux/r128_bufs.c38
-rw-r--r--linux/r128_cce.c970
-rw-r--r--linux/r128_context.c22
-rw-r--r--linux/r128_dma.c909
-rw-r--r--linux/r128_drm.h227
-rw-r--r--linux/r128_drv.c36
-rw-r--r--linux/r128_drv.h378
-rw-r--r--linux/r128_state.c464
12 files changed, 1912 insertions, 1182 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index b1b8d9768..278ff264c 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -38,7 +38,8 @@ endif
gamma-objs := $(lib-objs) gamma_drv.o gamma_dma.o
tdfx-objs := $(lib-objs) tdfx_drv.o tdfx_context.o
-r128-objs := $(lib-objs) r128_drv.o r128_dma.o r128_context.o r128_bufs.o
+r128-objs := $(lib-objs) r128_drv.o r128_cce.o r128_context.o r128_bufs.o\
+ r128_state.o
ffb-objs := $(lib-objs) ffb_drv.o ffb_context.o
mga-objs := $(lib-objs) mga_drv.o mga_dma.o mga_context.o mga_bufs.o \
mga_state.o
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c
index b58dcf066..6393812e2 100644
--- a/linux-core/r128_drv.c
+++ b/linux-core/r128_drv.c
@@ -33,15 +33,15 @@
#include "drmP.h"
#include "r128_drv.h"
-#define R128_NAME "r128"
-#define R128_DESC "ATI Rage 128"
-#define R128_DATE "20000910"
-#define R128_MAJOR 1
-#define R128_MINOR 0
-#define R128_PATCHLEVEL 0
+#define R128_NAME "r128"
+#define R128_DESC "ATI Rage 128"
+#define R128_DATE "20000905"
+#define R128_MAJOR 1
+#define R128_MINOR 1
+#define R128_PATCHLEVEL 0
-static drm_device_t r128_device;
-drm_ctx_t r128_res_ctx;
+static drm_device_t r128_device;
+drm_ctx_t r128_res_ctx;
static struct file_operations r128_fops = {
#if LINUX_VERSION_CODE >= 0x020400
@@ -108,9 +108,9 @@ static drm_ioctl_desc_t r128_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_IDLE)] = { r128_cce_idle, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 },
};
#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
@@ -425,13 +425,13 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd,
sizeof(version)))
return -EFAULT;
-#define DRM_COPY(name,value) \
- len = strlen(value); \
- if (len > name##_len) len = name##_len; \
- name##_len = strlen(value); \
- if (len && name) { \
- if (copy_to_user(name, value, len)) \
- return -EFAULT; \
+#define DRM_COPY(name,value) \
+ len = strlen(value); \
+ if (len > name##_len) len = name##_len; \
+ name##_len = strlen(value); \
+ if (len && name) { \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = R128_MAJOR;
@@ -666,6 +666,7 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd,
dev->sigdata.context = lock.context;
dev->sigdata.lock = dev->lock.hw_lock;
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
@@ -730,6 +731,7 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
current->priority = DEF_PRIORITY;
}
#endif
+
unblock_all_signals();
return 0;
}
diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel
index b1b8d9768..278ff264c 100644
--- a/linux/Makefile.kernel
+++ b/linux/Makefile.kernel
@@ -38,7 +38,8 @@ endif
gamma-objs := $(lib-objs) gamma_drv.o gamma_dma.o
tdfx-objs := $(lib-objs) tdfx_drv.o tdfx_context.o
-r128-objs := $(lib-objs) r128_drv.o r128_dma.o r128_context.o r128_bufs.o
+r128-objs := $(lib-objs) r128_drv.o r128_cce.o r128_context.o r128_bufs.o\
+ r128_state.o
ffb-objs := $(lib-objs) ffb_drv.o ffb_context.o
mga-objs := $(lib-objs) mga_drv.o mga_dma.o mga_context.o mga_bufs.o \
mga_state.o
diff --git a/linux/Makefile.linux b/linux/Makefile.linux
index 7fe57f8e3..d92d259ac 100644
--- a/linux/Makefile.linux
+++ b/linux/Makefile.linux
@@ -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.
-#
+#
# $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux,v 1.9 2000/08/04 03:51:47 tsi Exp $
#
# ***** NOTE NOTE NOTE NOTE NOTE *****
@@ -62,7 +62,7 @@ GAMMAHEADERS= gamma_drv.h $(DRMHEADERS)
TDFXOBJS= tdfx_drv.o tdfx_context.o
TDFXHEADERS= tdfx_drv.h $(DRMHEADERS)
-R128OBJS= r128_drv.o r128_dma.o r128_bufs.o r128_context.o
+R128OBJS= r128_drv.o r128_cce.o r128_bufs.o r128_state.o r128_context.o
R128HEADERS= r128_drv.h r128_drm.h $(DRMHEADERS)
PROGOBJS= drmstat.po xf86drm.po xf86drmHash.po xf86drmRandom.po sigio.po
diff --git a/linux/r128_bufs.c b/linux/r128_bufs.c
index 7e76441ee..0053c0feb 100644
--- a/linux/r128_bufs.c
+++ b/linux/r128_bufs.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,11 +23,11 @@
* 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: Kevin E. Martin <martin@valinux.com>
* Rickard E. (Rik) Faith <faith@valinux.com>
* Jeff Hartmann <jhartmann@valinux.com>
- *
+ *
*/
#define __NO_VERSION__
@@ -60,9 +60,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dma) return -EINVAL;
- if (copy_from_user(&request,
- (drm_buf_desc_t *)arg,
- sizeof(request)))
+ if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
return -EFAULT;
count = request.count;
@@ -94,7 +92,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
}
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
-
+
down(&dev->struct_sem);
entry = &dma->bufs[order];
if (entry->buf_count) {
@@ -102,7 +100,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
-
+
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
@@ -111,7 +109,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
return -ENOMEM;
}
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
+
entry->buf_size = size;
entry->page_order = page_order;
offset = 0;
@@ -173,9 +171,7 @@ int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
request.count = entry->buf_count;
request.size = size;
- if (copy_to_user((drm_buf_desc_t *)arg,
- &request,
- sizeof(request)))
+ if (copy_to_user((drm_buf_desc_t *)arg, &request, sizeof(request)))
return -EFAULT;
dma->flags = _DRM_DMA_USE_AGP;
@@ -195,9 +191,7 @@ int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (!dev_priv || dev_priv->is_pci) return -EINVAL;
- if (copy_from_user(&request,
- (drm_buf_desc_t *)arg,
- sizeof(request)))
+ if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
return -EFAULT;
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
@@ -234,9 +228,7 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
++dev->buf_use; /* Can't allocate more after this call */
spin_unlock(&dev->count_lock);
- if (copy_from_user(&request,
- (drm_buf_map_t *)arg,
- sizeof(request)))
+ if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request)))
return -EFAULT;
if (request.count >= dma->buf_count) {
@@ -250,9 +242,9 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
}
down(&current->mm->mmap_sem);
- virtual = do_mmap(filp, 0, map->size,
+ virtual = do_mmap(filp, 0, map->size,
PROT_READ|PROT_WRITE,
- MAP_SHARED,
+ MAP_SHARED,
(unsigned long)map->offset);
up(&current->mm->mmap_sem);
} else {
@@ -300,9 +292,7 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
request.count = dma->buf_count;
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
- if (copy_to_user((drm_buf_map_t *)arg,
- &request,
- sizeof(request)))
+ if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request)))
return -EFAULT;
return retcode;
diff --git a/linux/r128_cce.c b/linux/r128_cce.c
new file mode 100644
index 000000000..d9f988ed1
--- /dev/null
+++ b/linux/r128_cce.c
@@ -0,0 +1,970 @@
+/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * 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: Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "r128_drv.h"
+
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+
+
+/* FIXME: Temporary CCE packet buffer */
+u32 r128_cce_buffer[(1 << 14)] __attribute__ ((aligned (32)));
+
+
+#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+
+#define DO_REMAPFREE(_m) \
+ do { \
+ if ((_m)->handle && (_m)->size) \
+ drm_ioremapfree((_m)->handle, (_m)->size); \
+ } while (0)
+
+#define DO_FIND_MAP(_m, _o) \
+ do { \
+ int _i; \
+ for (_i = 0; _i < dev->map_count; _i++) { \
+ if (dev->maplist[_i]->offset == _o) { \
+ _m = dev->maplist[_i]; \
+ break; \
+ } \
+ } \
+ } while (0)
+
+
+int R128_READ_PLL(drm_device_t *dev, int addr)
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return R128_READ(R128_CLOCK_CNTL_DATA);
+}
+
+/* GH: This should really use my PIII mb() patch */
+#define r128_flush_write_combine() mb()
+
+
+static void r128_status(drm_device_t *dev)
+{
+ 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));
+}
+
+static int r128_do_cleanup_cce(drm_device_t *dev)
+{
+ if (dev->dev_private) {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ if (!dev_priv->is_pci) {
+ DO_REMAPFREE(dev_priv->agp_ring);
+ DO_REMAPFREE(dev_priv->agp_read_ptr);
+ DO_REMAPFREE(dev_priv->agp_vertbufs);
+ DO_REMAPFREE(dev_priv->agp_indbufs);
+ DO_REMAPFREE(dev_priv->agp_textures);
+ }
+
+ drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+ DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init)
+{
+ drm_r128_private_t *dev_priv;
+ int i;
+
+ dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL) return -ENOMEM;
+ dev->dev_private = (void *)dev_priv;
+
+ memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+ dev_priv->is_pci = init->is_pci;
+
+ dev_priv->usec_timeout = init->usec_timeout;
+ if (dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
+ drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ dev_priv->cce_mode = init->cce_mode;
+ dev_priv->cce_fifo_size = init->cce_fifo_size;
+ dev_priv->cce_is_bm_mode =
+ ((init->cce_mode == R128_PM4_192BM) ||
+ (init->cce_mode == R128_PM4_128BM_64INDBM) ||
+ (init->cce_mode == R128_PM4_64BM_128INDBM) ||
+ (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM));
+ dev_priv->cce_secure = init->cce_secure;
+
+ dev_priv->cce_buffer = r128_cce_buffer;
+
+ if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) {
+ drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < dev->map_count; i++) {
+ if (dev->maplist[i]->type == _DRM_SHM) {
+ dev_priv->sarea = dev->maplist[i];
+ break;
+ }
+ }
+
+ DO_FIND_MAP(dev_priv->fb, init->fb_offset);
+ if (!dev_priv->is_pci) {
+ DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset);
+ DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset);
+ DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset);
+ DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset);
+ DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset);
+ }
+ DO_FIND_MAP(dev_priv->mmio, init->mmio_offset);
+
+ dev_priv->sarea_priv =
+ (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ if (!dev_priv->is_pci) {
+ DO_REMAP(dev_priv->agp_ring);
+ DO_REMAP(dev_priv->agp_read_ptr);
+ DO_REMAP(dev_priv->agp_vertbufs);
+#if 0
+ DO_REMAP(dev_priv->agp_indirectbufs);
+ DO_REMAP(dev_priv->agp_textures);
+#endif
+
+ dev_priv->ring_size = init->ring_size;
+ dev_priv->ring_sizel2qw = drm_order(init->ring_size/8);
+ dev_priv->ring_entries = init->ring_size/sizeof(u32);
+ dev_priv->ring_read_ptr = ((__volatile__ u32 *)
+ dev_priv->agp_read_ptr->handle);
+ dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle;
+ dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle
+ + dev_priv->ring_entries);
+ }
+
+ dev_priv->submit_age = 0;
+ R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age);
+
+ return 0;
+}
+
+
+
+/* ================================================================
+ * GH: Done from here down
+ */
+
+int r128_init_cce( 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_init_t init;
+
+ if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
+ return -EFAULT;
+
+ switch ( init.func ) {
+ case R128_INIT_CCE:
+ return r128_do_init_cce( dev, &init );
+ case R128_CLEANUP_CCE:
+ return r128_do_cleanup_cce( dev );
+ }
+
+ return -EINVAL;
+}
+
+
+/* ================================================================
+ * Freelist management
+ */
+
+void r128_freelist_reset( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+}
+
+drm_buf_t *r128_freelist_get( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+
+ /* FIXME: Optimize -- use freelist code */
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pid == 0 ) return buf;
+ }
+
+ for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+ u32 done_age = R128_READ( R128_VB_AGE_REG );
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pending && buf_priv->age <= done_age ) {
+ /* The buffer has been processed, so it
+ * can now be used.
+ */
+ buf->pending = 0;
+ return buf;
+ }
+ }
+ udelay( 1 );
+ }
+
+ r128_status( dev );
+ return NULL;
+}
+
+
+/* ================================================================
+ * Engine control
+ */
+
+static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
+{
+ u32 tmp;
+ int i;
+
+ tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
+ R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
+ return 0;
+ }
+ udelay( 1 );
+ }
+
+ return -EBUSY;
+}
+
+static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
+{
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
+ if ( slots >= entries ) return 0;
+ udelay( 1 );
+ }
+ return -EBUSY;
+}
+
+int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
+{
+ int i, ret;
+
+ ret = r128_do_wait_for_fifo( dev_priv, 64 );
+ if ( !ret ) return ret;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
+ r128_do_pixcache_flush( dev_priv );
+ return 0;
+ }
+ udelay( 1 );
+ }
+ return -EBUSY;
+}
+
+static int r128_do_engine_reset( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
+
+ r128_do_pixcache_flush( dev_priv );
+
+ clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
+ mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
+
+ R128_WRITE_PLL( R128_MCLK_CNTL,
+ mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
+
+ gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
+
+ /* Taken from the sample code - do not change */
+ R128_WRITE( R128_GEN_RESET_CNTL,
+ gen_reset_cntl | R128_SOFT_RESET_GUI );
+ R128_READ( R128_GEN_RESET_CNTL );
+ R128_WRITE( R128_GEN_RESET_CNTL,
+ gen_reset_cntl & ~R128_SOFT_RESET_GUI );
+ R128_READ( R128_GEN_RESET_CNTL );
+
+ R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
+ R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
+ R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
+
+ /* For CCE ring buffer only */
+ if ( dev_priv->cce_is_bm_mode ) {
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
+ R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
+ *dev_priv->ring_read_ptr = 0;
+ dev_priv->sarea_priv->ring_write = 0;
+ }
+
+ /* Reset the CCE mode */
+ r128_do_wait_for_idle( dev_priv );
+ R128_WRITE( R128_PM4_BUFFER_CNTL,
+ dev_priv->cce_mode | dev_priv->ring_sizel2qw );
+ R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
+ R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
+
+ r128_freelist_reset( dev );
+ return 0;
+}
+
+int r128_eng_reset( 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;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_eng_reset called without lock held\n" );
+ return -EINVAL;
+ }
+
+ return r128_do_engine_reset( dev );
+}
+
+static int r128_do_engine_flush( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 tmp;
+
+ tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR );
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE );
+
+ return 0;
+}
+
+int r128_eng_flush( 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;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_eng_flush called without lock held\n" );
+ return -EINVAL;
+ }
+
+ return r128_do_engine_flush( dev );
+}
+
+
+/* ================================================================
+ * CCE FIFO control
+ */
+
+static int r128_do_cce_wait_for_fifo( drm_r128_private_t *dev_priv,
+ int entries )
+{
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ int slots = R128_READ( R128_PM4_STAT ) & R128_PM4_FIFOCNT_MASK;
+ if ( slots >= entries ) return 0;
+ udelay( 1 );
+ }
+ return -EBUSY;
+}
+
+static inline int r128_do_cce_idle_ring( drm_r128_private_t *dev_priv )
+{
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( *dev_priv->ring_read_ptr ==
+ dev_priv->sarea_priv->ring_write ) {
+ int pm4stat = R128_READ( R128_PM4_STAT );
+ if ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
+ dev_priv->cce_fifo_size &&
+ !(pm4stat & (R128_PM4_BUSY |
+ R128_PM4_GUI_ACTIVE)) ) {
+ return r128_do_pixcache_flush( dev_priv );
+ }
+ }
+ udelay( 1 );
+ }
+ return -EBUSY;
+}
+
+static inline int r128_do_cce_idle_pio( drm_r128_private_t *dev_priv )
+{
+ int ret;
+ int i;
+
+ ret = r128_do_cce_wait_for_fifo( dev_priv, dev_priv->cce_fifo_size );
+ if ( ret < 0 ) return ret;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ int pm4stat = R128_READ( R128_PM4_STAT );
+ if ( !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)) ) {
+ return r128_do_pixcache_flush( dev_priv );
+ }
+ udelay( 1 );
+ }
+ return -EBUSY;
+}
+
+static int r128_do_cce_idle( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ if ( dev_priv->cce_is_bm_mode ) {
+ return r128_do_cce_idle_ring( dev_priv );
+ } else {
+ return r128_do_cce_idle_pio( dev_priv );
+ }
+}
+
+int r128_cce_idle( 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;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_wait_idle called without lock held\n" );
+ return -EINVAL;
+ }
+
+ return r128_do_cce_idle( dev );
+}
+
+
+/* ================================================================
+ * CCE packet submission
+ */
+
+static int r128_verify_command( drm_r128_private_t *dev_priv,
+ u32 cmd, int *size )
+{
+ int writing = 1;
+
+ *size = 0;
+
+ switch ( cmd & R128_CCE_PACKET_MASK ) {
+ case R128_CCE_PACKET0:
+ if ( (cmd & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2) &&
+ (cmd & R128_CCE_PACKET0_REG_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2) ) {
+ writing = 0;
+ }
+ *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ break;
+
+ case R128_CCE_PACKET1:
+ if ( (cmd & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2) &&
+ (cmd & R128_CCE_PACKET1_REG0_MASK) !=
+ (R128_PM4_VC_FPU_SETUP >> 2) ) {
+ writing = 0;
+ }
+ if ( (cmd & R128_CCE_PACKET1_REG1_MASK) <= (0x1004 << 9) &&
+ (cmd & R128_CCE_PACKET1_REG1_MASK) !=
+ (R128_PM4_VC_FPU_SETUP << 9) ) {
+ writing = 0;
+ }
+ *size = 3;
+ break;
+
+ case R128_CCE_PACKET2:
+ break;
+
+ case R128_CCE_PACKET3:
+ *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
+ break;
+
+ }
+
+ return writing;
+}
+
+static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv,
+ u32 *commands, int *count )
+{
+ int write = dev_priv->sarea_priv->ring_write;
+ int *write_ptr = dev_priv->ring_start + write;
+ int c = *count;
+ u32 tmp = 0;
+ int psize = 0;
+ int writing = 1;
+ int timeout;
+
+ while ( c > 0 ) {
+ tmp = *commands++;
+ if ( !psize ) {
+ writing = r128_verify_command( dev_priv, tmp, &psize );
+ }
+ psize--;
+
+ if ( writing ) {
+ write++;
+ *write_ptr++ = tmp;
+ }
+ if ( write >= dev_priv->ring_entries ) {
+ write = 0;
+ write_ptr = dev_priv->ring_start;
+ }
+ timeout = 0;
+ while ( write == *dev_priv->ring_read_ptr ) {
+ R128_READ( R128_PM4_BUFFER_DL_RPTR );
+ if ( timeout++ >= dev_priv->usec_timeout )
+ return -EBUSY;
+ udelay( 1 );
+ }
+ c--;
+ }
+
+ if ( write < 32 ) {
+ memcpy( dev_priv->ring_end,
+ dev_priv->ring_start,
+ write * sizeof(u32) );
+ }
+
+ /* Make sure WC cache has been flushed */
+ r128_flush_write_combine();
+
+ dev_priv->sarea_priv->ring_write = write;
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
+
+ *count = 0;
+
+ return 0;
+}
+
+static int r128_submit_packet_pio_secure( drm_r128_private_t *dev_priv,
+ u32 *commands, int *count )
+{
+ u32 tmp = 0;
+ int psize = 0;
+ int writing = 1;
+ int addr = R128_PM4_FIFO_DATA_EVEN;
+ int ret;
+
+ while ( *count > 0 ) {
+ tmp = *commands++;
+ if (!psize) {
+ writing = r128_verify_command( dev_priv, tmp, &psize );
+ }
+ psize--;
+
+ if ( writing ) {
+ ret = r128_do_cce_wait_for_fifo( dev_priv, 1 );
+ if ( ret ) return ret;
+ R128_WRITE( addr, tmp );
+ addr ^= 0x0004;
+ }
+
+ *count -= 1;
+ }
+
+ if ( addr == R128_PM4_FIFO_DATA_ODD ) {
+ ret = r128_do_cce_wait_for_fifo( dev_priv, 1 );
+ if ( ret < 0 ) return ret;
+ R128_WRITE( addr, R128_CCE_PACKET2 );
+ }
+
+ return 0;
+}
+
+static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv,
+ u32 *commands, int *count )
+{
+ int write = dev_priv->sarea_priv->ring_write;
+ int *write_ptr = dev_priv->ring_start + write;
+ int c = *count;
+ int timeout;
+
+ while ( c > 0 ) {
+ write++;
+ *write_ptr++ = *commands++;
+ if ( write >= dev_priv->ring_entries ) {
+ write = 0;
+ write_ptr = dev_priv->ring_start;
+ }
+
+ timeout = 0;
+ while ( write == *dev_priv->ring_read_ptr ) {
+ R128_READ( R128_PM4_BUFFER_DL_RPTR );
+ if ( timeout++ >= dev_priv->usec_timeout )
+ return -EBUSY;
+ udelay( 1 );
+ }
+ c--;
+ }
+
+ if ( write < 32 ) {
+ memcpy( dev_priv->ring_end,
+ dev_priv->ring_start,
+ write * sizeof(u32) );
+ }
+
+ /* Make sure WC cache has been flushed */
+ r128_flush_write_combine();
+
+ dev_priv->sarea_priv->ring_write = write;
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
+
+ *count = 0;
+
+ return 0;
+}
+
+static int r128_submit_packet_pio_insecure( drm_r128_private_t *dev_priv,
+ u32 *commands, int *count )
+{
+ int ret;
+
+ while ( *count > 1 ) {
+ ret = r128_do_cce_wait_for_fifo( dev_priv, 2 );
+ if ( ret < 0 ) return ret;
+ R128_WRITE( R128_PM4_FIFO_DATA_EVEN, *commands++ );
+ R128_WRITE( R128_PM4_FIFO_DATA_ODD, *commands++ );
+ *count -= 2;
+ }
+
+ if ( *count ) {
+ ret = r128_do_cce_wait_for_fifo( dev_priv, 2 );
+ if ( ret < 0 ) return ret;
+ R128_WRITE( R128_PM4_FIFO_DATA_EVEN, *commands++ );
+ R128_WRITE( R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2 );
+ *count = 0;
+ }
+
+ return 0;
+}
+
+/* Internal packet submission routine. This uses the insecure versions
+ * of the packet submission functions, and thus should only be used for
+ * packets generated inside the kernel module.
+ */
+int r128_do_submit_packet( drm_r128_private_t *dev_priv,
+ u32 *buffer, int count )
+{
+ int c = count;
+ int ret;
+
+ if ( dev_priv->cce_is_bm_mode ) {
+ int left = 0;
+
+ if ( c >= dev_priv->ring_entries ) {
+ c = dev_priv->ring_entries - 1;
+ left = count - c;
+ }
+
+ /* Since this is only used by the kernel we can use the
+ * insecure ring buffer submit packet routine.
+ */
+ ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c );
+ c += left;
+ } else {
+ /* Since this is only used by the kernel we can use the
+ * insecure PIO submit packet routine.
+ */
+ ret = r128_submit_packet_pio_insecure( dev_priv, buffer, &c );
+ }
+
+ return ( ret < 0 ) ? ret : c;
+}
+
+/* External packet submission routine. This uses the secure versions
+ * by default, and can thus submit packets received from user space.
+ */
+int r128_cce_packet( 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_packet_t packet;
+ u32 *buffer;
+ int c;
+ int size;
+ int ret = 0;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_submit_packet called without lock held\n" );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &packet, (drm_r128_packet_t *)arg,
+ sizeof(packet) ) )
+ return -EFAULT;
+
+ c = packet.count;
+ size = c * sizeof(*buffer);
+
+ if ( dev_priv->cce_is_bm_mode ) {
+ int left = 0;
+
+ if ( c >= dev_priv->ring_entries ) {
+ c = dev_priv->ring_entries - 1;
+ size = c * sizeof(*buffer);
+ left = packet.count - c;
+ }
+
+ buffer = kmalloc( size, 0 );
+ if ( buffer == NULL)
+ return -ENOMEM;
+ if ( copy_from_user( buffer, packet.buffer, size ) )
+ return -EFAULT;
+
+ if ( dev_priv->cce_secure ) {
+ ret = r128_submit_packet_ring_secure( dev_priv,
+ buffer, &c );
+ } else {
+ ret = r128_submit_packet_ring_insecure( dev_priv,
+ buffer, &c );
+ }
+ c += left;
+ } else {
+ buffer = kmalloc( size, 0 );
+ if ( buffer == NULL )
+ return -ENOMEM;
+ if ( copy_from_user( buffer, packet.buffer, size ) )
+ return -EFAULT;
+
+ if ( dev_priv->cce_secure ) {
+ ret = r128_submit_packet_pio_secure( dev_priv,
+ buffer, &c );
+ } else {
+ ret = r128_submit_packet_pio_insecure( dev_priv,
+ buffer, &c );
+ }
+ }
+
+ kfree( buffer );
+
+ packet.count = c;
+ if ( copy_to_user( (drm_r128_packet_t *)arg, &packet,
+ sizeof(packet) ) )
+ return -EFAULT;
+
+ if ( ret ) {
+ return ret;
+ } else if ( c > 0 ) {
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+#if 0
+static int r128_send_vertbufs( drm_device_t *dev, drm_r128_vertex_t *v )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, ret;
+ RING_LOCALS;
+
+ /* Make sure we have valid data */
+ for (i = 0; i < v->send_count; i++) {
+ int idx = v->send_indices[i];
+
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("Index %d (of %d max)\n",
+ idx, dma->buf_count - 1);
+ return -EINVAL;
+ }
+ buf = dma->buflist[idx];
+ 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:"
+ " buffer %d, offset %d\n",
+ v->send_indices[i], i);
+ return -EINVAL;
+ }
+ }
+
+ /* Wait for idle, if we've wrapped to make sure that all pending
+ buffers have been processed */
+ if (dev_priv->submit_age == R128_MAX_VBUF_AGE) {
+ if ((ret = r128_do_cce_idle(dev)) < 0) return ret;
+ dev_priv->submit_age = 0;
+ r128_freelist_reset(dev);
+ }
+
+ /* Make sure WC cache has been flushed (if in PIO mode) */
+ if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine();
+
+ /* FIXME: Add support for sending vertex buffer to the CCE here
+ instead of in client code. The v->prim holds the primitive
+ type that should be drawn. Loop over the list buffers in
+ send_indices[] and submit a packet for each VB.
+
+ This will require us to loop over the clip rects here as
+ well, which implies that we extend the kernel driver to allow
+ cliprects to be stored here. Note that the cliprects could
+ possibly come from the X server instead of the client, but
+ this will require additional changes to the DRI to allow for
+ this optimization. */
+
+ /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */
+#if 0
+ cce_buffer[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0);
+ cce_buffer[1] = dev_priv->submit_age;
+
+ if ((ret = r128_do_submit_packet(dev, cce_buffer, 2)) < 0) {
+ /* Until we add support for sending VBs to the CCE in
+ this routine, we can recover from this error. After
+ we add that support, we won't be able to easily
+ recover, so we will probably have to implement
+ another mechanism for handling timeouts from packets
+ submitted directly by the kernel. */
+ return ret;
+ }
+#else
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_VB_AGE_REG, 0 ) );
+ OUT_RING( dev_priv->submit_age );
+
+ ADVANCE_RING();
+#endif
+ /* Now that the submit packet request has succeeded, we can mark
+ the buffers as pending */
+ for (i = 0; i < v->send_count; i++) {
+ buf = dma->buflist[v->send_indices[i]];
+ buf->pending = 1;
+
+ buf_priv = buf->dev_private;
+ buf_priv->age = dev_priv->submit_age;
+ }
+
+ dev_priv->submit_age++;
+
+ return 0;
+}
+#endif
+
+#if 0
+int r128_dma( 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;
+ int retcode = 0;
+ drm_dma_t d;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_dma called without lock held\n" );
+ return -EINVAL;
+ }
+ if ( !dev_priv || dev_priv->is_pci ) {
+ DRM_ERROR( "r128_dma called with a PCI card\n" );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &v, (drm_r128_vertex_t *)arg, sizeof(v) ) )
+ return -EFAULT;
+ DRM_DEBUG( "%d: %d send, %d req\n",
+ current->pid, v.send_count, v.request_count );
+
+#if 0
+ if ( d.send_count < 0 || d.send_count > dma->buf_count ) {
+ DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
+ current->pid, v.send_count, dma->buf_count);
+ return -EINVAL;
+ }
+#else
+ if ( d.send_count != 0 ) {
+ DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+ current->pid, d.send_count );
+ return -EINVAL;
+ }
+#endif
+ if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+ DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+ current->pid, d.request_count, dma->buf_count );
+ return -EINVAL;
+ }
+#if 0
+ if ( v.send_count ) {
+ retcode = r128_send_vertbufs( dev, &v );
+ }
+#endif
+ v.granted_count = 0;
+
+ if ( /* !retcode && */ d.request_count ) {
+ retcode = r128_get_dma_buffers( dev, &d );
+ }
+
+ DRM_DEBUG( "%d returning, granted = %d\n",
+ current->pid, d.granted_count );
+ if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
+ return -EFAULT;
+
+ return retcode;
+}
+#endif
diff --git a/linux/r128_context.c b/linux/r128_context.c
index 9cadadbaf..0d8b2f5c2 100644
--- a/linux/r128_context.c
+++ b/linux/r128_context.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.
- *
+ *
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
*
*/
@@ -53,21 +53,21 @@ int r128_context_switch(drm_device_t *dev, int old, int new)
#if DRM_DMA_HISTOGRAM
dev->ctx_start = get_cycles();
#endif
-
+
DRM_DEBUG("Context switch from %d to %d\n", old, new);
if (new == dev->last_context) {
clear_bit(0, &dev->context_flag);
return 0;
}
-
+
if (drm_flags & DRM_FLAG_NOCTX) {
r128_context_switch_complete(dev, new);
} else {
sprintf(buf, "C %d %d\n", old, new);
drm_write_string(dev, buf);
}
-
+
return 0;
}
@@ -75,7 +75,7 @@ int r128_context_switch_complete(drm_device_t *dev, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
dev->last_switch = jiffies;
-
+
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("Lock isn't held after context switch\n");
}
@@ -86,11 +86,11 @@ int r128_context_switch_complete(drm_device_t *dev, int new)
#if DRM_DMA_HISTOGRAM
atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
- dev->ctx_start)]);
-
+
#endif
clear_bit(0, &dev->context_flag);
wake_up(&dev->context_wait);
-
+
return 0;
}
@@ -109,9 +109,7 @@ int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- if (copy_to_user(&res.contexts[i],
- &i,
- sizeof(i)))
+ if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
return -EFAULT;
}
}
diff --git a/linux/r128_dma.c b/linux/r128_dma.c
deleted file mode 100644
index bcba67826..000000000
--- a/linux/r128_dma.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
- * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * 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
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * 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: Kevin E. Martin <martin@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "r128_drv.h"
-
-#include <linux/interrupt.h> /* For task queue support */
-#include <linux/delay.h>
-
-
-
-#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
-
-#define DO_REMAPFREE(_m) \
- do { \
- if ((_m)->handle && (_m)->size) \
- drm_ioremapfree((_m)->handle, (_m)->size); \
- } while (0)
-
-#define DO_FIND_MAP(_m, _o) \
- do { \
- int _i; \
- for (_i = 0; _i < dev->map_count; _i++) { \
- if (dev->maplist[_i]->offset == _o) { \
- _m = dev->maplist[_i]; \
- break; \
- } \
- } \
- } while (0)
-
-
-#define R128_MAX_VBUF_AGE 0x10000000
-#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0
-
-int R128_READ_PLL(drm_device_t *dev, int addr)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
-
- R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
- return R128_READ(R128_CLOCK_CNTL_DATA);
-}
-
-#define r128_flush_write_combine() mb()
-
-
-static void r128_status(drm_device_t *dev)
-{
- 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));
-}
-
-static int r128_do_cleanup_cce(drm_device_t *dev)
-{
- if (dev->dev_private) {
- drm_r128_private_t *dev_priv = dev->dev_private;
-
- if (!dev_priv->is_pci) {
- DO_REMAPFREE(dev_priv->agp_ring);
- DO_REMAPFREE(dev_priv->agp_read_ptr);
- DO_REMAPFREE(dev_priv->agp_vertbufs);
- DO_REMAPFREE(dev_priv->agp_indbufs);
- DO_REMAPFREE(dev_priv->agp_textures);
- }
-
- drm_free(dev->dev_private, sizeof(drm_r128_private_t),
- DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- }
-
- return 0;
-}
-
-static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init)
-{
- drm_r128_private_t *dev_priv;
- int i;
-
- dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
- if (dev_priv == NULL) return -ENOMEM;
- dev->dev_private = (void *)dev_priv;
-
- memset(dev_priv, 0, sizeof(drm_r128_private_t));
-
- dev_priv->is_pci = init->is_pci;
-
- dev_priv->usec_timeout = init->usec_timeout;
- if (dev_priv->usec_timeout < 1 ||
- dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- return -EINVAL;
- }
-
- dev_priv->cce_mode = init->cce_mode;
- dev_priv->cce_fifo_size = init->cce_fifo_size;
- dev_priv->cce_is_bm_mode =
- ((init->cce_mode == R128_PM4_192BM) ||
- (init->cce_mode == R128_PM4_128BM_64INDBM) ||
- (init->cce_mode == R128_PM4_64BM_128INDBM) ||
- (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM));
- dev_priv->cce_secure = init->cce_secure;
-
- if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) {
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- return -EINVAL;
- }
-
- for (i = 0; i < dev->map_count; i++) {
- if (dev->maplist[i]->type == _DRM_SHM) {
- dev_priv->sarea = dev->maplist[i];
- break;
- }
- }
-
- DO_FIND_MAP(dev_priv->fb, init->fb_offset);
- if (!dev_priv->is_pci) {
- DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset);
- DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset);
- DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset);
- DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset);
- DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset);
- }
- DO_FIND_MAP(dev_priv->mmio, init->mmio_offset);
-
- dev_priv->sarea_priv =
- (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
- init->sarea_priv_offset);
-
- if (!dev_priv->is_pci) {
- DO_REMAP(dev_priv->agp_ring);
- DO_REMAP(dev_priv->agp_read_ptr);
- DO_REMAP(dev_priv->agp_vertbufs);
-#if 0
- DO_REMAP(dev_priv->agp_indirectbufs);
- DO_REMAP(dev_priv->agp_textures);
-#endif
-
- dev_priv->ring_size = init->ring_size;
- dev_priv->ring_sizel2qw = drm_order(init->ring_size/8);
- dev_priv->ring_entries = init->ring_size/sizeof(u32);
- dev_priv->ring_read_ptr = ((__volatile__ u32 *)
- dev_priv->agp_read_ptr->handle);
- dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle;
- dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle
- + dev_priv->ring_entries);
- }
-
- dev_priv->submit_age = 0;
- R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age);
-
- return 0;
-}
-
-int r128_init_cce(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_init_t init;
-
- if (copy_from_user(&init, (drm_r128_init_t *)arg, sizeof(init)))
- return -EFAULT;
-
- switch (init.func) {
- case R128_INIT_CCE:
- return r128_do_init_cce(dev, &init);
- case R128_CLEANUP_CCE:
- return r128_do_cleanup_cce(dev);
- }
-
- return -EINVAL;
-}
-
-static void r128_mark_vertbufs_done(drm_device_t *dev)
-{
- drm_device_dma_t *dma = dev->dma;
- int i;
-
- for (i = 0; i < dma->buf_count; i++) {
- drm_buf_t *buf = dma->buflist[i];
- drm_r128_buf_priv_t *buf_priv = buf->dev_private;
- buf_priv->age = 0;
- }
-}
-
-static int r128_do_pixcache_flush(drm_device_t *dev)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- u32 tmp;
- int i;
-
- tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
- R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY))
- return 0;
- udelay(1);
- }
-
- return -EBUSY;
-}
-
-static int r128_do_wait_for_fifo(drm_device_t *dev, int entries)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int i;
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
- if (slots >= entries) return 0;
- udelay(1);
- }
- return -EBUSY;
-}
-
-static int r128_do_wait_for_idle(drm_device_t *dev)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int i, ret;
-
- if (!(ret = r128_do_wait_for_fifo(dev, 64))) return ret;
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
- (void)r128_do_pixcache_flush(dev);
- return 0;
- }
- udelay(1);
- }
- return -EBUSY;
-}
-
-int r128_do_engine_reset(drm_device_t *dev)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
-
- (void)r128_do_pixcache_flush(dev);
-
- clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
- mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
-
- R128_WRITE_PLL(R128_MCLK_CNTL,
- mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
-
- gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
-
- R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
- (void)R128_READ(R128_GEN_RESET_CNTL);
- R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
- (void)R128_READ(R128_GEN_RESET_CNTL);
-
- R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
- R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
- R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
-
- /* For CCE ring buffer only */
- if (dev_priv->cce_is_bm_mode) {
- R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
- R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
- *dev_priv->ring_read_ptr = 0;
- dev_priv->sarea_priv->ring_write = 0;
- }
-
- /* Reset the CCE mode */
- (void)r128_do_wait_for_idle(dev);
- R128_WRITE(R128_PM4_BUFFER_CNTL,
- dev_priv->cce_mode | dev_priv->ring_sizel2qw);
- (void)R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */
- R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
-
- r128_mark_vertbufs_done(dev);
- return 0;
-}
-
-int r128_eng_reset(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;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
- dev->lock.pid != current->pid) {
- DRM_ERROR("r128_eng_reset called without holding the lock\n");
- return -EINVAL;
- }
-
- return r128_do_engine_reset(dev);
-}
-
-static int r128_do_engine_flush(drm_device_t *dev)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- u32 tmp;
-
- tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR);
- R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE);
-
- return 0;
-}
-
-int r128_eng_flush(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;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
- dev->lock.pid != current->pid) {
- DRM_ERROR("r128_eng_flush called without holding the lock\n");
- return -EINVAL;
- }
-
- return r128_do_engine_flush(dev);
-}
-
-static int r128_do_cce_wait_for_fifo(drm_device_t *dev, int entries)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int i;
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- int slots = R128_READ(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK;
- if (slots >= entries) return 0;
- udelay(1);
- }
- return -EBUSY;
-}
-
-int r128_do_cce_wait_for_idle(drm_device_t *dev)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int i;
-
- if (dev_priv->cce_is_bm_mode) {
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- if (*dev_priv->ring_read_ptr == dev_priv->sarea_priv->ring_write) {
- int pm4stat = R128_READ(R128_PM4_STAT);
- if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size &&
- !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
- return r128_do_pixcache_flush(dev);
- }
- }
- udelay(1);
- }
- return -EBUSY;
- } else {
- int ret = r128_do_cce_wait_for_fifo(dev, dev_priv->cce_fifo_size);
- if (ret < 0) return ret;
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- int pm4stat = R128_READ(R128_PM4_STAT);
- if (!(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) {
- return r128_do_pixcache_flush(dev);
- }
- udelay(1);
- }
- return -EBUSY;
- }
-}
-
-int r128_cce_idle(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;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
- dev->lock.pid != current->pid) {
- DRM_ERROR("r128_wait_idle called without holding the lock\n");
- return -EINVAL;
- }
-
- return r128_do_cce_wait_for_idle(dev);
-}
-
-static int r128_submit_packets_ring_secure(drm_device_t *dev,
- u32 *commands, int *count)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int write = dev_priv->sarea_priv->ring_write;
- int *write_ptr = dev_priv->ring_start + write;
- int c = *count;
- u32 tmp = 0;
- int psize = 0;
- int writing = 1;
- int timeout;
-
- while (c > 0) {
- tmp = *commands++;
- if (!psize) {
- writing = 1;
-
- if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) {
- if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) {
- if ((tmp & R128_CCE_PACKET0_REG_MASK) !=
- (R128_PM4_VC_FPU_SETUP >> 2)) {
- writing = 0;
- }
- }
- psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
- } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) {
- if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) {
- if ((tmp & R128_CCE_PACKET1_REG0_MASK) !=
- (R128_PM4_VC_FPU_SETUP >> 2)) {
- writing = 0;
- }
- } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <=
- (0x1004 << 9)) {
- if ((tmp & R128_CCE_PACKET1_REG1_MASK) !=
- (R128_PM4_VC_FPU_SETUP << 9)) {
- writing = 0;
- }
- }
- psize = 3;
- } else {
- psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
- }
- }
- psize--;
-
- if (writing) {
- write++;
- *write_ptr++ = tmp;
- }
- if (write >= dev_priv->ring_entries) {
- write = 0;
- write_ptr = dev_priv->ring_start;
- }
- timeout = 0;
- while (write == *dev_priv->ring_read_ptr) {
- (void)R128_READ(R128_PM4_BUFFER_DL_RPTR);
- if (timeout++ >= dev_priv->usec_timeout)
- return -EBUSY;
- udelay(1);
- }
- c--;
- }
-
- if (write < 32)
- memcpy(dev_priv->ring_end,
- dev_priv->ring_start,
- write * sizeof(u32));
-
- /* Make sure WC cache has been flushed */
- r128_flush_write_combine();
-
- dev_priv->sarea_priv->ring_write = write;
- R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write);
-
- *count = 0;
-
- return 0;
-}
-
-static int r128_submit_packets_pio_secure(drm_device_t *dev,
- u32 *commands, int *count)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- u32 tmp = 0;
- int psize = 0;
- int writing = 1;
- int addr = R128_PM4_FIFO_DATA_EVEN;
- int ret;
-
- while (*count > 0) {
- tmp = *commands++;
- if (!psize) {
- writing = 1;
-
- if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) {
- if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) {
- if ((tmp & R128_CCE_PACKET0_REG_MASK) !=
- (R128_PM4_VC_FPU_SETUP >> 2)) {
- writing = 0;
- }
- }
- psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
- } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) {
- if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) {
- if ((tmp & R128_CCE_PACKET1_REG0_MASK) !=
- (R128_PM4_VC_FPU_SETUP >> 2)) {
- writing = 0;
- }
- } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <=
- (0x1004 << 9)) {
- if ((tmp & R128_CCE_PACKET1_REG1_MASK) !=
- (R128_PM4_VC_FPU_SETUP << 9)) {
- writing = 0;
- }
- }
- psize = 3;
- } else {
- psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
- }
- }
- psize--;
-
- if (writing) {
- if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0)
- return ret;
- R128_WRITE(addr, tmp);
- addr ^= 0x0004;
- }
-
- *count -= 1;
- }
-
- if (addr == R128_PM4_FIFO_DATA_ODD) {
- if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) return ret;
- R128_WRITE(addr, R128_CCE_PACKET2);
- }
-
- return 0;
-}
-
-static int r128_submit_packets_ring(drm_device_t *dev,
- u32 *commands, int *count)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int write = dev_priv->sarea_priv->ring_write;
- int *write_ptr = dev_priv->ring_start + write;
- int c = *count;
- int timeout;
-
- while (c > 0) {
- write++;
- *write_ptr++ = *commands++;
- if (write >= dev_priv->ring_entries) {
- write = 0;
- write_ptr = dev_priv->ring_start;
- }
- timeout = 0;
- while (write == *dev_priv->ring_read_ptr) {
- (void)R128_READ(R128_PM4_BUFFER_DL_RPTR);
- if (timeout++ >= dev_priv->usec_timeout)
- return -EBUSY;
- udelay(1);
- }
- c--;
- }
-
- if (write < 32)
- memcpy(dev_priv->ring_end,
- dev_priv->ring_start,
- write * sizeof(u32));
-
- /* Make sure WC cache has been flushed */
- r128_flush_write_combine();
-
- dev_priv->sarea_priv->ring_write = write;
- R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write);
-
- *count = 0;
-
- return 0;
-}
-
-static int r128_submit_packets_pio(drm_device_t *dev,
- u32 *commands, int *count)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int ret;
-
- while (*count > 1) {
- if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret;
- R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++);
- R128_WRITE(R128_PM4_FIFO_DATA_ODD, *commands++);
- *count -= 2;
- }
-
- if (*count) {
- if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret;
- R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++);
- R128_WRITE(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2);
- *count = 0;
- }
-
- return 0;
-}
-
-static int r128_do_submit_packets(drm_device_t *dev, u32 *buffer, int count)
-{
- drm_r128_private_t *dev_priv = dev->dev_private;
- int c = count;
- int ret;
-
- if (dev_priv->cce_is_bm_mode) {
- int left = 0;
-
- if (c >= dev_priv->ring_entries) {
- c = dev_priv->ring_entries-1;
- left = count - c;
- }
-
- /* Since this is only used by the kernel we can use the
- insecure ring buffer submit packet routine */
- ret = r128_submit_packets_ring(dev, buffer, &c);
-
- c += left;
- } else {
- /* Since this is only used by the kernel we can use the
- insecure PIO submit packet routine */
- ret = r128_submit_packets_pio(dev, buffer, &c);
- }
-
- if (ret < 0) return ret;
- else return c;
-}
-
-int r128_submit_pkt(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_packet_t packet;
- u32 *buffer;
- int c;
- int size;
- int ret = 0;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
- dev->lock.pid != current->pid) {
- DRM_ERROR("r128_submit_pkt called without holding the lock\n");
- return -EINVAL;
- }
-
- if (copy_from_user(&packet, (drm_r128_packet_t *)arg, sizeof(packet)))
- return -EFAULT;
-
- c = packet.count;
- size = c * sizeof(*buffer);
-
- if (dev_priv->cce_is_bm_mode) {
- int left = 0;
-
- if (c >= dev_priv->ring_entries) {
- c = dev_priv->ring_entries-1;
- size = c * sizeof(*buffer);
- left = packet.count - c;
- }
-
- if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
- if (copy_from_user(buffer, packet.buffer, size))
- return -EFAULT;
-
- if (dev_priv->cce_secure)
- ret = r128_submit_packets_ring_secure(dev, buffer, &c);
- else
- ret = r128_submit_packets_ring(dev, buffer, &c);
-
- c += left;
- } else {
- if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM;
- if (copy_from_user(buffer, packet.buffer, size))
- return -EFAULT;
-
- if (dev_priv->cce_secure)
- ret = r128_submit_packets_pio_secure(dev, buffer, &c);
- else
- ret = r128_submit_packets_pio(dev, buffer, &c);
- }
-
- kfree(buffer);
-
- packet.count = c;
- if (copy_to_user((drm_r128_packet_t *)arg, &packet, sizeof(packet)))
- return -EFAULT;
-
- if (ret) return ret;
- else if (c > 0) return -EAGAIN;
-
- return 0;
-}
-
-static int r128_send_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v)
-{
- drm_device_dma_t *dma = dev->dma;
- drm_r128_private_t *dev_priv = dev->dev_private;
- drm_r128_buf_priv_t *buf_priv;
- drm_buf_t *buf;
- int i, ret;
- u32 cce[2];
-
- /* Make sure we have valid data */
- for (i = 0; i < v->send_count; i++) {
- int idx = v->send_indices[i];
-
- if (idx < 0 || idx >= dma->buf_count) {
- DRM_ERROR("Index %d (of %d max)\n",
- idx, dma->buf_count - 1);
- return -EINVAL;
- }
- buf = dma->buflist[idx];
- 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:"
- " buffer %d, offset %d\n",
- v->send_indices[i], i);
- return -EINVAL;
- }
- }
-
- /* Wait for idle, if we've wrapped to make sure that all pending
- buffers have been processed */
- if (dev_priv->submit_age == R128_MAX_VBUF_AGE) {
- if ((ret = r128_do_cce_wait_for_idle(dev)) < 0) return ret;
- dev_priv->submit_age = 0;
- r128_mark_vertbufs_done(dev);
- }
-
- /* Make sure WC cache has been flushed (if in PIO mode) */
- if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine();
-
- /* FIXME: Add support for sending vertex buffer to the CCE here
- instead of in client code. The v->prim holds the primitive
- type that should be drawn. Loop over the list buffers in
- send_indices[] and submit a packet for each VB.
-
- This will require us to loop over the clip rects here as
- well, which implies that we extend the kernel driver to allow
- cliprects to be stored here. Note that the cliprects could
- possibly come from the X server instead of the client, but
- this will require additional changes to the DRI to allow for
- this optimization. */
-
- /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */
- cce[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0);
- cce[1] = dev_priv->submit_age;
- if ((ret = r128_do_submit_packets(dev, cce, 2)) < 0) {
- /* Until we add support for sending VBs to the CCE in
- this routine, we can recover from this error. After
- we add that support, we won't be able to easily
- recover, so we will probably have to implement
- another mechanism for handling timeouts from packets
- submitted directly by the kernel. */
- return ret;
- }
-
- /* Now that the submit packet request has succeeded, we can mark
- the buffers as pending */
- for (i = 0; i < v->send_count; i++) {
- buf = dma->buflist[v->send_indices[i]];
- buf->pending = 1;
-
- buf_priv = buf->dev_private;
- buf_priv->age = dev_priv->submit_age;
- }
-
- dev_priv->submit_age++;
-
- return 0;
-}
-
-static drm_buf_t *r128_freelist_get(drm_device_t *dev)
-{
- drm_device_dma_t *dma = dev->dma;
- drm_r128_private_t *dev_priv = dev->dev_private;
- drm_r128_buf_priv_t *buf_priv;
- drm_buf_t *buf;
- int i, t;
-
- /* FIXME: Optimize -- use freelist code */
-
- for (i = 0; i < dma->buf_count; i++) {
- buf = dma->buflist[i];
- buf_priv = buf->dev_private;
- if (buf->pid == 0) return buf;
- }
-
- for (t = 0; t < dev_priv->usec_timeout; t++) {
- u32 done_age = R128_READ(R128_VB_AGE_REG);
-
- for (i = 0; i < dma->buf_count; i++) {
- buf = dma->buflist[i];
- buf_priv = buf->dev_private;
- if (buf->pending && buf_priv->age <= done_age) {
- /* The buffer has been processed, so it
- can now be used */
- buf->pending = 0;
- return buf;
- }
- }
- udelay(1);
- }
-
- r128_status(dev);
- return NULL;
-}
-
-
-static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v)
-{
- drm_buf_t *buf;
- int i;
-
- for (i = v->granted_count; i < v->request_count; i++) {
- buf = r128_freelist_get(dev);
- if (!buf) break;
- buf->pid = current->pid;
- if (copy_to_user(&v->request_indices[i],
- &buf->idx,
- sizeof(buf->idx)) ||
- copy_to_user(&v->request_sizes[i],
- &buf->total,
- sizeof(buf->total)))
- return -EFAULT;
- ++v->granted_count;
- }
- return 0;
-}
-
-int r128_vertex_buf(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;
- int retcode = 0;
- drm_r128_vertex_t v;
-
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
- dev->lock.pid != current->pid) {
- DRM_ERROR("r128_vertex_buf called without holding the lock\n");
- return -EINVAL;
- }
-
- if (!dev_priv || dev_priv->is_pci) {
- DRM_ERROR("r128_vertex_buf called with a PCI card\n");
- return -EINVAL;
- }
-
- if (copy_from_user(&v, (drm_r128_vertex_t *)arg, sizeof(v)))
- return -EFAULT;
- DRM_DEBUG("%d: %d send, %d req\n",
- current->pid, v.send_count, v.request_count);
-
- if (v.send_count < 0 || v.send_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
- current->pid, v.send_count, dma->buf_count);
- return -EINVAL;
- }
- if (v.request_count < 0 || v.request_count > dma->buf_count) {
- DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
- current->pid, v.request_count, dma->buf_count);
- return -EINVAL;
- }
-
- if (v.send_count) {
- retcode = r128_send_vertbufs(dev, &v);
- }
-
- v.granted_count = 0;
-
- if (!retcode && v.request_count) {
- retcode = r128_get_vertbufs(dev, &v);
- }
-
- DRM_DEBUG("%d returning, granted = %d\n",
- current->pid, v.granted_count);
- if (copy_to_user((drm_r128_vertex_t *)arg, &v, sizeof(v)))
- return -EFAULT;
-
- return retcode;
-}
diff --git a/linux/r128_drm.h b/linux/r128_drm.h
index 9a0ba7071..b5c7629e6 100644
--- a/linux/r128_drm.h
+++ b/linux/r128_drm.h
@@ -32,6 +32,119 @@
#define _R128_DRM_H_
/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the X server file (r128_sarea.h)
+ */
+#ifndef __R128_SAREA_DEFINES__
+#define __R128_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define R128_UPLOAD_CONTEXT 0x001
+#define R128_UPLOAD_SETUP 0x002
+#define R128_UPLOAD_TEX0 0x004
+#define R128_UPLOAD_TEX1 0x008
+#define R128_UPLOAD_TEX0IMAGES 0x010
+#define R128_UPLOAD_TEX1IMAGES 0x020
+#define R128_UPLOAD_CORE 0x040
+#define R128_UPLOAD_MASKS 0x080
+#define R128_UPLOAD_WINDOW 0x100
+#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
+#define R128_REQUIRE_QUIESCENCE 0x400
+
+#define R128_FRONT 0x1
+#define R128_BACK 0x2
+#define R128_DEPTH 0x4
+
+/* Keep these small for testing.
+ */
+#define R128_NR_SAREA_CLIPRECTS 12
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define R128_LOCAL_TEX_HEAP 0
+#define R128_AGP_TEX_HEAP 1
+#define R128_NR_TEX_HEAPS 2
+#define R128_NR_TEX_REGIONS 16
+#define R128_LOG_TEX_GRANULARITY 16
+
+#define R128_NR_CONTEXT_REGS 12
+#define R128_TEX_MAXLEVELS 11
+
+#endif /* __R128_SAREA_DEFINES__ */
+
+typedef struct {
+ /* Context state - can be written in one large chunk */
+ u32 dst_pitch_offset_c;
+ u32 dp_gui_master_cntl_c;
+ u32 sc_top_left_c;
+ u32 sc_bottom_right_c;
+ u32 z_offset_c;
+ u32 z_pitch_c;
+ u32 z_sten_cntl_c;
+ u32 tex_cntl_c;
+ u32 misc_3d_state_cntl_reg;
+ u32 texture_clr_cmp_clr_c;
+ u32 texture_clr_cmp_msk_c;
+ u32 fog_color_c;
+
+ /* Texture state */
+ u32 tex_size_pitch_c;
+ u32 constant_color_c;
+
+ /* Setup state */
+ u32 pm4_vc_fpu_setup;
+ u32 setup_cntl;
+
+ /* Mask state */
+ u32 dp_write_mask;
+ u32 sten_ref_mask_c;
+ u32 plane_3d_mask_c;
+
+ /* Window state */
+ u32 window_xy_offset;
+
+ /* Core state */
+ u32 scale_3d_cntl;
+} drm_r128_context_regs_t;
+
+/* Setup registers for each texture unit */
+typedef struct {
+ u32 tex_cntl;
+ u32 tex_combine_cntl;
+ u32 tex_size_pitch;
+ u32 tex_offset[R128_TEX_MAXLEVELS];
+ u32 tex_border_color;
+} drm_r128_texture_regs_t;
+
+
+typedef struct drm_tex_region {
+ unsigned char next, prev;
+ unsigned char in_use;
+ int age;
+} drm_tex_region_t;
+
+typedef struct drm_r128_sarea {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ drm_r128_context_regs_t context_state;
+ drm_r128_texture_regs_t tex_state[R128_NR_TEX_HEAPS];
+ unsigned int dirty;
+ unsigned int vertsize;
+ unsigned int vc_format;
+
+ drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+
+ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+ int tex_age[R128_NR_TEX_HEAPS];
+ int ctx_owner;
+ int ring_write;
+} drm_r128_sarea_t;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmR128.h)
*/
typedef struct drm_r128_init {
@@ -56,107 +169,25 @@ typedef struct drm_r128_init {
int mmio_offset;
} drm_r128_init_t;
-typedef struct drm_r128_packet {
- unsigned long *buffer;
- int count;
- int flags;
-} drm_r128_packet_t;
-
-typedef enum drm_r128_prim {
- _DRM_R128_PRIM_NONE = 0x0001,
- _DRM_R128_PRIM_POINT = 0x0002,
- _DRM_R128_PRIM_LINE = 0x0004,
- _DRM_R128_PRIM_POLY_LINE = 0x0008,
- _DRM_R128_PRIM_TRI_LIST = 0x0010,
- _DRM_R128_PRIM_TRI_FAN = 0x0020,
- _DRM_R128_PRIM_TRI_STRIP = 0x0040,
- _DRM_R128_PRIM_TRI_TYPE2 = 0x0080
-} drm_r128_prim_t;
+typedef struct drm_r128_clear {
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int flags;
+} drm_r128_clear_t;
typedef struct drm_r128_vertex {
- /* Indices here refer to the offset into
- buflist in drm_buf_get_t. */
- int send_count; /* Number of buffers to send */
- int *send_indices; /* List of handles to buffers */
- int *send_sizes; /* Lengths of data to send */
- drm_r128_prim_t prim; /* Primitive type */
- int request_count; /* Number of buffers requested */
- int *request_indices; /* Buffer information */
- int *request_sizes;
- int granted_count; /* Number of buffers granted */
+ int index; /* Index of vertex buffer */
+ int used; /* Amount of buffer used */
+ int send; /* Dispatch buffer? */
+ int discard; /* Discard buffer? */
+ int request; /* Request new buffer? */
+ int granted; /* New buffer granted? */
} drm_r128_vertex_t;
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (r128_sarea.h)
- */
-#define R128_LOCAL_TEX_HEAP 0
-#define R128_AGP_TEX_HEAP 1
-#define R128_NR_TEX_HEAPS 2
-#define R128_NR_TEX_REGIONS 64
-#define R128_LOG_TEX_GRANULARITY 16
-
-typedef struct drm_tex_region {
- unsigned char next, prev;
- unsigned char in_use;
- int age;
-} drm_tex_region_t;
-
-typedef struct drm_r128_sarea {
- drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
- int tex_age[R128_NR_TEX_HEAPS];
- int ctx_owner;
- int ring_write;
-} drm_r128_sarea_t;
-
-
-/* GH: These typedefs are taken from my latest kernel module work, and
- * needed for the client-side 3D driver. They will go away (along with
- * most of the rest of the current kernel module).
- */
-#define R128_TEX_MAXLEVELS 11
-
-typedef struct {
- /* Context state - can be written in one large chunk */
- unsigned long dst_pitch_offset_c;
- unsigned long dp_gui_master_cntl_c;
- unsigned long sc_top_left_c;
- unsigned long sc_bottom_right_c;
- unsigned long z_offset_c;
- unsigned long z_pitch_c;
- unsigned long z_sten_cntl_c;
- unsigned long tex_cntl_c;
- unsigned long misc_3d_state_cntl_reg;
- unsigned long texture_clr_cmp_clr_c;
- unsigned long texture_clr_cmp_msk_c;
- unsigned long fog_color_c;
-
- /* Setup state */
- unsigned long pm4_vc_fpu_setup;
- unsigned long setup_cntl;
-
- /* Texture state */
- unsigned long tex_size_pitch_c;
- unsigned long constant_color_c;
-
- /* Mask state */
- unsigned long dp_write_mask;
- unsigned long sten_ref_mask_c;
- unsigned long plane_3d_mask_c;
-
- /* Window state */
- unsigned long window_xy_offset;
-
- /* Core state */
- unsigned long scale_3d_cntl;
-} drm_r128_context_regs_t;
-
-/* Setup registers for each texture unit */
-typedef struct {
- unsigned long tex_cntl;
- unsigned long tex_combine_cntl;
- unsigned long tex_size_pitch;
- unsigned long tex_offset[R128_TEX_MAXLEVELS];
- unsigned long tex_border_color;
-} drm_r128_texture_regs_t;
+typedef struct drm_r128_packet {
+ u32 *buffer;
+ int count;
+ int flags;
+} drm_r128_packet_t;
#endif
diff --git a/linux/r128_drv.c b/linux/r128_drv.c
index b58dcf066..6393812e2 100644
--- a/linux/r128_drv.c
+++ b/linux/r128_drv.c
@@ -33,15 +33,15 @@
#include "drmP.h"
#include "r128_drv.h"
-#define R128_NAME "r128"
-#define R128_DESC "ATI Rage 128"
-#define R128_DATE "20000910"
-#define R128_MAJOR 1
-#define R128_MINOR 0
-#define R128_PATCHLEVEL 0
+#define R128_NAME "r128"
+#define R128_DESC "ATI Rage 128"
+#define R128_DATE "20000905"
+#define R128_MAJOR 1
+#define R128_MINOR 1
+#define R128_PATCHLEVEL 0
-static drm_device_t r128_device;
-drm_ctx_t r128_res_ctx;
+static drm_device_t r128_device;
+drm_ctx_t r128_res_ctx;
static struct file_operations r128_fops = {
#if LINUX_VERSION_CODE >= 0x020400
@@ -108,9 +108,9 @@ static drm_ioctl_desc_t r128_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_R128_IDLE)] = { r128_cce_idle, 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 },
};
#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
@@ -425,13 +425,13 @@ int r128_version(struct inode *inode, struct file *filp, unsigned int cmd,
sizeof(version)))
return -EFAULT;
-#define DRM_COPY(name,value) \
- len = strlen(value); \
- if (len > name##_len) len = name##_len; \
- name##_len = strlen(value); \
- if (len && name) { \
- if (copy_to_user(name, value, len)) \
- return -EFAULT; \
+#define DRM_COPY(name,value) \
+ len = strlen(value); \
+ if (len > name##_len) len = name##_len; \
+ name##_len = strlen(value); \
+ if (len && name) { \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
}
version.version_major = R128_MAJOR;
@@ -666,6 +666,7 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd,
dev->sigdata.context = lock.context;
dev->sigdata.lock = dev->lock.hw_lock;
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_READY) {
/* Wait for space in DMA/FIFO */
}
@@ -730,6 +731,7 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
current->priority = DEF_PRIORITY;
}
#endif
+
unblock_all_signals();
return 0;
}
diff --git a/linux/r128_drv.h b/linux/r128_drv.h
index 5b15dddfb..9083af3a5 100644
--- a/linux/r128_drv.h
+++ b/linux/r128_drv.h
@@ -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>
* Kevin E. Martin <martin@valinux.com>
*
@@ -32,40 +32,67 @@
#ifndef _R128_DRV_H_
#define _R128_DRV_H_
-typedef struct drm_r128_private {
- int is_pci;
-
- int cce_mode;
- int cce_fifo_size;
- int cce_is_bm_mode;
- int cce_secure;
-
- drm_r128_sarea_t *sarea_priv;
+typedef struct drm_r128_freelist {
+ unsigned int age;
+ drm_buf_t *buf;
+ struct drm_r128_freelist *next;
+ struct drm_r128_freelist *prev;
+} drm_r128_freelist_t;
- __volatile__ u32 *ring_read_ptr;
+typedef struct drm_r128_ring_buffer {
+ __volatile__ u32 *read_ptr;
- u32 *ring_start;
- u32 *ring_end;
- int ring_size;
- int ring_sizel2qw;
- int ring_entries;
+ u32 start;
+ u32 end;
+ int size;
+ int size_l2qw;
+ u32 *virtual_start;
- int submit_age;
+ int head;
+ int tail;
+ u32 tail_mask;
+ int space;
+} drm_r128_ring_buffer_t;
- int usec_timeout;
+typedef struct drm_r128_private {
+ __volatile__ u32 *ring_read_ptr;
+ drm_r128_sarea_t *sarea_priv;
- drm_map_t *sarea;
- drm_map_t *fb;
- drm_map_t *agp_ring;
- drm_map_t *agp_read_ptr;
- drm_map_t *agp_vertbufs;
- drm_map_t *agp_indbufs;
- drm_map_t *agp_textures;
- drm_map_t *mmio;
+ u32 *ring_start;
+ u32 *ring_end;
+ int ring_size;
+ int ring_sizel2qw;
+ int ring_entries;
+
+ int cce_mode;
+ int cce_fifo_size;
+ int cce_is_bm_mode;
+ int cce_secure;
+ u32 *cce_buffer;
+
+ drm_r128_freelist_t *head;
+ drm_r128_freelist_t *tail;
+
+ unsigned int submit_age;
+
+ int usec_timeout;
+ int is_pci;
+
+ drm_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *agp_ring;
+ drm_map_t *agp_read_ptr;
+ drm_map_t *agp_vertbufs;
+ drm_map_t *agp_indbufs;
+ drm_map_t *agp_textures;
+ drm_map_t *mmio;
} drm_r128_private_t;
typedef struct drm_r128_buf_priv {
- u32 age;
+ u32 age;
+ int discard;
+ int dispatched;
+ drm_r128_freelist_t *my_freelist;
} drm_r128_buf_priv_t;
/* r128_drv.c */
@@ -87,11 +114,19 @@ extern int r128_eng_reset(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int r128_eng_flush(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int r128_submit_pkt(struct inode *inode, struct file *filp,
+extern int r128_cce_packet(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int r128_cce_idle(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int r128_vertex_buf(struct inode *inode, struct file *filp,
+
+extern void r128_flush_write_combine( void );
+extern int r128_do_wait_for_idle( drm_r128_private_t *dev_priv );
+extern int r128_do_submit_packet( drm_r128_private_t *dev_priv,
+ u32 *buffer, int count );
+extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
+
+ /* r128_state.c */
+extern int r128_cce_vertex(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* r128_bufs.c */
@@ -124,78 +159,138 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new);
* for Rage 128 kernel driver.
*/
-#define R128_PC_NGUI_CTLSTAT 0x0184
-# define R128_PC_FLUSH_ALL 0x00ff
-# define R128_PC_BUSY (1 << 31)
-
-#define R128_CLOCK_CNTL_INDEX 0x0008
-#define R128_CLOCK_CNTL_DATA 0x000c
-# define R128_PLL_WR_EN (1 << 7)
-
-#define R128_MCLK_CNTL 0x000f
-# define R128_FORCE_GCP (1 << 16)
-# define R128_FORCE_PIPE3D_CP (1 << 17)
-# define R128_FORCE_RCP (1 << 18)
-
-#define R128_GEN_RESET_CNTL 0x00f0
-# define R128_SOFT_RESET_GUI (1 << 0)
-
-#define R128_PM4_BUFFER_CNTL 0x0704
-# define R128_PM4_NONPM4 (0 << 28)
-# define R128_PM4_192PIO (1 << 28)
-# define R128_PM4_192BM (2 << 28)
-# define R128_PM4_128PIO_64INDBM (3 << 28)
-# define R128_PM4_128BM_64INDBM (4 << 28)
-# define R128_PM4_64PIO_128INDBM (5 << 28)
-# define R128_PM4_64BM_128INDBM (6 << 28)
-# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
-# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
-# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
-
-
-#define R128_PM4_BUFFER_DL_RPTR 0x0710
-#define R128_PM4_BUFFER_DL_WPTR 0x0714
-# define R128_PM4_BUFFER_DL_DONE (1 << 31)
-
-#define R128_PM4_VC_FPU_SETUP 0x071c
-
-#define R128_PM4_STAT 0x07b8
-# define R128_PM4_FIFOCNT_MASK 0x0fff
-# define R128_PM4_BUSY (1 << 16)
-# define R128_PM4_GUI_ACTIVE (1 << 31)
-
-#define R128_PM4_BUFFER_ADDR 0x07f0
-#define R128_PM4_MICRO_CNTL 0x07fc
-# define R128_PM4_MICRO_FREERUN (1 << 30)
-
-#define R128_PM4_FIFO_DATA_EVEN 0x1000
-#define R128_PM4_FIFO_DATA_ODD 0x1004
-
-#define R128_GUI_SCRATCH_REG0 0x15e0
-#define R128_GUI_SCRATCH_REG1 0x15e4
-#define R128_GUI_SCRATCH_REG2 0x15e8
-#define R128_GUI_SCRATCH_REG3 0x15ec
-#define R128_GUI_SCRATCH_REG4 0x15f0
-#define R128_GUI_SCRATCH_REG5 0x15f4
-
-#define R128_GUI_STAT 0x1740
-# define R128_GUI_FIFOCNT_MASK 0x0fff
-# define R128_GUI_ACTIVE (1 << 31)
-
-
-/* CCE command packets */
-#define R128_CCE_PACKET0 0x00000000
-#define R128_CCE_PACKET1 0x40000000
-#define R128_CCE_PACKET2 0x80000000
-# define R128_CCE_PACKET_MASK 0xC0000000
-# define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
-# define R128_CCE_PACKET0_REG_MASK 0x000007ff
-# define R128_CCE_PACKET1_REG0_MASK 0x000007ff
-# define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+#define R128_AUX_SC_CNTL 0x1660
+# define R128_AUX1_SC_EN (1 << 0)
+# define R128_AUX1_SC_MODE_OR (0 << 1)
+# define R128_AUX1_SC_MODE_NAND (1 << 1)
+# define R128_AUX2_SC_EN (1 << 2)
+# define R128_AUX2_SC_MODE_OR (0 << 3)
+# define R128_AUX2_SC_MODE_NAND (1 << 3)
+# define R128_AUX3_SC_EN (1 << 4)
+# define R128_AUX3_SC_MODE_OR (0 << 5)
+# define R128_AUX3_SC_MODE_NAND (1 << 5)
+#define R128_AUX1_SC_LEFT 0x1664
+#define R128_AUX1_SC_RIGHT 0x1668
+#define R128_AUX1_SC_TOP 0x166c
+#define R128_AUX1_SC_BOTTOM 0x1670
+#define R128_AUX2_SC_LEFT 0x1674
+#define R128_AUX2_SC_RIGHT 0x1678
+#define R128_AUX2_SC_TOP 0x167c
+#define R128_AUX2_SC_BOTTOM 0x1680
+#define R128_AUX3_SC_LEFT 0x1684
+#define R128_AUX3_SC_RIGHT 0x1688
+#define R128_AUX3_SC_TOP 0x168c
+#define R128_AUX3_SC_BOTTOM 0x1690
+
+#define R128_CLOCK_CNTL_INDEX 0x0008
+#define R128_CLOCK_CNTL_DATA 0x000c
+# define R128_PLL_WR_EN (1 << 7)
+
+#define R128_CONSTANT_COLOR_C 0x1d34
+
+#define R128_DP_WRITE_MASK 0x16cc
+#define R128_DST_PITCH_OFFSET_C 0x1c80
+
+#define R128_GEN_RESET_CNTL 0x00f0
+# define R128_SOFT_RESET_GUI (1 << 0)
+
+#define R128_GUI_SCRATCH_REG0 0x15e0
+#define R128_GUI_SCRATCH_REG1 0x15e4
+#define R128_GUI_SCRATCH_REG2 0x15e8
+#define R128_GUI_SCRATCH_REG3 0x15ec
+#define R128_GUI_SCRATCH_REG4 0x15f0
+#define R128_GUI_SCRATCH_REG5 0x15f4
+
+#define R128_GUI_STAT 0x1740
+# define R128_GUI_FIFOCNT_MASK 0x0fff
+# define R128_GUI_ACTIVE (1 << 31)
+
+#define R128_MCLK_CNTL 0x000f
+# define R128_FORCE_GCP (1 << 16)
+# define R128_FORCE_PIPE3D_CP (1 << 17)
+# define R128_FORCE_RCP (1 << 18)
+
+#define R128_PC_NGUI_CTLSTAT 0x0184
+# define R128_PC_FLUSH_ALL 0x00ff
+# define R128_PC_BUSY (1 << 31)
+
+#define R128_PM4_BUFFER_CNTL 0x0704
+# define R128_PM4_NONPM4 (0 << 28)
+# define R128_PM4_192PIO (1 << 28)
+# define R128_PM4_192BM (2 << 28)
+# define R128_PM4_128PIO_64INDBM (3 << 28)
+# define R128_PM4_128BM_64INDBM (4 << 28)
+# define R128_PM4_64PIO_128INDBM (5 << 28)
+# define R128_PM4_64BM_128INDBM (6 << 28)
+# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
+# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
+# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+
+#define R128_PM4_BUFFER_DL_RPTR 0x0710
+#define R128_PM4_BUFFER_DL_WPTR 0x0714
+# define R128_PM4_BUFFER_DL_DONE (1 << 31)
+
+#define R128_PM4_VC_FPU_SETUP 0x071c
+
+#define R128_PM4_STAT 0x07b8
+# define R128_PM4_FIFOCNT_MASK 0x0fff
+# define R128_PM4_BUSY (1 << 16)
+# define R128_PM4_GUI_ACTIVE (1 << 31)
+
+#define R128_PM4_BUFFER_ADDR 0x07f0
+#define R128_PM4_MICRO_CNTL 0x07fc
+# define R128_PM4_MICRO_FREERUN (1 << 30)
+
+#define R128_PM4_FIFO_DATA_EVEN 0x1000
+#define R128_PM4_FIFO_DATA_ODD 0x1004
+
+#define R128_PRIM_TEX_CNTL_C 0x1cb0
+
+#define R128_SCALE_3D_CNTL 0x1a00
+#define R128_SEC_TEX_CNTL_C 0x1d00
+#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
+#define R128_SETUP_CNTL 0x1bc4
+#define R128_STEN_REF_MASK_C 0x1d40
+
+#define R128_TEX_CNTL_C 0x1c9c
+# define R128_TEX_CACHE_FLUSH (1 << 23)
+
+#define R128_WINDOW_XY_OFFSET 0x1bcc
+
+
+/* CCE command packets
+ */
+#define R128_CCE_PACKET0 0x00000000
+#define R128_CCE_PACKET1 0x40000000
+#define R128_CCE_PACKET2 0x80000000
+#define R128_CCE_PACKET3 0xC0000000
+# define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300
+
+#define R128_CCE_PACKET_MASK 0xC0000000
+#define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
+#define R128_CCE_PACKET0_REG_MASK 0x000007ff
+#define R128_CCE_PACKET1_REG0_MASK 0x000007ff
+#define R128_CCE_PACKET1_REG1_MASK 0x003ff800
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT 16
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+#define R128_MAX_VB_AGE 0xffffffff
+#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0
+
#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
#define R128_ADDR(reg) (R128_BASE(reg) + reg)
@@ -221,4 +316,89 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr);
#define R128CCE2(p) ((p))
#define R128CCE3(p,n) ((p) | ((n) << 16))
+
+
+
+#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
+ ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
+ (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2() (R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
+ (pkt) | ((n) << 16))
+
+
+#define R128_VERBOSE 0
+
+#if 0
+
+#define RING_LOCALS unsigned long outring, ringmask; volatile u32 *virt;
+
+#define BEGIN_RING( n ) do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( "BEGIN_RING( %d ) in %s\n", \
+ n, __FUNCTION__ ); \
+ } \
+ if ( dev_priv->ring.space < n * sizeof(u32) ) { \
+ r128_wait_ring( dev_priv, n * sizeof(u32) ); \
+ } \
+ dev_priv->ring.space -= n * sizeof(u32); \
+ outring = dev_priv->ring.tail; \
+ ringmask = dev_priv->ring.tail_mask; \
+ virt = dev_priv->->ring.virtual_start; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( "ADVANCE_RING()\n" ); \
+ } \
+ dev_priv->sarea_priv->ring_write = write;
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
+ __ret = r128_do_submit_packet( dev_priv, buffer, outring ); \
+ if ( __ret < 0 ) { \
+ DRM_ERROR( "ADVANCE_RING fucked up!\n" ); \
+ } \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( " OUT_RING( 0x%08x )\n", \
+ (unsigned int)(x) ); \
+ } \
+ buffer[outring++] = x; \
+} while (0)
+
+#else
+
+#define RING_LOCALS unsigned long outring; u32 *buffer; int __ret;
+
+#define BEGIN_RING( n ) do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( "BEGIN_RING( %d ) in %s\n", \
+ n, __FUNCTION__ ); \
+ } \
+ outring = 0; \
+ buffer = dev_priv->cce_buffer; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( "ADVANCE_RING()\n" ); \
+ } \
+ __ret = r128_do_submit_packet( dev_priv, buffer, outring ); \
+ if ( __ret < 0 ) { \
+ DRM_ERROR( "ADVANCE_RING fucked up!\n" ); \
+ } \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( R128_VERBOSE ) { \
+ DRM_DEBUG( " OUT_RING( 0x%08x )\n", \
+ (unsigned int)(x) ); \
+ } \
+ buffer[outring++] = x; \
+} while (0)
+
+#endif
+
#endif
diff --git a/linux/r128_state.c b/linux/r128_state.c
new file mode 100644
index 000000000..124d9938e
--- /dev/null
+++ b/linux/r128_state.c
@@ -0,0 +1,464 @@
+/* r128_state.c -- State support for r128 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * 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: Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "r128_drv.h"
+#include "drm.h"
+
+
+/* ================================================================
+ * CCE hardware state programming functions
+ */
+
+static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
+ drm_clip_rect_t *boxes, int count )
+{
+ unsigned int aux_sc_cntl = 0x00000000;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 17 );
+
+ if ( count >= 1 ) {
+ OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
+ OUT_RING( boxes[0].x1 );
+ OUT_RING( boxes[0].x2 - 1 );
+ OUT_RING( boxes[0].y1 );
+ OUT_RING( boxes[0].y2 - 1 );
+
+ 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 );
+ OUT_RING( boxes[1].x2 - 1 );
+ OUT_RING( boxes[1].y1 );
+ OUT_RING( boxes[1].y2 - 1 );
+
+ aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
+ }
+ if ( count >= 3 ) {
+ OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
+ OUT_RING( boxes[2].x1 );
+ OUT_RING( boxes[2].x2 - 1 );
+ OUT_RING( boxes[2].y1 );
+ OUT_RING( boxes[2].y2 - 1 );
+
+ aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
+ }
+
+ OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
+ OUT_RING( aux_sc_cntl );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_core( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
+ OUT_RING( ctx->scale_3d_cntl );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_context( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 13 );
+
+ OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
+ OUT_RING( ctx->dst_pitch_offset_c );
+ OUT_RING( ctx->dp_gui_master_cntl_c );
+ OUT_RING( ctx->sc_top_left_c );
+ OUT_RING( ctx->sc_bottom_right_c );
+ OUT_RING( ctx->z_offset_c );
+ OUT_RING( ctx->z_pitch_c );
+ OUT_RING( ctx->z_sten_cntl_c );
+ OUT_RING( ctx->tex_cntl_c );
+ OUT_RING( ctx->misc_3d_state_cntl_reg );
+ OUT_RING( ctx->texture_clr_cmp_clr_c );
+ OUT_RING( ctx->texture_clr_cmp_msk_c );
+ OUT_RING( ctx->fog_color_c );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_setup( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 3 );
+
+ OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
+ OUT_RING( ctx->setup_cntl );
+ OUT_RING( ctx->pm4_vc_fpu_setup );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_masks( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
+ OUT_RING( ctx->dp_write_mask );
+
+ OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
+ OUT_RING( ctx->sten_ref_mask_c );
+ OUT_RING( ctx->plane_3d_mask_c );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_window( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
+ OUT_RING( ctx->window_xy_offset );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_tex0( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 3 );
+
+ OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
+ 2 + R128_TEX_MAXLEVELS ) );
+ OUT_RING( tex->tex_cntl );
+ OUT_RING( tex->tex_combine_cntl );
+ OUT_RING( ctx->tex_size_pitch_c );
+ for ( i = 0 ; i < R128_TEX_MAXLEVELS ; i++ ) {
+ OUT_RING( tex->tex_offset[i] );
+ }
+
+ OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
+ OUT_RING( ctx->constant_color_c );
+ OUT_RING( tex->tex_border_color );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_tex1( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 3 );
+
+ OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
+ 1 + R128_TEX_MAXLEVELS ) );
+ OUT_RING( tex->tex_cntl );
+ OUT_RING( tex->tex_combine_cntl );
+ for ( i = 0 ; i < R128_TEX_MAXLEVELS ; i++ ) {
+ OUT_RING( tex->tex_offset[i] );
+ }
+
+ OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
+ OUT_RING( tex->tex_border_color );
+
+ ADVANCE_RING();
+}
+
+static inline void r128_emit_state( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+
+ if ( dirty & R128_UPLOAD_CORE ) {
+ r128_emit_core( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_CORE;
+ }
+
+ if ( dirty & R128_UPLOAD_CONTEXT ) {
+ r128_emit_context( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & R128_UPLOAD_SETUP ) {
+ r128_emit_setup( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
+ }
+
+ if ( dirty & R128_UPLOAD_MASKS ) {
+ r128_emit_masks( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
+ }
+
+ if ( dirty & R128_UPLOAD_WINDOW ) {
+ r128_emit_window( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
+ }
+
+ if ( dirty & R128_UPLOAD_TEX0 ) {
+ r128_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
+ }
+
+ if ( dirty & R128_UPLOAD_TEX1 ) {
+ r128_emit_tex1( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
+ }
+
+ /* Turn off the texture cache flushing */
+ sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+}
+
+
+/* ================================================================
+ * CCE command dispatch functions
+ */
+
+static void r128_cce_dispatch_swap( drm_device_t *dev )
+{
+
+}
+
+static void r128_cce_dispatch_clear( drm_device_t *dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_depth )
+{
+
+}
+
+static void r128_cce_dispatch_vertex( drm_device_t *dev,
+ drm_buf_t *buf )
+{
+ 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->agp_vertbufs->offset
+ + buf->offset - dev->agp->base;
+ int size = buf->used / (vertsize * sizeof(u32));
+ int prim;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ DRM_DEBUG( "vertex buffer index = %d\n", index );
+ DRM_DEBUG( "vertex buffer offset = 0x%x\n", offset );
+ DRM_DEBUG( "vertex buffer size = %d bytes\n", size );
+ DRM_DEBUG( "vertex size = %d\n", vertsize );
+ DRM_DEBUG( "vertex format = 0x%x\n", format );
+
+ prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST;
+
+ if ( buf->used ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+ r128_emit_state( dev_priv );
+ }
+
+ 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 );
+ }
+
+ /* Emit the vertex buffer rendering commands */
+ BEGIN_RING( 5 );
+
+ OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+ OUT_RING( offset );
+ OUT_RING( size );
+ OUT_RING( format );
+ OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+ (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
+
+ ADVANCE_RING();
+
+ i += 3;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_VB_AGE_REG, 0 ) );
+ OUT_RING( dev_priv->submit_age );
+
+ ADVANCE_RING();
+
+ buf->pending = 1;
+
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ buf_priv->age = dev_priv->submit_age;
+ }
+
+ dev_priv->submit_age++;
+
+#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_get_vertex_buffer( drm_device_t *dev, drm_r128_vertex_t *v )
+{
+ drm_buf_t *buf;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ buf = r128_freelist_get( dev );
+ if ( !buf ) return;
+
+ buf->pid = current->pid;
+
+ v->index = buf->idx;
+ v->granted = 1;
+}
+
+int r128_cce_vertex( 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_vertex_t vertex;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "r128_cce_vertex called without lock held\n" );
+ return -EINVAL;
+ }
+ if ( !dev_priv || dev_priv->is_pci ) {
+ DRM_ERROR( "r128_cce_vertex called with a PCI card\n" );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg,
+ sizeof(vertex) ) )
+ return -EFAULT;
+ DRM_DEBUG( "%d: index=%d used=%d flags=%s%s%s\n",
+ current->pid, vertex.index, vertex.used,
+ ( vertex.send ) ? "S" : ".",
+ ( vertex.discard ) ? "D" : ".",
+ ( vertex.request ) ? "R" : "." );
+
+ /* You can send us buffers.
+ */
+ if ( vertex.send || vertex.discard ) {
+ if ( vertex.index < 0 || vertex.index >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ vertex.index, dma->buf_count - 1 );
+ return -EINVAL;
+ }
+
+ buf = dma->buflist[vertex.index];
+ 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",
+ vertex.index );
+ return -EINVAL;
+ }
+
+ buf->used = vertex.used;
+ buf_priv->discard = vertex.discard;
+
+ r128_cce_dispatch_vertex( dev, buf );
+ }
+
+ /* And we'll give you new ones too.
+ */
+ if ( vertex.request ) {
+ r128_get_vertex_buffer( dev, &vertex );
+ }
+
+ DRM_DEBUG( "%d: returning, index=%d\n", current->pid, vertex.index );
+ if ( copy_to_user( (drm_r128_vertex_t *)arg, &vertex,
+ sizeof(vertex) ) )
+ return -EFAULT;
+
+ return 0;
+}