mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-11 07:18:08 +02:00
Somewhat unstable development work. Use at your own risk.
This commit is contained in:
parent
83253109dc
commit
cc57f63b8f
12 changed files with 1902 additions and 1172 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(¤t->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(¤t->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;
|
||||
|
|
|
|||
970
linux/r128_cce.c
Normal file
970
linux/r128_cce.c
Normal file
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
909
linux/r128_dma.c
909
linux/r128_dma.c
|
|
@ -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;
|
||||
}
|
||||
227
linux/r128_drm.h
227
linux/r128_drm.h
|
|
@ -31,6 +31,119 @@
|
|||
#ifndef _R128_DRM_H_
|
||||
#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)
|
||||
*/
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
358
linux/r128_drv.h
358
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_freelist {
|
||||
unsigned int age;
|
||||
drm_buf_t *buf;
|
||||
struct drm_r128_freelist *next;
|
||||
struct drm_r128_freelist *prev;
|
||||
} drm_r128_freelist_t;
|
||||
|
||||
typedef struct drm_r128_ring_buffer {
|
||||
__volatile__ u32 *read_ptr;
|
||||
|
||||
u32 start;
|
||||
u32 end;
|
||||
int size;
|
||||
int size_l2qw;
|
||||
u32 *virtual_start;
|
||||
|
||||
int head;
|
||||
int tail;
|
||||
u32 tail_mask;
|
||||
int space;
|
||||
} drm_r128_ring_buffer_t;
|
||||
|
||||
typedef struct drm_r128_private {
|
||||
int is_pci;
|
||||
|
||||
int cce_mode;
|
||||
int cce_fifo_size;
|
||||
int cce_is_bm_mode;
|
||||
int cce_secure;
|
||||
|
||||
__volatile__ u32 *ring_read_ptr;
|
||||
drm_r128_sarea_t *sarea_priv;
|
||||
|
||||
__volatile__ u32 *ring_read_ptr;
|
||||
u32 *ring_start;
|
||||
u32 *ring_end;
|
||||
int ring_size;
|
||||
int ring_sizel2qw;
|
||||
int ring_entries;
|
||||
|
||||
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;
|
||||
|
||||
int submit_age;
|
||||
drm_r128_freelist_t *head;
|
||||
drm_r128_freelist_t *tail;
|
||||
|
||||
int usec_timeout;
|
||||
unsigned int submit_age;
|
||||
|
||||
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;
|
||||
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_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_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_CONSTANT_COLOR_C 0x1d34
|
||||
|
||||
#define R128_GEN_RESET_CNTL 0x00f0
|
||||
# define R128_SOFT_RESET_GUI (1 << 0)
|
||||
#define R128_DP_WRITE_MASK 0x16cc
|
||||
#define R128_DST_PITCH_OFFSET_C 0x1c80
|
||||
|
||||
#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_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
|
||||
|
||||
|
||||
#define R128_PM4_BUFFER_DL_RPTR 0x0710
|
||||
#define R128_PM4_BUFFER_DL_WPTR 0x0714
|
||||
# define R128_PM4_BUFFER_DL_DONE (1 << 31)
|
||||
/* 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_PM4_VC_FPU_SETUP 0x071c
|
||||
#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_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_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
|
||||
|
|
|
|||
464
linux/r128_state.c
Normal file
464
linux/r128_state.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue